deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / src / x87 / code-stubs-x87.cc
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/v8.h"
6
7 #if V8_TARGET_ARCH_X87
8
9 #include "src/base/bits.h"
10 #include "src/bootstrapper.h"
11 #include "src/code-stubs.h"
12 #include "src/codegen.h"
13 #include "src/ic/handler-compiler.h"
14 #include "src/ic/ic.h"
15 #include "src/ic/stub-cache.h"
16 #include "src/isolate.h"
17 #include "src/jsregexp.h"
18 #include "src/regexp-macro-assembler.h"
19 #include "src/runtime/runtime.h"
20
21 namespace v8 {
22 namespace internal {
23
24
25 static void InitializeArrayConstructorDescriptor(
26     Isolate* isolate, CodeStubDescriptor* descriptor,
27     int constant_stack_parameter_count) {
28   // register state
29   // eax -- number of arguments
30   // edi -- function
31   // ebx -- allocation site with elements kind
32   Address deopt_handler = Runtime::FunctionForId(
33       Runtime::kArrayConstructor)->entry;
34
35   if (constant_stack_parameter_count == 0) {
36     descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
37                            JS_FUNCTION_STUB_MODE);
38   } else {
39     descriptor->Initialize(eax, deopt_handler, constant_stack_parameter_count,
40                            JS_FUNCTION_STUB_MODE, PASS_ARGUMENTS);
41   }
42 }
43
44
45 static void InitializeInternalArrayConstructorDescriptor(
46     Isolate* isolate, CodeStubDescriptor* descriptor,
47     int constant_stack_parameter_count) {
48   // register state
49   // eax -- number of arguments
50   // edi -- constructor function
51   Address deopt_handler = Runtime::FunctionForId(
52       Runtime::kInternalArrayConstructor)->entry;
53
54   if (constant_stack_parameter_count == 0) {
55     descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
56                            JS_FUNCTION_STUB_MODE);
57   } else {
58     descriptor->Initialize(eax, deopt_handler, constant_stack_parameter_count,
59                            JS_FUNCTION_STUB_MODE, PASS_ARGUMENTS);
60   }
61 }
62
63
64 void ArrayNoArgumentConstructorStub::InitializeDescriptor(
65     CodeStubDescriptor* descriptor) {
66   InitializeArrayConstructorDescriptor(isolate(), descriptor, 0);
67 }
68
69
70 void ArraySingleArgumentConstructorStub::InitializeDescriptor(
71     CodeStubDescriptor* descriptor) {
72   InitializeArrayConstructorDescriptor(isolate(), descriptor, 1);
73 }
74
75
76 void ArrayNArgumentsConstructorStub::InitializeDescriptor(
77     CodeStubDescriptor* descriptor) {
78   InitializeArrayConstructorDescriptor(isolate(), descriptor, -1);
79 }
80
81
82 void InternalArrayNoArgumentConstructorStub::InitializeDescriptor(
83     CodeStubDescriptor* descriptor) {
84   InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 0);
85 }
86
87
88 void InternalArraySingleArgumentConstructorStub::InitializeDescriptor(
89     CodeStubDescriptor* descriptor) {
90   InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 1);
91 }
92
93
94 void InternalArrayNArgumentsConstructorStub::InitializeDescriptor(
95     CodeStubDescriptor* descriptor) {
96   InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, -1);
97 }
98
99
100 #define __ ACCESS_MASM(masm)
101
102
103 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm,
104                                                ExternalReference miss) {
105   // Update the static counter each time a new code stub is generated.
106   isolate()->counters()->code_stubs()->Increment();
107
108   CallInterfaceDescriptor descriptor = GetCallInterfaceDescriptor();
109   int param_count = descriptor.GetEnvironmentParameterCount();
110   {
111     // Call the runtime system in a fresh internal frame.
112     FrameScope scope(masm, StackFrame::INTERNAL);
113     DCHECK(param_count == 0 ||
114            eax.is(descriptor.GetEnvironmentParameterRegister(param_count - 1)));
115     // Push arguments
116     for (int i = 0; i < param_count; ++i) {
117       __ push(descriptor.GetEnvironmentParameterRegister(i));
118     }
119     __ CallExternalReference(miss, param_count);
120   }
121
122   __ ret(0);
123 }
124
125
126 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
127   // We don't allow a GC during a store buffer overflow so there is no need to
128   // store the registers in any particular way, but we do have to store and
129   // restore them.
130   __ pushad();
131   if (save_doubles()) {
132     // Save FPU stat in m108byte.
133     __ sub(esp, Immediate(108));
134     __ fnsave(Operand(esp, 0));
135   }
136   const int argument_count = 1;
137
138   AllowExternalCallThatCantCauseGC scope(masm);
139   __ PrepareCallCFunction(argument_count, ecx);
140   __ mov(Operand(esp, 0 * kPointerSize),
141          Immediate(ExternalReference::isolate_address(isolate())));
142   __ CallCFunction(
143       ExternalReference::store_buffer_overflow_function(isolate()),
144       argument_count);
145   if (save_doubles()) {
146     // Restore FPU stat in m108byte.
147     __ frstor(Operand(esp, 0));
148     __ add(esp, Immediate(108));
149   }
150   __ popad();
151   __ ret(0);
152 }
153
154
155 class FloatingPointHelper : public AllStatic {
156  public:
157   enum ArgLocation {
158     ARGS_ON_STACK,
159     ARGS_IN_REGISTERS
160   };
161
162   // Code pattern for loading a floating point value. Input value must
163   // be either a smi or a heap number object (fp value). Requirements:
164   // operand in register number. Returns operand as floating point number
165   // on FPU stack.
166   static void LoadFloatOperand(MacroAssembler* masm, Register number);
167
168   // Test if operands are smi or number objects (fp). Requirements:
169   // operand_1 in eax, operand_2 in edx; falls through on float
170   // operands, jumps to the non_float label otherwise.
171   static void CheckFloatOperands(MacroAssembler* masm,
172                                  Label* non_float,
173                                  Register scratch);
174 };
175
176
177 void DoubleToIStub::Generate(MacroAssembler* masm) {
178   Register input_reg = this->source();
179   Register final_result_reg = this->destination();
180   DCHECK(is_truncating());
181
182   Label check_negative, process_64_bits, done, done_no_stash;
183
184   int double_offset = offset();
185
186   // Account for return address and saved regs if input is esp.
187   if (input_reg.is(esp)) double_offset += 3 * kPointerSize;
188
189   MemOperand mantissa_operand(MemOperand(input_reg, double_offset));
190   MemOperand exponent_operand(MemOperand(input_reg,
191                                          double_offset + kDoubleSize / 2));
192
193   Register scratch1;
194   {
195     Register scratch_candidates[3] = { ebx, edx, edi };
196     for (int i = 0; i < 3; i++) {
197       scratch1 = scratch_candidates[i];
198       if (!final_result_reg.is(scratch1) && !input_reg.is(scratch1)) break;
199     }
200   }
201   // Since we must use ecx for shifts below, use some other register (eax)
202   // to calculate the result if ecx is the requested return register.
203   Register result_reg = final_result_reg.is(ecx) ? eax : final_result_reg;
204   // Save ecx if it isn't the return register and therefore volatile, or if it
205   // is the return register, then save the temp register we use in its stead for
206   // the result.
207   Register save_reg = final_result_reg.is(ecx) ? eax : ecx;
208   __ push(scratch1);
209   __ push(save_reg);
210
211   bool stash_exponent_copy = !input_reg.is(esp);
212   __ mov(scratch1, mantissa_operand);
213   __ mov(ecx, exponent_operand);
214   if (stash_exponent_copy) __ push(ecx);
215
216   __ and_(ecx, HeapNumber::kExponentMask);
217   __ shr(ecx, HeapNumber::kExponentShift);
218   __ lea(result_reg, MemOperand(ecx, -HeapNumber::kExponentBias));
219   __ cmp(result_reg, Immediate(HeapNumber::kMantissaBits));
220   __ j(below, &process_64_bits);
221
222   // Result is entirely in lower 32-bits of mantissa
223   int delta = HeapNumber::kExponentBias + Double::kPhysicalSignificandSize;
224   __ sub(ecx, Immediate(delta));
225   __ xor_(result_reg, result_reg);
226   __ cmp(ecx, Immediate(31));
227   __ j(above, &done);
228   __ shl_cl(scratch1);
229   __ jmp(&check_negative);
230
231   __ bind(&process_64_bits);
232   // Result must be extracted from shifted 32-bit mantissa
233   __ sub(ecx, Immediate(delta));
234   __ neg(ecx);
235   if (stash_exponent_copy) {
236     __ mov(result_reg, MemOperand(esp, 0));
237   } else {
238     __ mov(result_reg, exponent_operand);
239   }
240   __ and_(result_reg,
241           Immediate(static_cast<uint32_t>(Double::kSignificandMask >> 32)));
242   __ add(result_reg,
243          Immediate(static_cast<uint32_t>(Double::kHiddenBit >> 32)));
244   __ shrd(result_reg, scratch1);
245   __ shr_cl(result_reg);
246   __ test(ecx, Immediate(32));
247   {
248     Label skip_mov;
249     __ j(equal, &skip_mov, Label::kNear);
250     __ mov(scratch1, result_reg);
251     __ bind(&skip_mov);
252   }
253
254   // If the double was negative, negate the integer result.
255   __ bind(&check_negative);
256   __ mov(result_reg, scratch1);
257   __ neg(result_reg);
258   if (stash_exponent_copy) {
259     __ cmp(MemOperand(esp, 0), Immediate(0));
260   } else {
261     __ cmp(exponent_operand, Immediate(0));
262   }
263   {
264     Label skip_mov;
265     __ j(less_equal, &skip_mov, Label::kNear);
266     __ mov(result_reg, scratch1);
267     __ bind(&skip_mov);
268   }
269
270   // Restore registers
271   __ bind(&done);
272   if (stash_exponent_copy) {
273     __ add(esp, Immediate(kDoubleSize / 2));
274   }
275   __ bind(&done_no_stash);
276   if (!final_result_reg.is(result_reg)) {
277     DCHECK(final_result_reg.is(ecx));
278     __ mov(final_result_reg, result_reg);
279   }
280   __ pop(save_reg);
281   __ pop(scratch1);
282   __ ret(0);
283 }
284
285
286 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm,
287                                            Register number) {
288   Label load_smi, done;
289
290   __ JumpIfSmi(number, &load_smi, Label::kNear);
291   __ fld_d(FieldOperand(number, HeapNumber::kValueOffset));
292   __ jmp(&done, Label::kNear);
293
294   __ bind(&load_smi);
295   __ SmiUntag(number);
296   __ push(number);
297   __ fild_s(Operand(esp, 0));
298   __ pop(number);
299
300   __ bind(&done);
301 }
302
303
304 void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm,
305                                              Label* non_float,
306                                              Register scratch) {
307   Label test_other, done;
308   // Test if both operands are floats or smi -> scratch=k_is_float;
309   // Otherwise scratch = k_not_float.
310   __ JumpIfSmi(edx, &test_other, Label::kNear);
311   __ mov(scratch, FieldOperand(edx, HeapObject::kMapOffset));
312   Factory* factory = masm->isolate()->factory();
313   __ cmp(scratch, factory->heap_number_map());
314   __ j(not_equal, non_float);  // argument in edx is not a number -> NaN
315
316   __ bind(&test_other);
317   __ JumpIfSmi(eax, &done, Label::kNear);
318   __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset));
319   __ cmp(scratch, factory->heap_number_map());
320   __ j(not_equal, non_float);  // argument in eax is not a number -> NaN
321
322   // Fall-through: Both operands are numbers.
323   __ bind(&done);
324 }
325
326
327 void MathPowStub::Generate(MacroAssembler* masm) {
328   // No SSE2 support
329   UNREACHABLE();
330 }
331
332
333 void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
334   Label miss;
335   Register receiver = LoadDescriptor::ReceiverRegister();
336
337   if (FLAG_vector_ics) {
338     // With careful management, we won't have to save slot and vector on
339     // the stack. Simply handle the possibly missing case first.
340     // TODO(mvstanton): this code can be more efficient.
341     __ cmp(FieldOperand(receiver, JSFunction::kPrototypeOrInitialMapOffset),
342            Immediate(isolate()->factory()->the_hole_value()));
343     __ j(equal, &miss);
344     __ TryGetFunctionPrototype(receiver, eax, ebx, &miss);
345     __ ret(0);
346   } else {
347     NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, eax,
348                                                             ebx, &miss);
349   }
350   __ bind(&miss);
351   PropertyAccessCompiler::TailCallBuiltin(
352       masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC));
353 }
354
355
356 void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) {
357   // Return address is on the stack.
358   Label slow;
359
360   Register receiver = LoadDescriptor::ReceiverRegister();
361   Register key = LoadDescriptor::NameRegister();
362   Register scratch = eax;
363   DCHECK(!scratch.is(receiver) && !scratch.is(key));
364
365   // Check that the key is an array index, that is Uint32.
366   __ test(key, Immediate(kSmiTagMask | kSmiSignMask));
367   __ j(not_zero, &slow);
368
369   // Everything is fine, call runtime.
370   __ pop(scratch);
371   __ push(receiver);  // receiver
372   __ push(key);       // key
373   __ push(scratch);   // return address
374
375   // Perform tail call to the entry.
376   ExternalReference ref = ExternalReference(
377       IC_Utility(IC::kLoadElementWithInterceptor), masm->isolate());
378   __ TailCallExternalReference(ref, 2, 1);
379
380   __ bind(&slow);
381   PropertyAccessCompiler::TailCallBuiltin(
382       masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
383 }
384
385
386 void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
387   // Return address is on the stack.
388   Label miss;
389
390   Register receiver = LoadDescriptor::ReceiverRegister();
391   Register index = LoadDescriptor::NameRegister();
392   Register scratch = edi;
393   DCHECK(!scratch.is(receiver) && !scratch.is(index));
394   Register result = eax;
395   DCHECK(!result.is(scratch));
396   DCHECK(!FLAG_vector_ics ||
397          (!scratch.is(VectorLoadICDescriptor::VectorRegister()) &&
398           result.is(VectorLoadICDescriptor::SlotRegister())));
399
400   // StringCharAtGenerator doesn't use the result register until it's passed
401   // the different miss possibilities. If it did, we would have a conflict
402   // when FLAG_vector_ics is true.
403
404   StringCharAtGenerator char_at_generator(receiver, index, scratch, result,
405                                           &miss,  // When not a string.
406                                           &miss,  // When not a number.
407                                           &miss,  // When index out of range.
408                                           STRING_INDEX_IS_ARRAY_INDEX,
409                                           RECEIVER_IS_STRING);
410   char_at_generator.GenerateFast(masm);
411   __ ret(0);
412
413   StubRuntimeCallHelper call_helper;
414   char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper);
415
416   __ bind(&miss);
417   PropertyAccessCompiler::TailCallBuiltin(
418       masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
419 }
420
421
422 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
423   CHECK(!has_new_target());
424   // The key is in edx and the parameter count is in eax.
425   DCHECK(edx.is(ArgumentsAccessReadDescriptor::index()));
426   DCHECK(eax.is(ArgumentsAccessReadDescriptor::parameter_count()));
427
428   // The displacement is used for skipping the frame pointer on the
429   // stack. It is the offset of the last parameter (if any) relative
430   // to the frame pointer.
431   static const int kDisplacement = 1 * kPointerSize;
432
433   // Check that the key is a smi.
434   Label slow;
435   __ JumpIfNotSmi(edx, &slow, Label::kNear);
436
437   // Check if the calling frame is an arguments adaptor frame.
438   Label adaptor;
439   __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
440   __ mov(ecx, Operand(ebx, StandardFrameConstants::kContextOffset));
441   __ cmp(ecx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
442   __ j(equal, &adaptor, Label::kNear);
443
444   // Check index against formal parameters count limit passed in
445   // through register eax. Use unsigned comparison to get negative
446   // check for free.
447   __ cmp(edx, eax);
448   __ j(above_equal, &slow, Label::kNear);
449
450   // Read the argument from the stack and return it.
451   STATIC_ASSERT(kSmiTagSize == 1);
452   STATIC_ASSERT(kSmiTag == 0);  // Shifting code depends on these.
453   __ lea(ebx, Operand(ebp, eax, times_2, 0));
454   __ neg(edx);
455   __ mov(eax, Operand(ebx, edx, times_2, kDisplacement));
456   __ ret(0);
457
458   // Arguments adaptor case: Check index against actual arguments
459   // limit found in the arguments adaptor frame. Use unsigned
460   // comparison to get negative check for free.
461   __ bind(&adaptor);
462   __ mov(ecx, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset));
463   __ cmp(edx, ecx);
464   __ j(above_equal, &slow, Label::kNear);
465
466   // Read the argument from the stack and return it.
467   STATIC_ASSERT(kSmiTagSize == 1);
468   STATIC_ASSERT(kSmiTag == 0);  // Shifting code depends on these.
469   __ lea(ebx, Operand(ebx, ecx, times_2, 0));
470   __ neg(edx);
471   __ mov(eax, Operand(ebx, edx, times_2, kDisplacement));
472   __ ret(0);
473
474   // Slow-case: Handle non-smi or out-of-bounds access to arguments
475   // by calling the runtime system.
476   __ bind(&slow);
477   __ pop(ebx);  // Return address.
478   __ push(edx);
479   __ push(ebx);
480   __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1);
481 }
482
483
484 void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) {
485   // esp[0] : return address
486   // esp[4] : number of parameters
487   // esp[8] : receiver displacement
488   // esp[12] : function
489
490   CHECK(!has_new_target());
491
492   // Check if the calling frame is an arguments adaptor frame.
493   Label runtime;
494   __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
495   __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset));
496   __ cmp(ecx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
497   __ j(not_equal, &runtime, Label::kNear);
498
499   // Patch the arguments.length and the parameters pointer.
500   __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
501   __ mov(Operand(esp, 1 * kPointerSize), ecx);
502   __ lea(edx, Operand(edx, ecx, times_2,
503               StandardFrameConstants::kCallerSPOffset));
504   __ mov(Operand(esp, 2 * kPointerSize), edx);
505
506   __ bind(&runtime);
507   __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1);
508 }
509
510
511 void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
512   // esp[0] : return address
513   // esp[4] : number of parameters (tagged)
514   // esp[8] : receiver displacement
515   // esp[12] : function
516
517   // ebx = parameter count (tagged)
518   __ mov(ebx, Operand(esp, 1 * kPointerSize));
519
520   CHECK(!has_new_target());
521
522   // Check if the calling frame is an arguments adaptor frame.
523   // TODO(rossberg): Factor out some of the bits that are shared with the other
524   // Generate* functions.
525   Label runtime;
526   Label adaptor_frame, try_allocate;
527   __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
528   __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset));
529   __ cmp(ecx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
530   __ j(equal, &adaptor_frame, Label::kNear);
531
532   // No adaptor, parameter count = argument count.
533   __ mov(ecx, ebx);
534   __ jmp(&try_allocate, Label::kNear);
535
536   // We have an adaptor frame. Patch the parameters pointer.
537   __ bind(&adaptor_frame);
538   __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
539   __ lea(edx, Operand(edx, ecx, times_2,
540                       StandardFrameConstants::kCallerSPOffset));
541   __ mov(Operand(esp, 2 * kPointerSize), edx);
542
543   // ebx = parameter count (tagged)
544   // ecx = argument count (smi-tagged)
545   // esp[4] = parameter count (tagged)
546   // esp[8] = address of receiver argument
547   // Compute the mapped parameter count = min(ebx, ecx) in ebx.
548   __ cmp(ebx, ecx);
549   __ j(less_equal, &try_allocate, Label::kNear);
550   __ mov(ebx, ecx);
551
552   __ bind(&try_allocate);
553
554   // Save mapped parameter count.
555   __ push(ebx);
556
557   // Compute the sizes of backing store, parameter map, and arguments object.
558   // 1. Parameter map, has 2 extra words containing context and backing store.
559   const int kParameterMapHeaderSize =
560       FixedArray::kHeaderSize + 2 * kPointerSize;
561   Label no_parameter_map;
562   __ test(ebx, ebx);
563   __ j(zero, &no_parameter_map, Label::kNear);
564   __ lea(ebx, Operand(ebx, times_2, kParameterMapHeaderSize));
565   __ bind(&no_parameter_map);
566
567   // 2. Backing store.
568   __ lea(ebx, Operand(ebx, ecx, times_2, FixedArray::kHeaderSize));
569
570   // 3. Arguments object.
571   __ add(ebx, Immediate(Heap::kSloppyArgumentsObjectSize));
572
573   // Do the allocation of all three objects in one go.
574   __ Allocate(ebx, eax, edx, edi, &runtime, TAG_OBJECT);
575
576   // eax = address of new object(s) (tagged)
577   // ecx = argument count (smi-tagged)
578   // esp[0] = mapped parameter count (tagged)
579   // esp[8] = parameter count (tagged)
580   // esp[12] = address of receiver argument
581   // Get the arguments map from the current native context into edi.
582   Label has_mapped_parameters, instantiate;
583   __ mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
584   __ mov(edi, FieldOperand(edi, GlobalObject::kNativeContextOffset));
585   __ mov(ebx, Operand(esp, 0 * kPointerSize));
586   __ test(ebx, ebx);
587   __ j(not_zero, &has_mapped_parameters, Label::kNear);
588   __ mov(
589       edi,
590       Operand(edi, Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX)));
591   __ jmp(&instantiate, Label::kNear);
592
593   __ bind(&has_mapped_parameters);
594   __ mov(
595       edi,
596       Operand(edi, Context::SlotOffset(Context::ALIASED_ARGUMENTS_MAP_INDEX)));
597   __ bind(&instantiate);
598
599   // eax = address of new object (tagged)
600   // ebx = mapped parameter count (tagged)
601   // ecx = argument count (smi-tagged)
602   // edi = address of arguments map (tagged)
603   // esp[0] = mapped parameter count (tagged)
604   // esp[8] = parameter count (tagged)
605   // esp[12] = address of receiver argument
606   // Copy the JS object part.
607   __ mov(FieldOperand(eax, JSObject::kMapOffset), edi);
608   __ mov(FieldOperand(eax, JSObject::kPropertiesOffset),
609          masm->isolate()->factory()->empty_fixed_array());
610   __ mov(FieldOperand(eax, JSObject::kElementsOffset),
611          masm->isolate()->factory()->empty_fixed_array());
612
613   // Set up the callee in-object property.
614   STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
615   __ mov(edx, Operand(esp, 4 * kPointerSize));
616   __ AssertNotSmi(edx);
617   __ mov(FieldOperand(eax, JSObject::kHeaderSize +
618                       Heap::kArgumentsCalleeIndex * kPointerSize),
619          edx);
620
621   // Use the length (smi tagged) and set that as an in-object property too.
622   __ AssertSmi(ecx);
623   STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
624   __ mov(FieldOperand(eax, JSObject::kHeaderSize +
625                       Heap::kArgumentsLengthIndex * kPointerSize),
626          ecx);
627
628   // Set up the elements pointer in the allocated arguments object.
629   // If we allocated a parameter map, edi will point there, otherwise to the
630   // backing store.
631   __ lea(edi, Operand(eax, Heap::kSloppyArgumentsObjectSize));
632   __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi);
633
634   // eax = address of new object (tagged)
635   // ebx = mapped parameter count (tagged)
636   // ecx = argument count (tagged)
637   // edi = address of parameter map or backing store (tagged)
638   // esp[0] = mapped parameter count (tagged)
639   // esp[8] = parameter count (tagged)
640   // esp[12] = address of receiver argument
641   // Free a register.
642   __ push(eax);
643
644   // Initialize parameter map. If there are no mapped arguments, we're done.
645   Label skip_parameter_map;
646   __ test(ebx, ebx);
647   __ j(zero, &skip_parameter_map);
648
649   __ mov(FieldOperand(edi, FixedArray::kMapOffset),
650          Immediate(isolate()->factory()->sloppy_arguments_elements_map()));
651   __ lea(eax, Operand(ebx, reinterpret_cast<intptr_t>(Smi::FromInt(2))));
652   __ mov(FieldOperand(edi, FixedArray::kLengthOffset), eax);
653   __ mov(FieldOperand(edi, FixedArray::kHeaderSize + 0 * kPointerSize), esi);
654   __ lea(eax, Operand(edi, ebx, times_2, kParameterMapHeaderSize));
655   __ mov(FieldOperand(edi, FixedArray::kHeaderSize + 1 * kPointerSize), eax);
656
657   // Copy the parameter slots and the holes in the arguments.
658   // We need to fill in mapped_parameter_count slots. They index the context,
659   // where parameters are stored in reverse order, at
660   //   MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1
661   // The mapped parameter thus need to get indices
662   //   MIN_CONTEXT_SLOTS+parameter_count-1 ..
663   //       MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count
664   // We loop from right to left.
665   Label parameters_loop, parameters_test;
666   __ push(ecx);
667   __ mov(eax, Operand(esp, 2 * kPointerSize));
668   __ mov(ebx, Immediate(Smi::FromInt(Context::MIN_CONTEXT_SLOTS)));
669   __ add(ebx, Operand(esp, 4 * kPointerSize));
670   __ sub(ebx, eax);
671   __ mov(ecx, isolate()->factory()->the_hole_value());
672   __ mov(edx, edi);
673   __ lea(edi, Operand(edi, eax, times_2, kParameterMapHeaderSize));
674   // eax = loop variable (tagged)
675   // ebx = mapping index (tagged)
676   // ecx = the hole value
677   // edx = address of parameter map (tagged)
678   // edi = address of backing store (tagged)
679   // esp[0] = argument count (tagged)
680   // esp[4] = address of new object (tagged)
681   // esp[8] = mapped parameter count (tagged)
682   // esp[16] = parameter count (tagged)
683   // esp[20] = address of receiver argument
684   __ jmp(&parameters_test, Label::kNear);
685
686   __ bind(&parameters_loop);
687   __ sub(eax, Immediate(Smi::FromInt(1)));
688   __ mov(FieldOperand(edx, eax, times_2, kParameterMapHeaderSize), ebx);
689   __ mov(FieldOperand(edi, eax, times_2, FixedArray::kHeaderSize), ecx);
690   __ add(ebx, Immediate(Smi::FromInt(1)));
691   __ bind(&parameters_test);
692   __ test(eax, eax);
693   __ j(not_zero, &parameters_loop, Label::kNear);
694   __ pop(ecx);
695
696   __ bind(&skip_parameter_map);
697
698   // ecx = argument count (tagged)
699   // edi = address of backing store (tagged)
700   // esp[0] = address of new object (tagged)
701   // esp[4] = mapped parameter count (tagged)
702   // esp[12] = parameter count (tagged)
703   // esp[16] = address of receiver argument
704   // Copy arguments header and remaining slots (if there are any).
705   __ mov(FieldOperand(edi, FixedArray::kMapOffset),
706          Immediate(isolate()->factory()->fixed_array_map()));
707   __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx);
708
709   Label arguments_loop, arguments_test;
710   __ mov(ebx, Operand(esp, 1 * kPointerSize));
711   __ mov(edx, Operand(esp, 4 * kPointerSize));
712   __ sub(edx, ebx);  // Is there a smarter way to do negative scaling?
713   __ sub(edx, ebx);
714   __ jmp(&arguments_test, Label::kNear);
715
716   __ bind(&arguments_loop);
717   __ sub(edx, Immediate(kPointerSize));
718   __ mov(eax, Operand(edx, 0));
719   __ mov(FieldOperand(edi, ebx, times_2, FixedArray::kHeaderSize), eax);
720   __ add(ebx, Immediate(Smi::FromInt(1)));
721
722   __ bind(&arguments_test);
723   __ cmp(ebx, ecx);
724   __ j(less, &arguments_loop, Label::kNear);
725
726   // Restore.
727   __ pop(eax);  // Address of arguments object.
728   __ pop(ebx);  // Parameter count.
729
730   // Return and remove the on-stack parameters.
731   __ ret(3 * kPointerSize);
732
733   // Do the runtime call to allocate the arguments object.
734   __ bind(&runtime);
735   __ pop(eax);  // Remove saved parameter count.
736   __ mov(Operand(esp, 1 * kPointerSize), ecx);  // Patch argument count.
737   __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1);
738 }
739
740
741 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
742   // esp[0] : return address
743   // esp[4] : number of parameters
744   // esp[8] : receiver displacement
745   // esp[12] : function
746
747   // Check if the calling frame is an arguments adaptor frame.
748   Label adaptor_frame, try_allocate, runtime;
749   __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
750   __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset));
751   __ cmp(ecx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
752   __ j(equal, &adaptor_frame, Label::kNear);
753
754   // Get the length from the frame.
755   __ mov(ecx, Operand(esp, 1 * kPointerSize));
756   __ jmp(&try_allocate, Label::kNear);
757
758   // Patch the arguments.length and the parameters pointer.
759   __ bind(&adaptor_frame);
760   __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
761
762   if (has_new_target()) {
763     // If the constructor was [[Call]]ed, the call will not push a new.target
764     // onto the stack. In that case the arguments array we construct is bogus,
765     // bu we do not care as the constructor throws immediately.
766     __ cmp(ecx, Immediate(Smi::FromInt(0)));
767     Label skip_decrement;
768     __ j(equal, &skip_decrement);
769     // Subtract 1 from smi-tagged arguments count.
770     __ sub(ecx, Immediate(2));
771     __ bind(&skip_decrement);
772   }
773
774   __ lea(edx, Operand(edx, ecx, times_2,
775                       StandardFrameConstants::kCallerSPOffset));
776   __ mov(Operand(esp, 1 * kPointerSize), ecx);
777   __ mov(Operand(esp, 2 * kPointerSize), edx);
778
779   // Try the new space allocation. Start out with computing the size of
780   // the arguments object and the elements array.
781   Label add_arguments_object;
782   __ bind(&try_allocate);
783   __ test(ecx, ecx);
784   __ j(zero, &add_arguments_object, Label::kNear);
785   __ lea(ecx, Operand(ecx, times_2, FixedArray::kHeaderSize));
786   __ bind(&add_arguments_object);
787   __ add(ecx, Immediate(Heap::kStrictArgumentsObjectSize));
788
789   // Do the allocation of both objects in one go.
790   __ Allocate(ecx, eax, edx, ebx, &runtime, TAG_OBJECT);
791
792   // Get the arguments map from the current native context.
793   __ mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
794   __ mov(edi, FieldOperand(edi, GlobalObject::kNativeContextOffset));
795   const int offset = Context::SlotOffset(Context::STRICT_ARGUMENTS_MAP_INDEX);
796   __ mov(edi, Operand(edi, offset));
797
798   __ mov(FieldOperand(eax, JSObject::kMapOffset), edi);
799   __ mov(FieldOperand(eax, JSObject::kPropertiesOffset),
800          masm->isolate()->factory()->empty_fixed_array());
801   __ mov(FieldOperand(eax, JSObject::kElementsOffset),
802          masm->isolate()->factory()->empty_fixed_array());
803
804   // Get the length (smi tagged) and set that as an in-object property too.
805   STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
806   __ mov(ecx, Operand(esp, 1 * kPointerSize));
807   __ AssertSmi(ecx);
808   __ mov(FieldOperand(eax, JSObject::kHeaderSize +
809                       Heap::kArgumentsLengthIndex * kPointerSize),
810          ecx);
811
812   // If there are no actual arguments, we're done.
813   Label done;
814   __ test(ecx, ecx);
815   __ j(zero, &done, Label::kNear);
816
817   // Get the parameters pointer from the stack.
818   __ mov(edx, Operand(esp, 2 * kPointerSize));
819
820   // Set up the elements pointer in the allocated arguments object and
821   // initialize the header in the elements fixed array.
822   __ lea(edi, Operand(eax, Heap::kStrictArgumentsObjectSize));
823   __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi);
824   __ mov(FieldOperand(edi, FixedArray::kMapOffset),
825          Immediate(isolate()->factory()->fixed_array_map()));
826
827   __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx);
828   // Untag the length for the loop below.
829   __ SmiUntag(ecx);
830
831   // Copy the fixed array slots.
832   Label loop;
833   __ bind(&loop);
834   __ mov(ebx, Operand(edx, -1 * kPointerSize));  // Skip receiver.
835   __ mov(FieldOperand(edi, FixedArray::kHeaderSize), ebx);
836   __ add(edi, Immediate(kPointerSize));
837   __ sub(edx, Immediate(kPointerSize));
838   __ dec(ecx);
839   __ j(not_zero, &loop);
840
841   // Return and remove the on-stack parameters.
842   __ bind(&done);
843   __ ret(3 * kPointerSize);
844
845   // Do the runtime call to allocate the arguments object.
846   __ bind(&runtime);
847   __ TailCallRuntime(Runtime::kNewStrictArguments, 3, 1);
848 }
849
850
851 void RestParamAccessStub::GenerateNew(MacroAssembler* masm) {
852   // esp[0] : return address
853   // esp[4] : index of rest parameter
854   // esp[8] : number of parameters
855   // esp[12] : receiver displacement
856
857   // Check if the calling frame is an arguments adaptor frame.
858   Label runtime;
859   __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
860   __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset));
861   __ cmp(ecx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
862   __ j(not_equal, &runtime);
863
864   // Patch the arguments.length and the parameters pointer.
865   __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
866   __ mov(Operand(esp, 2 * kPointerSize), ecx);
867   __ lea(edx, Operand(edx, ecx, times_2,
868                       StandardFrameConstants::kCallerSPOffset));
869   __ mov(Operand(esp, 3 * kPointerSize), edx);
870
871   __ bind(&runtime);
872   __ TailCallRuntime(Runtime::kNewRestParam, 3, 1);
873 }
874
875
876 void RegExpExecStub::Generate(MacroAssembler* masm) {
877   // Just jump directly to runtime if native RegExp is not selected at compile
878   // time or if regexp entry in generated code is turned off runtime switch or
879   // at compilation.
880 #ifdef V8_INTERPRETED_REGEXP
881   __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
882 #else  // V8_INTERPRETED_REGEXP
883
884   // Stack frame on entry.
885   //  esp[0]: return address
886   //  esp[4]: last_match_info (expected JSArray)
887   //  esp[8]: previous index
888   //  esp[12]: subject string
889   //  esp[16]: JSRegExp object
890
891   static const int kLastMatchInfoOffset = 1 * kPointerSize;
892   static const int kPreviousIndexOffset = 2 * kPointerSize;
893   static const int kSubjectOffset = 3 * kPointerSize;
894   static const int kJSRegExpOffset = 4 * kPointerSize;
895
896   Label runtime;
897   Factory* factory = isolate()->factory();
898
899   // Ensure that a RegExp stack is allocated.
900   ExternalReference address_of_regexp_stack_memory_address =
901       ExternalReference::address_of_regexp_stack_memory_address(isolate());
902   ExternalReference address_of_regexp_stack_memory_size =
903       ExternalReference::address_of_regexp_stack_memory_size(isolate());
904   __ mov(ebx, Operand::StaticVariable(address_of_regexp_stack_memory_size));
905   __ test(ebx, ebx);
906   __ j(zero, &runtime);
907
908   // Check that the first argument is a JSRegExp object.
909   __ mov(eax, Operand(esp, kJSRegExpOffset));
910   STATIC_ASSERT(kSmiTag == 0);
911   __ JumpIfSmi(eax, &runtime);
912   __ CmpObjectType(eax, JS_REGEXP_TYPE, ecx);
913   __ j(not_equal, &runtime);
914
915   // Check that the RegExp has been compiled (data contains a fixed array).
916   __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset));
917   if (FLAG_debug_code) {
918     __ test(ecx, Immediate(kSmiTagMask));
919     __ Check(not_zero, kUnexpectedTypeForRegExpDataFixedArrayExpected);
920     __ CmpObjectType(ecx, FIXED_ARRAY_TYPE, ebx);
921     __ Check(equal, kUnexpectedTypeForRegExpDataFixedArrayExpected);
922   }
923
924   // ecx: RegExp data (FixedArray)
925   // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
926   __ mov(ebx, FieldOperand(ecx, JSRegExp::kDataTagOffset));
927   __ cmp(ebx, Immediate(Smi::FromInt(JSRegExp::IRREGEXP)));
928   __ j(not_equal, &runtime);
929
930   // ecx: RegExp data (FixedArray)
931   // Check that the number of captures fit in the static offsets vector buffer.
932   __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset));
933   // Check (number_of_captures + 1) * 2 <= offsets vector size
934   // Or          number_of_captures * 2 <= offsets vector size - 2
935   // Multiplying by 2 comes for free since edx is smi-tagged.
936   STATIC_ASSERT(kSmiTag == 0);
937   STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
938   STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2);
939   __ cmp(edx, Isolate::kJSRegexpStaticOffsetsVectorSize - 2);
940   __ j(above, &runtime);
941
942   // Reset offset for possibly sliced string.
943   __ Move(edi, Immediate(0));
944   __ mov(eax, Operand(esp, kSubjectOffset));
945   __ JumpIfSmi(eax, &runtime);
946   __ mov(edx, eax);  // Make a copy of the original subject string.
947   __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
948   __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
949
950   // eax: subject string
951   // edx: subject string
952   // ebx: subject string instance type
953   // ecx: RegExp data (FixedArray)
954   // Handle subject string according to its encoding and representation:
955   // (1) Sequential two byte?  If yes, go to (9).
956   // (2) Sequential one byte?  If yes, go to (6).
957   // (3) Anything but sequential or cons?  If yes, go to (7).
958   // (4) Cons string.  If the string is flat, replace subject with first string.
959   //     Otherwise bailout.
960   // (5a) Is subject sequential two byte?  If yes, go to (9).
961   // (5b) Is subject external?  If yes, go to (8).
962   // (6) One byte sequential.  Load regexp code for one byte.
963   // (E) Carry on.
964   /// [...]
965
966   // Deferred code at the end of the stub:
967   // (7) Not a long external string?  If yes, go to (10).
968   // (8) External string.  Make it, offset-wise, look like a sequential string.
969   // (8a) Is the external string one byte?  If yes, go to (6).
970   // (9) Two byte sequential.  Load regexp code for one byte. Go to (E).
971   // (10) Short external string or not a string?  If yes, bail out to runtime.
972   // (11) Sliced string.  Replace subject with parent. Go to (5a).
973
974   Label seq_one_byte_string /* 6 */, seq_two_byte_string /* 9 */,
975         external_string /* 8 */, check_underlying /* 5a */,
976         not_seq_nor_cons /* 7 */, check_code /* E */,
977         not_long_external /* 10 */;
978
979   // (1) Sequential two byte?  If yes, go to (9).
980   __ and_(ebx, kIsNotStringMask |
981                kStringRepresentationMask |
982                kStringEncodingMask |
983                kShortExternalStringMask);
984   STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0);
985   __ j(zero, &seq_two_byte_string);  // Go to (9).
986
987   // (2) Sequential one byte?  If yes, go to (6).
988   // Any other sequential string must be one byte.
989   __ and_(ebx, Immediate(kIsNotStringMask |
990                          kStringRepresentationMask |
991                          kShortExternalStringMask));
992   __ j(zero, &seq_one_byte_string, Label::kNear);  // Go to (6).
993
994   // (3) Anything but sequential or cons?  If yes, go to (7).
995   // We check whether the subject string is a cons, since sequential strings
996   // have already been covered.
997   STATIC_ASSERT(kConsStringTag < kExternalStringTag);
998   STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
999   STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
1000   STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
1001   __ cmp(ebx, Immediate(kExternalStringTag));
1002   __ j(greater_equal, &not_seq_nor_cons);  // Go to (7).
1003
1004   // (4) Cons string.  Check that it's flat.
1005   // Replace subject with first string and reload instance type.
1006   __ cmp(FieldOperand(eax, ConsString::kSecondOffset), factory->empty_string());
1007   __ j(not_equal, &runtime);
1008   __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset));
1009   __ bind(&check_underlying);
1010   __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
1011   __ mov(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
1012
1013   // (5a) Is subject sequential two byte?  If yes, go to (9).
1014   __ test_b(ebx, kStringRepresentationMask | kStringEncodingMask);
1015   STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0);
1016   __ j(zero, &seq_two_byte_string);  // Go to (9).
1017   // (5b) Is subject external?  If yes, go to (8).
1018   __ test_b(ebx, kStringRepresentationMask);
1019   // The underlying external string is never a short external string.
1020   STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
1021   STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
1022   __ j(not_zero, &external_string);  // Go to (8).
1023
1024   // eax: sequential subject string (or look-alike, external string)
1025   // edx: original subject string
1026   // ecx: RegExp data (FixedArray)
1027   // (6) One byte sequential.  Load regexp code for one byte.
1028   __ bind(&seq_one_byte_string);
1029   // Load previous index and check range before edx is overwritten.  We have
1030   // to use edx instead of eax here because it might have been only made to
1031   // look like a sequential string when it actually is an external string.
1032   __ mov(ebx, Operand(esp, kPreviousIndexOffset));
1033   __ JumpIfNotSmi(ebx, &runtime);
1034   __ cmp(ebx, FieldOperand(edx, String::kLengthOffset));
1035   __ j(above_equal, &runtime);
1036   __ mov(edx, FieldOperand(ecx, JSRegExp::kDataOneByteCodeOffset));
1037   __ Move(ecx, Immediate(1));  // Type is one byte.
1038
1039   // (E) Carry on.  String handling is done.
1040   __ bind(&check_code);
1041   // edx: irregexp code
1042   // Check that the irregexp code has been generated for the actual string
1043   // encoding. If it has, the field contains a code object otherwise it contains
1044   // a smi (code flushing support).
1045   __ JumpIfSmi(edx, &runtime);
1046
1047   // eax: subject string
1048   // ebx: previous index (smi)
1049   // edx: code
1050   // ecx: encoding of subject string (1 if one_byte, 0 if two_byte);
1051   // All checks done. Now push arguments for native regexp code.
1052   Counters* counters = isolate()->counters();
1053   __ IncrementCounter(counters->regexp_entry_native(), 1);
1054
1055   // Isolates: note we add an additional parameter here (isolate pointer).
1056   static const int kRegExpExecuteArguments = 9;
1057   __ EnterApiExitFrame(kRegExpExecuteArguments);
1058
1059   // Argument 9: Pass current isolate address.
1060   __ mov(Operand(esp, 8 * kPointerSize),
1061       Immediate(ExternalReference::isolate_address(isolate())));
1062
1063   // Argument 8: Indicate that this is a direct call from JavaScript.
1064   __ mov(Operand(esp, 7 * kPointerSize), Immediate(1));
1065
1066   // Argument 7: Start (high end) of backtracking stack memory area.
1067   __ mov(esi, Operand::StaticVariable(address_of_regexp_stack_memory_address));
1068   __ add(esi, Operand::StaticVariable(address_of_regexp_stack_memory_size));
1069   __ mov(Operand(esp, 6 * kPointerSize), esi);
1070
1071   // Argument 6: Set the number of capture registers to zero to force global
1072   // regexps to behave as non-global.  This does not affect non-global regexps.
1073   __ mov(Operand(esp, 5 * kPointerSize), Immediate(0));
1074
1075   // Argument 5: static offsets vector buffer.
1076   __ mov(Operand(esp, 4 * kPointerSize),
1077          Immediate(ExternalReference::address_of_static_offsets_vector(
1078              isolate())));
1079
1080   // Argument 2: Previous index.
1081   __ SmiUntag(ebx);
1082   __ mov(Operand(esp, 1 * kPointerSize), ebx);
1083
1084   // Argument 1: Original subject string.
1085   // The original subject is in the previous stack frame. Therefore we have to
1086   // use ebp, which points exactly to one pointer size below the previous esp.
1087   // (Because creating a new stack frame pushes the previous ebp onto the stack
1088   // and thereby moves up esp by one kPointerSize.)
1089   __ mov(esi, Operand(ebp, kSubjectOffset + kPointerSize));
1090   __ mov(Operand(esp, 0 * kPointerSize), esi);
1091
1092   // esi: original subject string
1093   // eax: underlying subject string
1094   // ebx: previous index
1095   // ecx: encoding of subject string (1 if one_byte 0 if two_byte);
1096   // edx: code
1097   // Argument 4: End of string data
1098   // Argument 3: Start of string data
1099   // Prepare start and end index of the input.
1100   // Load the length from the original sliced string if that is the case.
1101   __ mov(esi, FieldOperand(esi, String::kLengthOffset));
1102   __ add(esi, edi);  // Calculate input end wrt offset.
1103   __ SmiUntag(edi);
1104   __ add(ebx, edi);  // Calculate input start wrt offset.
1105
1106   // ebx: start index of the input string
1107   // esi: end index of the input string
1108   Label setup_two_byte, setup_rest;
1109   __ test(ecx, ecx);
1110   __ j(zero, &setup_two_byte, Label::kNear);
1111   __ SmiUntag(esi);
1112   __ lea(ecx, FieldOperand(eax, esi, times_1, SeqOneByteString::kHeaderSize));
1113   __ mov(Operand(esp, 3 * kPointerSize), ecx);  // Argument 4.
1114   __ lea(ecx, FieldOperand(eax, ebx, times_1, SeqOneByteString::kHeaderSize));
1115   __ mov(Operand(esp, 2 * kPointerSize), ecx);  // Argument 3.
1116   __ jmp(&setup_rest, Label::kNear);
1117
1118   __ bind(&setup_two_byte);
1119   STATIC_ASSERT(kSmiTag == 0);
1120   STATIC_ASSERT(kSmiTagSize == 1);  // esi is smi (powered by 2).
1121   __ lea(ecx, FieldOperand(eax, esi, times_1, SeqTwoByteString::kHeaderSize));
1122   __ mov(Operand(esp, 3 * kPointerSize), ecx);  // Argument 4.
1123   __ lea(ecx, FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize));
1124   __ mov(Operand(esp, 2 * kPointerSize), ecx);  // Argument 3.
1125
1126   __ bind(&setup_rest);
1127
1128   // Locate the code entry and call it.
1129   __ add(edx, Immediate(Code::kHeaderSize - kHeapObjectTag));
1130   __ call(edx);
1131
1132   // Drop arguments and come back to JS mode.
1133   __ LeaveApiExitFrame(true);
1134
1135   // Check the result.
1136   Label success;
1137   __ cmp(eax, 1);
1138   // We expect exactly one result since we force the called regexp to behave
1139   // as non-global.
1140   __ j(equal, &success);
1141   Label failure;
1142   __ cmp(eax, NativeRegExpMacroAssembler::FAILURE);
1143   __ j(equal, &failure);
1144   __ cmp(eax, NativeRegExpMacroAssembler::EXCEPTION);
1145   // If not exception it can only be retry. Handle that in the runtime system.
1146   __ j(not_equal, &runtime);
1147   // Result must now be exception. If there is no pending exception already a
1148   // stack overflow (on the backtrack stack) was detected in RegExp code but
1149   // haven't created the exception yet. Handle that in the runtime system.
1150   // TODO(592): Rerunning the RegExp to get the stack overflow exception.
1151   ExternalReference pending_exception(Isolate::kPendingExceptionAddress,
1152                                       isolate());
1153   __ mov(edx, Immediate(isolate()->factory()->the_hole_value()));
1154   __ mov(eax, Operand::StaticVariable(pending_exception));
1155   __ cmp(edx, eax);
1156   __ j(equal, &runtime);
1157
1158   // For exception, throw the exception again.
1159   __ TailCallRuntime(Runtime::kRegExpExecReThrow, 4, 1);
1160
1161   __ bind(&failure);
1162   // For failure to match, return null.
1163   __ mov(eax, factory->null_value());
1164   __ ret(4 * kPointerSize);
1165
1166   // Load RegExp data.
1167   __ bind(&success);
1168   __ mov(eax, Operand(esp, kJSRegExpOffset));
1169   __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset));
1170   __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset));
1171   // Calculate number of capture registers (number_of_captures + 1) * 2.
1172   STATIC_ASSERT(kSmiTag == 0);
1173   STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
1174   __ add(edx, Immediate(2));  // edx was a smi.
1175
1176   // edx: Number of capture registers
1177   // Load last_match_info which is still known to be a fast case JSArray.
1178   // Check that the fourth object is a JSArray object.
1179   __ mov(eax, Operand(esp, kLastMatchInfoOffset));
1180   __ JumpIfSmi(eax, &runtime);
1181   __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx);
1182   __ j(not_equal, &runtime);
1183   // Check that the JSArray is in fast case.
1184   __ mov(ebx, FieldOperand(eax, JSArray::kElementsOffset));
1185   __ mov(eax, FieldOperand(ebx, HeapObject::kMapOffset));
1186   __ cmp(eax, factory->fixed_array_map());
1187   __ j(not_equal, &runtime);
1188   // Check that the last match info has space for the capture registers and the
1189   // additional information.
1190   __ mov(eax, FieldOperand(ebx, FixedArray::kLengthOffset));
1191   __ SmiUntag(eax);
1192   __ sub(eax, Immediate(RegExpImpl::kLastMatchOverhead));
1193   __ cmp(edx, eax);
1194   __ j(greater, &runtime);
1195
1196   // ebx: last_match_info backing store (FixedArray)
1197   // edx: number of capture registers
1198   // Store the capture count.
1199   __ SmiTag(edx);  // Number of capture registers to smi.
1200   __ mov(FieldOperand(ebx, RegExpImpl::kLastCaptureCountOffset), edx);
1201   __ SmiUntag(edx);  // Number of capture registers back from smi.
1202   // Store last subject and last input.
1203   __ mov(eax, Operand(esp, kSubjectOffset));
1204   __ mov(ecx, eax);
1205   __ mov(FieldOperand(ebx, RegExpImpl::kLastSubjectOffset), eax);
1206   __ RecordWriteField(ebx, RegExpImpl::kLastSubjectOffset, eax, edi,
1207                       kDontSaveFPRegs);
1208   __ mov(eax, ecx);
1209   __ mov(FieldOperand(ebx, RegExpImpl::kLastInputOffset), eax);
1210   __ RecordWriteField(ebx, RegExpImpl::kLastInputOffset, eax, edi,
1211                       kDontSaveFPRegs);
1212
1213   // Get the static offsets vector filled by the native regexp code.
1214   ExternalReference address_of_static_offsets_vector =
1215       ExternalReference::address_of_static_offsets_vector(isolate());
1216   __ mov(ecx, Immediate(address_of_static_offsets_vector));
1217
1218   // ebx: last_match_info backing store (FixedArray)
1219   // ecx: offsets vector
1220   // edx: number of capture registers
1221   Label next_capture, done;
1222   // Capture register counter starts from number of capture registers and
1223   // counts down until wraping after zero.
1224   __ bind(&next_capture);
1225   __ sub(edx, Immediate(1));
1226   __ j(negative, &done, Label::kNear);
1227   // Read the value from the static offsets vector buffer.
1228   __ mov(edi, Operand(ecx, edx, times_int_size, 0));
1229   __ SmiTag(edi);
1230   // Store the smi value in the last match info.
1231   __ mov(FieldOperand(ebx,
1232                       edx,
1233                       times_pointer_size,
1234                       RegExpImpl::kFirstCaptureOffset),
1235                       edi);
1236   __ jmp(&next_capture);
1237   __ bind(&done);
1238
1239   // Return last match info.
1240   __ mov(eax, Operand(esp, kLastMatchInfoOffset));
1241   __ ret(4 * kPointerSize);
1242
1243   // Do the runtime call to execute the regexp.
1244   __ bind(&runtime);
1245   __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
1246
1247   // Deferred code for string handling.
1248   // (7) Not a long external string?  If yes, go to (10).
1249   __ bind(&not_seq_nor_cons);
1250   // Compare flags are still set from (3).
1251   __ j(greater, &not_long_external, Label::kNear);  // Go to (10).
1252
1253   // (8) External string.  Short external strings have been ruled out.
1254   __ bind(&external_string);
1255   // Reload instance type.
1256   __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
1257   __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
1258   if (FLAG_debug_code) {
1259     // Assert that we do not have a cons or slice (indirect strings) here.
1260     // Sequential strings have already been ruled out.
1261     __ test_b(ebx, kIsIndirectStringMask);
1262     __ Assert(zero, kExternalStringExpectedButNotFound);
1263   }
1264   __ mov(eax, FieldOperand(eax, ExternalString::kResourceDataOffset));
1265   // Move the pointer so that offset-wise, it looks like a sequential string.
1266   STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
1267   __ sub(eax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
1268   STATIC_ASSERT(kTwoByteStringTag == 0);
1269   // (8a) Is the external string one byte?  If yes, go to (6).
1270   __ test_b(ebx, kStringEncodingMask);
1271   __ j(not_zero, &seq_one_byte_string);  // Goto (6).
1272
1273   // eax: sequential subject string (or look-alike, external string)
1274   // edx: original subject string
1275   // ecx: RegExp data (FixedArray)
1276   // (9) Two byte sequential.  Load regexp code for one byte. Go to (E).
1277   __ bind(&seq_two_byte_string);
1278   // Load previous index and check range before edx is overwritten.  We have
1279   // to use edx instead of eax here because it might have been only made to
1280   // look like a sequential string when it actually is an external string.
1281   __ mov(ebx, Operand(esp, kPreviousIndexOffset));
1282   __ JumpIfNotSmi(ebx, &runtime);
1283   __ cmp(ebx, FieldOperand(edx, String::kLengthOffset));
1284   __ j(above_equal, &runtime);
1285   __ mov(edx, FieldOperand(ecx, JSRegExp::kDataUC16CodeOffset));
1286   __ Move(ecx, Immediate(0));  // Type is two byte.
1287   __ jmp(&check_code);  // Go to (E).
1288
1289   // (10) Not a string or a short external string?  If yes, bail out to runtime.
1290   __ bind(&not_long_external);
1291   // Catch non-string subject or short external string.
1292   STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
1293   __ test(ebx, Immediate(kIsNotStringMask | kShortExternalStringTag));
1294   __ j(not_zero, &runtime);
1295
1296   // (11) Sliced string.  Replace subject with parent.  Go to (5a).
1297   // Load offset into edi and replace subject string with parent.
1298   __ mov(edi, FieldOperand(eax, SlicedString::kOffsetOffset));
1299   __ mov(eax, FieldOperand(eax, SlicedString::kParentOffset));
1300   __ jmp(&check_underlying);  // Go to (5a).
1301 #endif  // V8_INTERPRETED_REGEXP
1302 }
1303
1304
1305 static int NegativeComparisonResult(Condition cc) {
1306   DCHECK(cc != equal);
1307   DCHECK((cc == less) || (cc == less_equal)
1308       || (cc == greater) || (cc == greater_equal));
1309   return (cc == greater || cc == greater_equal) ? LESS : GREATER;
1310 }
1311
1312
1313 static void CheckInputType(MacroAssembler* masm, Register input,
1314                            CompareICState::State expected, Label* fail) {
1315   Label ok;
1316   if (expected == CompareICState::SMI) {
1317     __ JumpIfNotSmi(input, fail);
1318   } else if (expected == CompareICState::NUMBER) {
1319     __ JumpIfSmi(input, &ok);
1320     __ cmp(FieldOperand(input, HeapObject::kMapOffset),
1321            Immediate(masm->isolate()->factory()->heap_number_map()));
1322     __ j(not_equal, fail);
1323   }
1324   // We could be strict about internalized/non-internalized here, but as long as
1325   // hydrogen doesn't care, the stub doesn't have to care either.
1326   __ bind(&ok);
1327 }
1328
1329
1330 static void BranchIfNotInternalizedString(MacroAssembler* masm,
1331                                           Label* label,
1332                                           Register object,
1333                                           Register scratch) {
1334   __ JumpIfSmi(object, label);
1335   __ mov(scratch, FieldOperand(object, HeapObject::kMapOffset));
1336   __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
1337   STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
1338   __ test(scratch, Immediate(kIsNotStringMask | kIsNotInternalizedMask));
1339   __ j(not_zero, label);
1340 }
1341
1342
1343 void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
1344   Label check_unequal_objects;
1345   Condition cc = GetCondition();
1346
1347   Label miss;
1348   CheckInputType(masm, edx, left(), &miss);
1349   CheckInputType(masm, eax, right(), &miss);
1350
1351   // Compare two smis.
1352   Label non_smi, smi_done;
1353   __ mov(ecx, edx);
1354   __ or_(ecx, eax);
1355   __ JumpIfNotSmi(ecx, &non_smi, Label::kNear);
1356   __ sub(edx, eax);  // Return on the result of the subtraction.
1357   __ j(no_overflow, &smi_done, Label::kNear);
1358   __ not_(edx);  // Correct sign in case of overflow. edx is never 0 here.
1359   __ bind(&smi_done);
1360   __ mov(eax, edx);
1361   __ ret(0);
1362   __ bind(&non_smi);
1363
1364   // NOTICE! This code is only reached after a smi-fast-case check, so
1365   // it is certain that at least one operand isn't a smi.
1366
1367   // Identical objects can be compared fast, but there are some tricky cases
1368   // for NaN and undefined.
1369   Label generic_heap_number_comparison;
1370   {
1371     Label not_identical;
1372     __ cmp(eax, edx);
1373     __ j(not_equal, &not_identical);
1374
1375     if (cc != equal) {
1376       // Check for undefined.  undefined OP undefined is false even though
1377       // undefined == undefined.
1378       Label check_for_nan;
1379       __ cmp(edx, isolate()->factory()->undefined_value());
1380       __ j(not_equal, &check_for_nan, Label::kNear);
1381       __ Move(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc))));
1382       __ ret(0);
1383       __ bind(&check_for_nan);
1384     }
1385
1386     // Test for NaN. Compare heap numbers in a general way,
1387     // to hanlde NaNs correctly.
1388     __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
1389            Immediate(isolate()->factory()->heap_number_map()));
1390     __ j(equal, &generic_heap_number_comparison, Label::kNear);
1391     if (cc != equal) {
1392       // Call runtime on identical JSObjects.  Otherwise return equal.
1393       __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
1394       __ j(above_equal, &not_identical);
1395     }
1396     __ Move(eax, Immediate(Smi::FromInt(EQUAL)));
1397     __ ret(0);
1398
1399
1400     __ bind(&not_identical);
1401   }
1402
1403   // Strict equality can quickly decide whether objects are equal.
1404   // Non-strict object equality is slower, so it is handled later in the stub.
1405   if (cc == equal && strict()) {
1406     Label slow;  // Fallthrough label.
1407     Label not_smis;
1408     // If we're doing a strict equality comparison, we don't have to do
1409     // type conversion, so we generate code to do fast comparison for objects
1410     // and oddballs. Non-smi numbers and strings still go through the usual
1411     // slow-case code.
1412     // If either is a Smi (we know that not both are), then they can only
1413     // be equal if the other is a HeapNumber. If so, use the slow case.
1414     STATIC_ASSERT(kSmiTag == 0);
1415     DCHECK_EQ(static_cast<Smi*>(0), Smi::FromInt(0));
1416     __ mov(ecx, Immediate(kSmiTagMask));
1417     __ and_(ecx, eax);
1418     __ test(ecx, edx);
1419     __ j(not_zero, &not_smis, Label::kNear);
1420     // One operand is a smi.
1421
1422     // Check whether the non-smi is a heap number.
1423     STATIC_ASSERT(kSmiTagMask == 1);
1424     // ecx still holds eax & kSmiTag, which is either zero or one.
1425     __ sub(ecx, Immediate(0x01));
1426     __ mov(ebx, edx);
1427     __ xor_(ebx, eax);
1428     __ and_(ebx, ecx);  // ebx holds either 0 or eax ^ edx.
1429     __ xor_(ebx, eax);
1430     // if eax was smi, ebx is now edx, else eax.
1431
1432     // Check if the non-smi operand is a heap number.
1433     __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
1434            Immediate(isolate()->factory()->heap_number_map()));
1435     // If heap number, handle it in the slow case.
1436     __ j(equal, &slow, Label::kNear);
1437     // Return non-equal (ebx is not zero)
1438     __ mov(eax, ebx);
1439     __ ret(0);
1440
1441     __ bind(&not_smis);
1442     // If either operand is a JSObject or an oddball value, then they are not
1443     // equal since their pointers are different
1444     // There is no test for undetectability in strict equality.
1445
1446     // Get the type of the first operand.
1447     // If the first object is a JS object, we have done pointer comparison.
1448     Label first_non_object;
1449     STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE);
1450     __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
1451     __ j(below, &first_non_object, Label::kNear);
1452
1453     // Return non-zero (eax is not zero)
1454     Label return_not_equal;
1455     STATIC_ASSERT(kHeapObjectTag != 0);
1456     __ bind(&return_not_equal);
1457     __ ret(0);
1458
1459     __ bind(&first_non_object);
1460     // Check for oddballs: true, false, null, undefined.
1461     __ CmpInstanceType(ecx, ODDBALL_TYPE);
1462     __ j(equal, &return_not_equal);
1463
1464     __ CmpObjectType(edx, FIRST_SPEC_OBJECT_TYPE, ecx);
1465     __ j(above_equal, &return_not_equal);
1466
1467     // Check for oddballs: true, false, null, undefined.
1468     __ CmpInstanceType(ecx, ODDBALL_TYPE);
1469     __ j(equal, &return_not_equal);
1470
1471     // Fall through to the general case.
1472     __ bind(&slow);
1473   }
1474
1475   // Generate the number comparison code.
1476   Label non_number_comparison;
1477   Label unordered;
1478   __ bind(&generic_heap_number_comparison);
1479   FloatingPointHelper::CheckFloatOperands(
1480       masm, &non_number_comparison, ebx);
1481   FloatingPointHelper::LoadFloatOperand(masm, eax);
1482   FloatingPointHelper::LoadFloatOperand(masm, edx);
1483   __ FCmp();
1484
1485   // Don't base result on EFLAGS when a NaN is involved.
1486   __ j(parity_even, &unordered, Label::kNear);
1487
1488   Label below_label, above_label;
1489   // Return a result of -1, 0, or 1, based on EFLAGS.
1490   __ j(below, &below_label, Label::kNear);
1491   __ j(above, &above_label, Label::kNear);
1492
1493   __ Move(eax, Immediate(0));
1494   __ ret(0);
1495
1496   __ bind(&below_label);
1497   __ mov(eax, Immediate(Smi::FromInt(-1)));
1498   __ ret(0);
1499
1500   __ bind(&above_label);
1501   __ mov(eax, Immediate(Smi::FromInt(1)));
1502   __ ret(0);
1503
1504   // If one of the numbers was NaN, then the result is always false.
1505   // The cc is never not-equal.
1506   __ bind(&unordered);
1507   DCHECK(cc != not_equal);
1508   if (cc == less || cc == less_equal) {
1509     __ mov(eax, Immediate(Smi::FromInt(1)));
1510   } else {
1511     __ mov(eax, Immediate(Smi::FromInt(-1)));
1512   }
1513   __ ret(0);
1514
1515   // The number comparison code did not provide a valid result.
1516   __ bind(&non_number_comparison);
1517
1518   // Fast negative check for internalized-to-internalized equality.
1519   Label check_for_strings;
1520   if (cc == equal) {
1521     BranchIfNotInternalizedString(masm, &check_for_strings, eax, ecx);
1522     BranchIfNotInternalizedString(masm, &check_for_strings, edx, ecx);
1523
1524     // We've already checked for object identity, so if both operands
1525     // are internalized they aren't equal. Register eax already holds a
1526     // non-zero value, which indicates not equal, so just return.
1527     __ ret(0);
1528   }
1529
1530   __ bind(&check_for_strings);
1531
1532   __ JumpIfNotBothSequentialOneByteStrings(edx, eax, ecx, ebx,
1533                                            &check_unequal_objects);
1534
1535   // Inline comparison of one-byte strings.
1536   if (cc == equal) {
1537     StringHelper::GenerateFlatOneByteStringEquals(masm, edx, eax, ecx, ebx);
1538   } else {
1539     StringHelper::GenerateCompareFlatOneByteStrings(masm, edx, eax, ecx, ebx,
1540                                                     edi);
1541   }
1542 #ifdef DEBUG
1543   __ Abort(kUnexpectedFallThroughFromStringComparison);
1544 #endif
1545
1546   __ bind(&check_unequal_objects);
1547   if (cc == equal && !strict()) {
1548     // Non-strict equality.  Objects are unequal if
1549     // they are both JSObjects and not undetectable,
1550     // and their pointers are different.
1551     Label not_both_objects;
1552     Label return_unequal;
1553     // At most one is a smi, so we can test for smi by adding the two.
1554     // A smi plus a heap object has the low bit set, a heap object plus
1555     // a heap object has the low bit clear.
1556     STATIC_ASSERT(kSmiTag == 0);
1557     STATIC_ASSERT(kSmiTagMask == 1);
1558     __ lea(ecx, Operand(eax, edx, times_1, 0));
1559     __ test(ecx, Immediate(kSmiTagMask));
1560     __ j(not_zero, &not_both_objects, Label::kNear);
1561     __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
1562     __ j(below, &not_both_objects, Label::kNear);
1563     __ CmpObjectType(edx, FIRST_SPEC_OBJECT_TYPE, ebx);
1564     __ j(below, &not_both_objects, Label::kNear);
1565     // We do not bail out after this point.  Both are JSObjects, and
1566     // they are equal if and only if both are undetectable.
1567     // The and of the undetectable flags is 1 if and only if they are equal.
1568     __ test_b(FieldOperand(ecx, Map::kBitFieldOffset),
1569               1 << Map::kIsUndetectable);
1570     __ j(zero, &return_unequal, Label::kNear);
1571     __ test_b(FieldOperand(ebx, Map::kBitFieldOffset),
1572               1 << Map::kIsUndetectable);
1573     __ j(zero, &return_unequal, Label::kNear);
1574     // The objects are both undetectable, so they both compare as the value
1575     // undefined, and are equal.
1576     __ Move(eax, Immediate(EQUAL));
1577     __ bind(&return_unequal);
1578     // Return non-equal by returning the non-zero object pointer in eax,
1579     // or return equal if we fell through to here.
1580     __ ret(0);  // rax, rdx were pushed
1581     __ bind(&not_both_objects);
1582   }
1583
1584   // Push arguments below the return address.
1585   __ pop(ecx);
1586   __ push(edx);
1587   __ push(eax);
1588
1589   // Figure out which native to call and setup the arguments.
1590   Builtins::JavaScript builtin;
1591   if (cc == equal) {
1592     builtin = strict() ? Builtins::STRICT_EQUALS : Builtins::EQUALS;
1593   } else {
1594     builtin = Builtins::COMPARE;
1595     __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc))));
1596   }
1597
1598   // Restore return address on the stack.
1599   __ push(ecx);
1600
1601   // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
1602   // tagged as a small integer.
1603   __ InvokeBuiltin(builtin, JUMP_FUNCTION);
1604
1605   __ bind(&miss);
1606   GenerateMiss(masm);
1607 }
1608
1609
1610 static void GenerateRecordCallTarget(MacroAssembler* masm) {
1611   // Cache the called function in a feedback vector slot.  Cache states
1612   // are uninitialized, monomorphic (indicated by a JSFunction), and
1613   // megamorphic.
1614   // eax : number of arguments to the construct function
1615   // ebx : Feedback vector
1616   // edx : slot in feedback vector (Smi)
1617   // edi : the function to call
1618   Isolate* isolate = masm->isolate();
1619   Label initialize, done, miss, megamorphic, not_array_function;
1620
1621   // Load the cache state into ecx.
1622   __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size,
1623                            FixedArray::kHeaderSize));
1624
1625   // A monomorphic cache hit or an already megamorphic state: invoke the
1626   // function without changing the state.
1627   __ cmp(ecx, edi);
1628   __ j(equal, &done, Label::kFar);
1629   __ cmp(ecx, Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate)));
1630   __ j(equal, &done, Label::kFar);
1631
1632   if (!FLAG_pretenuring_call_new) {
1633     // If we came here, we need to see if we are the array function.
1634     // If we didn't have a matching function, and we didn't find the megamorph
1635     // sentinel, then we have in the slot either some other function or an
1636     // AllocationSite. Do a map check on the object in ecx.
1637     Handle<Map> allocation_site_map = isolate->factory()->allocation_site_map();
1638     __ cmp(FieldOperand(ecx, 0), Immediate(allocation_site_map));
1639     __ j(not_equal, &miss);
1640
1641     // Make sure the function is the Array() function
1642     __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx);
1643     __ cmp(edi, ecx);
1644     __ j(not_equal, &megamorphic);
1645     __ jmp(&done, Label::kFar);
1646   }
1647
1648   __ bind(&miss);
1649
1650   // A monomorphic miss (i.e, here the cache is not uninitialized) goes
1651   // megamorphic.
1652   __ cmp(ecx, Immediate(TypeFeedbackVector::UninitializedSentinel(isolate)));
1653   __ j(equal, &initialize);
1654   // MegamorphicSentinel is an immortal immovable object (undefined) so no
1655   // write-barrier is needed.
1656   __ bind(&megamorphic);
1657   __ mov(
1658       FieldOperand(ebx, edx, times_half_pointer_size, FixedArray::kHeaderSize),
1659       Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate)));
1660   __ jmp(&done, Label::kFar);
1661
1662   // An uninitialized cache is patched with the function or sentinel to
1663   // indicate the ElementsKind if function is the Array constructor.
1664   __ bind(&initialize);
1665   if (!FLAG_pretenuring_call_new) {
1666     // Make sure the function is the Array() function
1667     __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx);
1668     __ cmp(edi, ecx);
1669     __ j(not_equal, &not_array_function);
1670
1671     // The target function is the Array constructor,
1672     // Create an AllocationSite if we don't already have it, store it in the
1673     // slot.
1674     {
1675       FrameScope scope(masm, StackFrame::INTERNAL);
1676
1677       // Arguments register must be smi-tagged to call out.
1678       __ SmiTag(eax);
1679       __ push(eax);
1680       __ push(edi);
1681       __ push(edx);
1682       __ push(ebx);
1683
1684       CreateAllocationSiteStub create_stub(isolate);
1685       __ CallStub(&create_stub);
1686
1687       __ pop(ebx);
1688       __ pop(edx);
1689       __ pop(edi);
1690       __ pop(eax);
1691       __ SmiUntag(eax);
1692     }
1693     __ jmp(&done);
1694
1695     __ bind(&not_array_function);
1696   }
1697
1698   __ mov(FieldOperand(ebx, edx, times_half_pointer_size,
1699                       FixedArray::kHeaderSize),
1700          edi);
1701   // We won't need edx or ebx anymore, just save edi
1702   __ push(edi);
1703   __ push(ebx);
1704   __ push(edx);
1705   __ RecordWriteArray(ebx, edi, edx, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
1706                       OMIT_SMI_CHECK);
1707   __ pop(edx);
1708   __ pop(ebx);
1709   __ pop(edi);
1710
1711   __ bind(&done);
1712 }
1713
1714
1715 static void EmitContinueIfStrictOrNative(MacroAssembler* masm, Label* cont) {
1716   // Do not transform the receiver for strict mode functions.
1717   __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
1718   __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset),
1719             1 << SharedFunctionInfo::kStrictModeBitWithinByte);
1720   __ j(not_equal, cont);
1721
1722   // Do not transform the receiver for natives (shared already in ecx).
1723   __ test_b(FieldOperand(ecx, SharedFunctionInfo::kNativeByteOffset),
1724             1 << SharedFunctionInfo::kNativeBitWithinByte);
1725   __ j(not_equal, cont);
1726 }
1727
1728
1729 static void EmitSlowCase(Isolate* isolate,
1730                          MacroAssembler* masm,
1731                          int argc,
1732                          Label* non_function) {
1733   // Check for function proxy.
1734   __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE);
1735   __ j(not_equal, non_function);
1736   __ pop(ecx);
1737   __ push(edi);  // put proxy as additional argument under return address
1738   __ push(ecx);
1739   __ Move(eax, Immediate(argc + 1));
1740   __ Move(ebx, Immediate(0));
1741   __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY);
1742   {
1743     Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline();
1744     __ jmp(adaptor, RelocInfo::CODE_TARGET);
1745   }
1746
1747   // CALL_NON_FUNCTION expects the non-function callee as receiver (instead
1748   // of the original receiver from the call site).
1749   __ bind(non_function);
1750   __ mov(Operand(esp, (argc + 1) * kPointerSize), edi);
1751   __ Move(eax, Immediate(argc));
1752   __ Move(ebx, Immediate(0));
1753   __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
1754   Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline();
1755   __ jmp(adaptor, RelocInfo::CODE_TARGET);
1756 }
1757
1758
1759 static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
1760   // Wrap the receiver and patch it back onto the stack.
1761   { FrameScope frame_scope(masm, StackFrame::INTERNAL);
1762     __ push(edi);
1763     __ push(eax);
1764     __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1765     __ pop(edi);
1766   }
1767   __ mov(Operand(esp, (argc + 1) * kPointerSize), eax);
1768   __ jmp(cont);
1769 }
1770
1771
1772 static void CallFunctionNoFeedback(MacroAssembler* masm,
1773                                    int argc, bool needs_checks,
1774                                    bool call_as_method) {
1775   // edi : the function to call
1776   Label slow, non_function, wrap, cont;
1777
1778   if (needs_checks) {
1779     // Check that the function really is a JavaScript function.
1780     __ JumpIfSmi(edi, &non_function);
1781
1782     // Goto slow case if we do not have a function.
1783     __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
1784     __ j(not_equal, &slow);
1785   }
1786
1787   // Fast-case: Just invoke the function.
1788   ParameterCount actual(argc);
1789
1790   if (call_as_method) {
1791     if (needs_checks) {
1792       EmitContinueIfStrictOrNative(masm, &cont);
1793     }
1794
1795     // Load the receiver from the stack.
1796     __ mov(eax, Operand(esp, (argc + 1) * kPointerSize));
1797
1798     if (needs_checks) {
1799       __ JumpIfSmi(eax, &wrap);
1800
1801       __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
1802       __ j(below, &wrap);
1803     } else {
1804       __ jmp(&wrap);
1805     }
1806
1807     __ bind(&cont);
1808   }
1809
1810   __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper());
1811
1812   if (needs_checks) {
1813     // Slow-case: Non-function called.
1814     __ bind(&slow);
1815     // (non_function is bound in EmitSlowCase)
1816     EmitSlowCase(masm->isolate(), masm, argc, &non_function);
1817   }
1818
1819   if (call_as_method) {
1820     __ bind(&wrap);
1821     EmitWrapCase(masm, argc, &cont);
1822   }
1823 }
1824
1825
1826 void CallFunctionStub::Generate(MacroAssembler* masm) {
1827   CallFunctionNoFeedback(masm, argc(), NeedsChecks(), CallAsMethod());
1828 }
1829
1830
1831 void CallConstructStub::Generate(MacroAssembler* masm) {
1832   // eax : number of arguments
1833   // ebx : feedback vector
1834   // edx : (only if ebx is not the megamorphic symbol) slot in feedback
1835   //       vector (Smi)
1836   // edi : constructor function
1837   Label slow, non_function_call;
1838
1839   // Check that function is not a smi.
1840   __ JumpIfSmi(edi, &non_function_call);
1841   // Check that function is a JSFunction.
1842   __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
1843   __ j(not_equal, &slow);
1844
1845   if (RecordCallTarget()) {
1846     GenerateRecordCallTarget(masm);
1847
1848     if (FLAG_pretenuring_call_new) {
1849       // Put the AllocationSite from the feedback vector into ebx.
1850       // By adding kPointerSize we encode that we know the AllocationSite
1851       // entry is at the feedback vector slot given by edx + 1.
1852       __ mov(ebx, FieldOperand(ebx, edx, times_half_pointer_size,
1853                                FixedArray::kHeaderSize + kPointerSize));
1854     } else {
1855       Label feedback_register_initialized;
1856       // Put the AllocationSite from the feedback vector into ebx, or undefined.
1857       __ mov(ebx, FieldOperand(ebx, edx, times_half_pointer_size,
1858                                FixedArray::kHeaderSize));
1859       Handle<Map> allocation_site_map =
1860           isolate()->factory()->allocation_site_map();
1861       __ cmp(FieldOperand(ebx, 0), Immediate(allocation_site_map));
1862       __ j(equal, &feedback_register_initialized);
1863       __ mov(ebx, isolate()->factory()->undefined_value());
1864       __ bind(&feedback_register_initialized);
1865     }
1866
1867     __ AssertUndefinedOrAllocationSite(ebx);
1868   }
1869
1870   if (IsSuperConstructorCall()) {
1871     __ mov(edx, Operand(esp, eax, times_pointer_size, 2 * kPointerSize));
1872   } else {
1873     // Pass original constructor to construct stub.
1874     __ mov(edx, edi);
1875   }
1876
1877   // Jump to the function-specific construct stub.
1878   Register jmp_reg = ecx;
1879   __ mov(jmp_reg, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
1880   __ mov(jmp_reg, FieldOperand(jmp_reg,
1881                                SharedFunctionInfo::kConstructStubOffset));
1882   __ lea(jmp_reg, FieldOperand(jmp_reg, Code::kHeaderSize));
1883   __ jmp(jmp_reg);
1884
1885   // edi: called object
1886   // eax: number of arguments
1887   // ecx: object map
1888   Label do_call;
1889   __ bind(&slow);
1890   __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE);
1891   __ j(not_equal, &non_function_call);
1892   __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR);
1893   __ jmp(&do_call);
1894
1895   __ bind(&non_function_call);
1896   __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
1897   __ bind(&do_call);
1898   // Set expected number of arguments to zero (not changing eax).
1899   __ Move(ebx, Immediate(0));
1900   Handle<Code> arguments_adaptor =
1901       isolate()->builtins()->ArgumentsAdaptorTrampoline();
1902   __ jmp(arguments_adaptor, RelocInfo::CODE_TARGET);
1903 }
1904
1905
1906 static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) {
1907   __ mov(vector, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1908   __ mov(vector, FieldOperand(vector, JSFunction::kSharedFunctionInfoOffset));
1909   __ mov(vector, FieldOperand(vector,
1910                               SharedFunctionInfo::kFeedbackVectorOffset));
1911 }
1912
1913
1914 void CallIC_ArrayStub::Generate(MacroAssembler* masm) {
1915   // edi - function
1916   // edx - slot id
1917   // ebx - vector
1918   Label miss;
1919   int argc = arg_count();
1920   ParameterCount actual(argc);
1921
1922   __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx);
1923   __ cmp(edi, ecx);
1924   __ j(not_equal, &miss);
1925
1926   __ mov(eax, arg_count());
1927   __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size,
1928                            FixedArray::kHeaderSize));
1929
1930   // Verify that ecx contains an AllocationSite
1931   Factory* factory = masm->isolate()->factory();
1932   __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
1933          factory->allocation_site_map());
1934   __ j(not_equal, &miss);
1935
1936   __ mov(ebx, ecx);
1937   __ mov(edx, edi);
1938   ArrayConstructorStub stub(masm->isolate(), arg_count());
1939   __ TailCallStub(&stub);
1940
1941   __ bind(&miss);
1942   GenerateMiss(masm);
1943
1944   // The slow case, we need this no matter what to complete a call after a miss.
1945   CallFunctionNoFeedback(masm,
1946                          arg_count(),
1947                          true,
1948                          CallAsMethod());
1949
1950   // Unreachable.
1951   __ int3();
1952 }
1953
1954
1955 void CallICStub::Generate(MacroAssembler* masm) {
1956   // edi - function
1957   // edx - slot id
1958   // ebx - vector
1959   Isolate* isolate = masm->isolate();
1960   const int with_types_offset =
1961       FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex);
1962   const int generic_offset =
1963       FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex);
1964   Label extra_checks_or_miss, slow_start;
1965   Label slow, non_function, wrap, cont;
1966   Label have_js_function;
1967   int argc = arg_count();
1968   ParameterCount actual(argc);
1969
1970   // The checks. First, does edi match the recorded monomorphic target?
1971   __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size,
1972                            FixedArray::kHeaderSize));
1973
1974   // We don't know that we have a weak cell. We might have a private symbol
1975   // or an AllocationSite, but the memory is safe to examine.
1976   // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to
1977   // FixedArray.
1978   // WeakCell::kValueOffset - contains a JSFunction or Smi(0)
1979   // Symbol::kHashFieldSlot - if the low bit is 1, then the hash is not
1980   // computed, meaning that it can't appear to be a pointer. If the low bit is
1981   // 0, then hash is computed, but the 0 bit prevents the field from appearing
1982   // to be a pointer.
1983   STATIC_ASSERT(WeakCell::kSize >= kPointerSize);
1984   STATIC_ASSERT(AllocationSite::kTransitionInfoOffset ==
1985                     WeakCell::kValueOffset &&
1986                 WeakCell::kValueOffset == Symbol::kHashFieldSlot);
1987
1988   __ cmp(edi, FieldOperand(ecx, WeakCell::kValueOffset));
1989   __ j(not_equal, &extra_checks_or_miss);
1990
1991   // The compare above could have been a SMI/SMI comparison. Guard against this
1992   // convincing us that we have a monomorphic JSFunction.
1993   __ JumpIfSmi(edi, &extra_checks_or_miss);
1994
1995   __ bind(&have_js_function);
1996   if (CallAsMethod()) {
1997     EmitContinueIfStrictOrNative(masm, &cont);
1998
1999     // Load the receiver from the stack.
2000     __ mov(eax, Operand(esp, (argc + 1) * kPointerSize));
2001
2002     __ JumpIfSmi(eax, &wrap);
2003
2004     __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
2005     __ j(below, &wrap);
2006
2007     __ bind(&cont);
2008   }
2009
2010   __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper());
2011
2012   __ bind(&slow);
2013   EmitSlowCase(isolate, masm, argc, &non_function);
2014
2015   if (CallAsMethod()) {
2016     __ bind(&wrap);
2017     EmitWrapCase(masm, argc, &cont);
2018   }
2019
2020   __ bind(&extra_checks_or_miss);
2021   Label uninitialized, miss;
2022
2023   __ cmp(ecx, Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate)));
2024   __ j(equal, &slow_start);
2025
2026   // The following cases attempt to handle MISS cases without going to the
2027   // runtime.
2028   if (FLAG_trace_ic) {
2029     __ jmp(&miss);
2030   }
2031
2032   __ cmp(ecx, Immediate(TypeFeedbackVector::UninitializedSentinel(isolate)));
2033   __ j(equal, &uninitialized);
2034
2035   // We are going megamorphic. If the feedback is a JSFunction, it is fine
2036   // to handle it here. More complex cases are dealt with in the runtime.
2037   __ AssertNotSmi(ecx);
2038   __ CmpObjectType(ecx, JS_FUNCTION_TYPE, ecx);
2039   __ j(not_equal, &miss);
2040   __ mov(
2041       FieldOperand(ebx, edx, times_half_pointer_size, FixedArray::kHeaderSize),
2042       Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate)));
2043   // We have to update statistics for runtime profiling.
2044   __ sub(FieldOperand(ebx, with_types_offset), Immediate(Smi::FromInt(1)));
2045   __ add(FieldOperand(ebx, generic_offset), Immediate(Smi::FromInt(1)));
2046   __ jmp(&slow_start);
2047
2048   __ bind(&uninitialized);
2049
2050   // We are going monomorphic, provided we actually have a JSFunction.
2051   __ JumpIfSmi(edi, &miss);
2052
2053   // Goto miss case if we do not have a function.
2054   __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
2055   __ j(not_equal, &miss);
2056
2057   // Make sure the function is not the Array() function, which requires special
2058   // behavior on MISS.
2059   __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx);
2060   __ cmp(edi, ecx);
2061   __ j(equal, &miss);
2062
2063   // Update stats.
2064   __ add(FieldOperand(ebx, with_types_offset), Immediate(Smi::FromInt(1)));
2065
2066   // Store the function. Use a stub since we need a frame for allocation.
2067   // ebx - vector
2068   // edx - slot
2069   // edi - function
2070   {
2071     FrameScope scope(masm, StackFrame::INTERNAL);
2072     CreateWeakCellStub create_stub(isolate);
2073     __ push(edi);
2074     __ CallStub(&create_stub);
2075     __ pop(edi);
2076   }
2077
2078   __ jmp(&have_js_function);
2079
2080   // We are here because tracing is on or we encountered a MISS case we can't
2081   // handle here.
2082   __ bind(&miss);
2083   GenerateMiss(masm);
2084
2085   // the slow case
2086   __ bind(&slow_start);
2087
2088   // Check that the function really is a JavaScript function.
2089   __ JumpIfSmi(edi, &non_function);
2090
2091   // Goto slow case if we do not have a function.
2092   __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
2093   __ j(not_equal, &slow);
2094   __ jmp(&have_js_function);
2095
2096   // Unreachable
2097   __ int3();
2098 }
2099
2100
2101 void CallICStub::GenerateMiss(MacroAssembler* masm) {
2102   FrameScope scope(masm, StackFrame::INTERNAL);
2103
2104   // Push the receiver and the function and feedback info.
2105   __ push(edi);
2106   __ push(ebx);
2107   __ push(edx);
2108
2109   // Call the entry.
2110   IC::UtilityId id = GetICState() == DEFAULT ? IC::kCallIC_Miss
2111                                              : IC::kCallIC_Customization_Miss;
2112
2113   ExternalReference miss = ExternalReference(IC_Utility(id), masm->isolate());
2114   __ CallExternalReference(miss, 3);
2115
2116   // Move result to edi and exit the internal frame.
2117   __ mov(edi, eax);
2118 }
2119
2120
2121 bool CEntryStub::NeedsImmovableCode() {
2122   return false;
2123 }
2124
2125
2126 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
2127   CEntryStub::GenerateAheadOfTime(isolate);
2128   StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
2129   StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
2130   // It is important that the store buffer overflow stubs are generated first.
2131   ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
2132   CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
2133   CreateWeakCellStub::GenerateAheadOfTime(isolate);
2134   BinaryOpICStub::GenerateAheadOfTime(isolate);
2135   BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate);
2136 }
2137
2138
2139 void CodeStub::GenerateFPStubs(Isolate* isolate) {
2140   CEntryStub save_doubles(isolate, 1, kSaveFPRegs);
2141   // Stubs might already be in the snapshot, detect that and don't regenerate,
2142   // which would lead to code stub initialization state being messed up.
2143   Code* save_doubles_code;
2144   if (!save_doubles.FindCodeInCache(&save_doubles_code)) {
2145     save_doubles_code = *(save_doubles.GetCode());
2146   }
2147   isolate->set_fp_stubs_generated(true);
2148 }
2149
2150
2151 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) {
2152   CEntryStub stub(isolate, 1, kDontSaveFPRegs);
2153   stub.GetCode();
2154 }
2155
2156
2157 void CEntryStub::Generate(MacroAssembler* masm) {
2158   // eax: number of arguments including receiver
2159   // ebx: pointer to C function  (C callee-saved)
2160   // ebp: frame pointer  (restored after C call)
2161   // esp: stack pointer  (restored after C call)
2162   // esi: current context (C callee-saved)
2163   // edi: JS function of the caller (C callee-saved)
2164
2165   ProfileEntryHookStub::MaybeCallEntryHook(masm);
2166
2167   // Enter the exit frame that transitions from JavaScript to C++.
2168   __ EnterExitFrame(save_doubles());
2169
2170   // ebx: pointer to C function  (C callee-saved)
2171   // ebp: frame pointer  (restored after C call)
2172   // esp: stack pointer  (restored after C call)
2173   // edi: number of arguments including receiver  (C callee-saved)
2174   // esi: pointer to the first argument (C callee-saved)
2175
2176   // Result returned in eax, or eax+edx if result size is 2.
2177
2178   // Check stack alignment.
2179   if (FLAG_debug_code) {
2180     __ CheckStackAlignment();
2181   }
2182
2183   // Call C function.
2184   __ mov(Operand(esp, 0 * kPointerSize), edi);  // argc.
2185   __ mov(Operand(esp, 1 * kPointerSize), esi);  // argv.
2186   __ mov(Operand(esp, 2 * kPointerSize),
2187          Immediate(ExternalReference::isolate_address(isolate())));
2188   __ call(ebx);
2189   // Result is in eax or edx:eax - do not destroy these registers!
2190
2191   // Runtime functions should not return 'the hole'.  Allowing it to escape may
2192   // lead to crashes in the IC code later.
2193   if (FLAG_debug_code) {
2194     Label okay;
2195     __ cmp(eax, isolate()->factory()->the_hole_value());
2196     __ j(not_equal, &okay, Label::kNear);
2197     __ int3();
2198     __ bind(&okay);
2199   }
2200
2201   // Check result for exception sentinel.
2202   Label exception_returned;
2203   __ cmp(eax, isolate()->factory()->exception());
2204   __ j(equal, &exception_returned);
2205
2206   // Check that there is no pending exception, otherwise we
2207   // should have returned the exception sentinel.
2208   if (FLAG_debug_code) {
2209     __ push(edx);
2210     __ mov(edx, Immediate(isolate()->factory()->the_hole_value()));
2211     Label okay;
2212     ExternalReference pending_exception_address(
2213         Isolate::kPendingExceptionAddress, isolate());
2214     __ cmp(edx, Operand::StaticVariable(pending_exception_address));
2215     // Cannot use check here as it attempts to generate call into runtime.
2216     __ j(equal, &okay, Label::kNear);
2217     __ int3();
2218     __ bind(&okay);
2219     __ pop(edx);
2220   }
2221
2222   // Exit the JavaScript to C++ exit frame.
2223   __ LeaveExitFrame(save_doubles());
2224   __ ret(0);
2225
2226   // Handling of exception.
2227   __ bind(&exception_returned);
2228
2229   ExternalReference pending_handler_context_address(
2230       Isolate::kPendingHandlerContextAddress, isolate());
2231   ExternalReference pending_handler_code_address(
2232       Isolate::kPendingHandlerCodeAddress, isolate());
2233   ExternalReference pending_handler_offset_address(
2234       Isolate::kPendingHandlerOffsetAddress, isolate());
2235   ExternalReference pending_handler_fp_address(
2236       Isolate::kPendingHandlerFPAddress, isolate());
2237   ExternalReference pending_handler_sp_address(
2238       Isolate::kPendingHandlerSPAddress, isolate());
2239
2240   // Ask the runtime for help to determine the handler. This will set eax to
2241   // contain the current pending exception, don't clobber it.
2242   ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate());
2243   {
2244     FrameScope scope(masm, StackFrame::MANUAL);
2245     __ PrepareCallCFunction(3, eax);
2246     __ mov(Operand(esp, 0 * kPointerSize), Immediate(0));  // argc.
2247     __ mov(Operand(esp, 1 * kPointerSize), Immediate(0));  // argv.
2248     __ mov(Operand(esp, 2 * kPointerSize),
2249            Immediate(ExternalReference::isolate_address(isolate())));
2250     __ CallCFunction(find_handler, 3);
2251   }
2252
2253   // Retrieve the handler context, SP and FP.
2254   __ mov(esi, Operand::StaticVariable(pending_handler_context_address));
2255   __ mov(esp, Operand::StaticVariable(pending_handler_sp_address));
2256   __ mov(ebp, Operand::StaticVariable(pending_handler_fp_address));
2257
2258   // If the handler is a JS frame, restore the context to the frame. Note that
2259   // the context will be set to (esi == 0) for non-JS frames.
2260   Label skip;
2261   __ test(esi, esi);
2262   __ j(zero, &skip, Label::kNear);
2263   __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
2264   __ bind(&skip);
2265
2266   // Compute the handler entry address and jump to it.
2267   __ mov(edi, Operand::StaticVariable(pending_handler_code_address));
2268   __ mov(edx, Operand::StaticVariable(pending_handler_offset_address));
2269   __ lea(edi, FieldOperand(edi, edx, times_1, Code::kHeaderSize));
2270   __ jmp(edi);
2271 }
2272
2273
2274 void JSEntryStub::Generate(MacroAssembler* masm) {
2275   Label invoke, handler_entry, exit;
2276   Label not_outermost_js, not_outermost_js_2;
2277
2278   ProfileEntryHookStub::MaybeCallEntryHook(masm);
2279
2280   // Set up frame.
2281   __ push(ebp);
2282   __ mov(ebp, esp);
2283
2284   // Push marker in two places.
2285   int marker = type();
2286   __ push(Immediate(Smi::FromInt(marker)));  // context slot
2287   __ push(Immediate(Smi::FromInt(marker)));  // function slot
2288   // Save callee-saved registers (C calling conventions).
2289   __ push(edi);
2290   __ push(esi);
2291   __ push(ebx);
2292
2293   // Save copies of the top frame descriptor on the stack.
2294   ExternalReference c_entry_fp(Isolate::kCEntryFPAddress, isolate());
2295   __ push(Operand::StaticVariable(c_entry_fp));
2296
2297   // If this is the outermost JS call, set js_entry_sp value.
2298   ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate());
2299   __ cmp(Operand::StaticVariable(js_entry_sp), Immediate(0));
2300   __ j(not_equal, &not_outermost_js, Label::kNear);
2301   __ mov(Operand::StaticVariable(js_entry_sp), ebp);
2302   __ push(Immediate(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)));
2303   __ jmp(&invoke, Label::kNear);
2304   __ bind(&not_outermost_js);
2305   __ push(Immediate(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME)));
2306
2307   // Jump to a faked try block that does the invoke, with a faked catch
2308   // block that sets the pending exception.
2309   __ jmp(&invoke);
2310   __ bind(&handler_entry);
2311   handler_offset_ = handler_entry.pos();
2312   // Caught exception: Store result (exception) in the pending exception
2313   // field in the JSEnv and return a failure sentinel.
2314   ExternalReference pending_exception(Isolate::kPendingExceptionAddress,
2315                                       isolate());
2316   __ mov(Operand::StaticVariable(pending_exception), eax);
2317   __ mov(eax, Immediate(isolate()->factory()->exception()));
2318   __ jmp(&exit);
2319
2320   // Invoke: Link this frame into the handler chain.
2321   __ bind(&invoke);
2322   __ PushStackHandler();
2323
2324   // Clear any pending exceptions.
2325   __ mov(edx, Immediate(isolate()->factory()->the_hole_value()));
2326   __ mov(Operand::StaticVariable(pending_exception), edx);
2327
2328   // Fake a receiver (NULL).
2329   __ push(Immediate(0));  // receiver
2330
2331   // Invoke the function by calling through JS entry trampoline builtin and
2332   // pop the faked function when we return. Notice that we cannot store a
2333   // reference to the trampoline code directly in this stub, because the
2334   // builtin stubs may not have been generated yet.
2335   if (type() == StackFrame::ENTRY_CONSTRUCT) {
2336     ExternalReference construct_entry(Builtins::kJSConstructEntryTrampoline,
2337                                       isolate());
2338     __ mov(edx, Immediate(construct_entry));
2339   } else {
2340     ExternalReference entry(Builtins::kJSEntryTrampoline, isolate());
2341     __ mov(edx, Immediate(entry));
2342   }
2343   __ mov(edx, Operand(edx, 0));  // deref address
2344   __ lea(edx, FieldOperand(edx, Code::kHeaderSize));
2345   __ call(edx);
2346
2347   // Unlink this frame from the handler chain.
2348   __ PopStackHandler();
2349
2350   __ bind(&exit);
2351   // Check if the current stack frame is marked as the outermost JS frame.
2352   __ pop(ebx);
2353   __ cmp(ebx, Immediate(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)));
2354   __ j(not_equal, &not_outermost_js_2);
2355   __ mov(Operand::StaticVariable(js_entry_sp), Immediate(0));
2356   __ bind(&not_outermost_js_2);
2357
2358   // Restore the top frame descriptor from the stack.
2359   __ pop(Operand::StaticVariable(ExternalReference(
2360       Isolate::kCEntryFPAddress, isolate())));
2361
2362   // Restore callee-saved registers (C calling conventions).
2363   __ pop(ebx);
2364   __ pop(esi);
2365   __ pop(edi);
2366   __ add(esp, Immediate(2 * kPointerSize));  // remove markers
2367
2368   // Restore frame pointer and return.
2369   __ pop(ebp);
2370   __ ret(0);
2371 }
2372
2373
2374 // Generate stub code for instanceof.
2375 // This code can patch a call site inlined cache of the instance of check,
2376 // which looks like this.
2377 //
2378 //   81 ff XX XX XX XX   cmp    edi, <the hole, patched to a map>
2379 //   75 0a               jne    <some near label>
2380 //   b8 XX XX XX XX      mov    eax, <the hole, patched to either true or false>
2381 //
2382 // If call site patching is requested the stack will have the delta from the
2383 // return address to the cmp instruction just below the return address. This
2384 // also means that call site patching can only take place with arguments in
2385 // registers. TOS looks like this when call site patching is requested
2386 //
2387 //   esp[0] : return address
2388 //   esp[4] : delta from return address to cmp instruction
2389 //
2390 void InstanceofStub::Generate(MacroAssembler* masm) {
2391   // Call site inlining and patching implies arguments in registers.
2392   DCHECK(HasArgsInRegisters() || !HasCallSiteInlineCheck());
2393
2394   // Fixed register usage throughout the stub.
2395   Register object = eax;  // Object (lhs).
2396   Register map = ebx;  // Map of the object.
2397   Register function = edx;  // Function (rhs).
2398   Register prototype = edi;  // Prototype of the function.
2399   Register scratch = ecx;
2400
2401   // Constants describing the call site code to patch.
2402   static const int kDeltaToCmpImmediate = 2;
2403   static const int kDeltaToMov = 8;
2404   static const int kDeltaToMovImmediate = 9;
2405   static const int8_t kCmpEdiOperandByte1 = bit_cast<int8_t, uint8_t>(0x3b);
2406   static const int8_t kCmpEdiOperandByte2 = bit_cast<int8_t, uint8_t>(0x3d);
2407   static const int8_t kMovEaxImmediateByte = bit_cast<int8_t, uint8_t>(0xb8);
2408
2409   DCHECK_EQ(object.code(), InstanceofStub::left().code());
2410   DCHECK_EQ(function.code(), InstanceofStub::right().code());
2411
2412   // Get the object and function - they are always both needed.
2413   Label slow, not_js_object;
2414   if (!HasArgsInRegisters()) {
2415     __ mov(object, Operand(esp, 2 * kPointerSize));
2416     __ mov(function, Operand(esp, 1 * kPointerSize));
2417   }
2418
2419   // Check that the left hand is a JS object.
2420   __ JumpIfSmi(object, &not_js_object);
2421   __ IsObjectJSObjectType(object, map, scratch, &not_js_object);
2422
2423   // If there is a call site cache don't look in the global cache, but do the
2424   // real lookup and update the call site cache.
2425   if (!HasCallSiteInlineCheck() && !ReturnTrueFalseObject()) {
2426     // Look up the function and the map in the instanceof cache.
2427     Label miss;
2428     __ CompareRoot(function, scratch, Heap::kInstanceofCacheFunctionRootIndex);
2429     __ j(not_equal, &miss, Label::kNear);
2430     __ CompareRoot(map, scratch, Heap::kInstanceofCacheMapRootIndex);
2431     __ j(not_equal, &miss, Label::kNear);
2432     __ LoadRoot(eax, Heap::kInstanceofCacheAnswerRootIndex);
2433     __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
2434     __ bind(&miss);
2435   }
2436
2437   // Get the prototype of the function.
2438   __ TryGetFunctionPrototype(function, prototype, scratch, &slow, true);
2439
2440   // Check that the function prototype is a JS object.
2441   __ JumpIfSmi(prototype, &slow);
2442   __ IsObjectJSObjectType(prototype, scratch, scratch, &slow);
2443
2444   // Update the global instanceof or call site inlined cache with the current
2445   // map and function. The cached answer will be set when it is known below.
2446   if (!HasCallSiteInlineCheck()) {
2447     __ StoreRoot(map, scratch, Heap::kInstanceofCacheMapRootIndex);
2448     __ StoreRoot(function, scratch, Heap::kInstanceofCacheFunctionRootIndex);
2449   } else {
2450     // The constants for the code patching are based on no push instructions
2451     // at the call site.
2452     DCHECK(HasArgsInRegisters());
2453     // Get return address and delta to inlined map check.
2454     __ mov(scratch, Operand(esp, 0 * kPointerSize));
2455     __ sub(scratch, Operand(esp, 1 * kPointerSize));
2456     if (FLAG_debug_code) {
2457       __ cmpb(Operand(scratch, 0), kCmpEdiOperandByte1);
2458       __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCmp1);
2459       __ cmpb(Operand(scratch, 1), kCmpEdiOperandByte2);
2460       __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCmp2);
2461     }
2462     __ mov(scratch, Operand(scratch, kDeltaToCmpImmediate));
2463     __ mov(Operand(scratch, 0), map);
2464   }
2465
2466   // Loop through the prototype chain of the object looking for the function
2467   // prototype.
2468   __ mov(scratch, FieldOperand(map, Map::kPrototypeOffset));
2469   Label loop, is_instance, is_not_instance;
2470   __ bind(&loop);
2471   __ cmp(scratch, prototype);
2472   __ j(equal, &is_instance, Label::kNear);
2473   Factory* factory = isolate()->factory();
2474   __ cmp(scratch, Immediate(factory->null_value()));
2475   __ j(equal, &is_not_instance, Label::kNear);
2476   __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
2477   __ mov(scratch, FieldOperand(scratch, Map::kPrototypeOffset));
2478   __ jmp(&loop);
2479
2480   __ bind(&is_instance);
2481   if (!HasCallSiteInlineCheck()) {
2482     __ mov(eax, Immediate(0));
2483     __ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex);
2484     if (ReturnTrueFalseObject()) {
2485       __ mov(eax, factory->true_value());
2486     }
2487   } else {
2488     // Get return address and delta to inlined map check.
2489     __ mov(eax, factory->true_value());
2490     __ mov(scratch, Operand(esp, 0 * kPointerSize));
2491     __ sub(scratch, Operand(esp, 1 * kPointerSize));
2492     if (FLAG_debug_code) {
2493       __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte);
2494       __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov);
2495     }
2496     __ mov(Operand(scratch, kDeltaToMovImmediate), eax);
2497     if (!ReturnTrueFalseObject()) {
2498       __ Move(eax, Immediate(0));
2499     }
2500   }
2501   __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
2502
2503   __ bind(&is_not_instance);
2504   if (!HasCallSiteInlineCheck()) {
2505     __ mov(eax, Immediate(Smi::FromInt(1)));
2506     __ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex);
2507     if (ReturnTrueFalseObject()) {
2508       __ mov(eax, factory->false_value());
2509     }
2510   } else {
2511     // Get return address and delta to inlined map check.
2512     __ mov(eax, factory->false_value());
2513     __ mov(scratch, Operand(esp, 0 * kPointerSize));
2514     __ sub(scratch, Operand(esp, 1 * kPointerSize));
2515     if (FLAG_debug_code) {
2516       __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte);
2517       __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov);
2518     }
2519     __ mov(Operand(scratch, kDeltaToMovImmediate), eax);
2520     if (!ReturnTrueFalseObject()) {
2521       __ Move(eax, Immediate(Smi::FromInt(1)));
2522     }
2523   }
2524   __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
2525
2526   Label object_not_null, object_not_null_or_smi;
2527   __ bind(&not_js_object);
2528   // Before null, smi and string value checks, check that the rhs is a function
2529   // as for a non-function rhs an exception needs to be thrown.
2530   __ JumpIfSmi(function, &slow, Label::kNear);
2531   __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch);
2532   __ j(not_equal, &slow, Label::kNear);
2533
2534   // Null is not instance of anything.
2535   __ cmp(object, factory->null_value());
2536   __ j(not_equal, &object_not_null, Label::kNear);
2537   if (ReturnTrueFalseObject()) {
2538     __ mov(eax, factory->false_value());
2539   } else {
2540     __ Move(eax, Immediate(Smi::FromInt(1)));
2541   }
2542   __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
2543
2544   __ bind(&object_not_null);
2545   // Smi values is not instance of anything.
2546   __ JumpIfNotSmi(object, &object_not_null_or_smi, Label::kNear);
2547   if (ReturnTrueFalseObject()) {
2548     __ mov(eax, factory->false_value());
2549   } else {
2550     __ Move(eax, Immediate(Smi::FromInt(1)));
2551   }
2552   __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
2553
2554   __ bind(&object_not_null_or_smi);
2555   // String values is not instance of anything.
2556   Condition is_string = masm->IsObjectStringType(object, scratch, scratch);
2557   __ j(NegateCondition(is_string), &slow, Label::kNear);
2558   if (ReturnTrueFalseObject()) {
2559     __ mov(eax, factory->false_value());
2560   } else {
2561     __ Move(eax, Immediate(Smi::FromInt(1)));
2562   }
2563   __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
2564
2565   // Slow-case: Go through the JavaScript implementation.
2566   __ bind(&slow);
2567   if (!ReturnTrueFalseObject()) {
2568     // Tail call the builtin which returns 0 or 1.
2569     if (HasArgsInRegisters()) {
2570       // Push arguments below return address.
2571       __ pop(scratch);
2572       __ push(object);
2573       __ push(function);
2574       __ push(scratch);
2575     }
2576     __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
2577   } else {
2578     // Call the builtin and convert 0/1 to true/false.
2579     {
2580       FrameScope scope(masm, StackFrame::INTERNAL);
2581       __ push(object);
2582       __ push(function);
2583       __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION);
2584     }
2585     Label true_value, done;
2586     __ test(eax, eax);
2587     __ j(zero, &true_value, Label::kNear);
2588     __ mov(eax, factory->false_value());
2589     __ jmp(&done, Label::kNear);
2590     __ bind(&true_value);
2591     __ mov(eax, factory->true_value());
2592     __ bind(&done);
2593     __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
2594   }
2595 }
2596
2597
2598 // -------------------------------------------------------------------------
2599 // StringCharCodeAtGenerator
2600
2601 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
2602   // If the receiver is a smi trigger the non-string case.
2603   if (check_mode_ == RECEIVER_IS_UNKNOWN) {
2604     __ JumpIfSmi(object_, receiver_not_string_);
2605
2606     // Fetch the instance type of the receiver into result register.
2607     __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset));
2608     __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
2609     // If the receiver is not a string trigger the non-string case.
2610     __ test(result_, Immediate(kIsNotStringMask));
2611     __ j(not_zero, receiver_not_string_);
2612   }
2613
2614   // If the index is non-smi trigger the non-smi case.
2615   __ JumpIfNotSmi(index_, &index_not_smi_);
2616   __ bind(&got_smi_index_);
2617
2618   // Check for index out of range.
2619   __ cmp(index_, FieldOperand(object_, String::kLengthOffset));
2620   __ j(above_equal, index_out_of_range_);
2621
2622   __ SmiUntag(index_);
2623
2624   Factory* factory = masm->isolate()->factory();
2625   StringCharLoadGenerator::Generate(
2626       masm, factory, object_, index_, result_, &call_runtime_);
2627
2628   __ SmiTag(result_);
2629   __ bind(&exit_);
2630 }
2631
2632
2633 void StringCharCodeAtGenerator::GenerateSlow(
2634     MacroAssembler* masm, EmbedMode embed_mode,
2635     const RuntimeCallHelper& call_helper) {
2636   __ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase);
2637
2638   // Index is not a smi.
2639   __ bind(&index_not_smi_);
2640   // If index is a heap number, try converting it to an integer.
2641   __ CheckMap(index_,
2642               masm->isolate()->factory()->heap_number_map(),
2643               index_not_number_,
2644               DONT_DO_SMI_CHECK);
2645   call_helper.BeforeCall(masm);
2646   if (FLAG_vector_ics && embed_mode == PART_OF_IC_HANDLER) {
2647     __ push(VectorLoadICDescriptor::VectorRegister());
2648     __ push(VectorLoadICDescriptor::SlotRegister());
2649   }
2650   __ push(object_);
2651   __ push(index_);  // Consumed by runtime conversion function.
2652   if (index_flags_ == STRING_INDEX_IS_NUMBER) {
2653     __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
2654   } else {
2655     DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
2656     // NumberToSmi discards numbers that are not exact integers.
2657     __ CallRuntime(Runtime::kNumberToSmi, 1);
2658   }
2659   if (!index_.is(eax)) {
2660     // Save the conversion result before the pop instructions below
2661     // have a chance to overwrite it.
2662     __ mov(index_, eax);
2663   }
2664   __ pop(object_);
2665   if (FLAG_vector_ics && embed_mode == PART_OF_IC_HANDLER) {
2666     __ pop(VectorLoadICDescriptor::SlotRegister());
2667     __ pop(VectorLoadICDescriptor::VectorRegister());
2668   }
2669   // Reload the instance type.
2670   __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset));
2671   __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
2672   call_helper.AfterCall(masm);
2673   // If index is still not a smi, it must be out of range.
2674   STATIC_ASSERT(kSmiTag == 0);
2675   __ JumpIfNotSmi(index_, index_out_of_range_);
2676   // Otherwise, return to the fast path.
2677   __ jmp(&got_smi_index_);
2678
2679   // Call runtime. We get here when the receiver is a string and the
2680   // index is a number, but the code of getting the actual character
2681   // is too complex (e.g., when the string needs to be flattened).
2682   __ bind(&call_runtime_);
2683   call_helper.BeforeCall(masm);
2684   __ push(object_);
2685   __ SmiTag(index_);
2686   __ push(index_);
2687   __ CallRuntime(Runtime::kStringCharCodeAtRT, 2);
2688   if (!result_.is(eax)) {
2689     __ mov(result_, eax);
2690   }
2691   call_helper.AfterCall(masm);
2692   __ jmp(&exit_);
2693
2694   __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
2695 }
2696
2697
2698 // -------------------------------------------------------------------------
2699 // StringCharFromCodeGenerator
2700
2701 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
2702   // Fast case of Heap::LookupSingleCharacterStringFromCode.
2703   STATIC_ASSERT(kSmiTag == 0);
2704   STATIC_ASSERT(kSmiShiftSize == 0);
2705   DCHECK(base::bits::IsPowerOfTwo32(String::kMaxOneByteCharCode + 1));
2706   __ test(code_,
2707           Immediate(kSmiTagMask |
2708                     ((~String::kMaxOneByteCharCode) << kSmiTagSize)));
2709   __ j(not_zero, &slow_case_);
2710
2711   Factory* factory = masm->isolate()->factory();
2712   __ Move(result_, Immediate(factory->single_character_string_cache()));
2713   STATIC_ASSERT(kSmiTag == 0);
2714   STATIC_ASSERT(kSmiTagSize == 1);
2715   STATIC_ASSERT(kSmiShiftSize == 0);
2716   // At this point code register contains smi tagged one byte char code.
2717   __ mov(result_, FieldOperand(result_,
2718                                code_, times_half_pointer_size,
2719                                FixedArray::kHeaderSize));
2720   __ cmp(result_, factory->undefined_value());
2721   __ j(equal, &slow_case_);
2722   __ bind(&exit_);
2723 }
2724
2725
2726 void StringCharFromCodeGenerator::GenerateSlow(
2727     MacroAssembler* masm,
2728     const RuntimeCallHelper& call_helper) {
2729   __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase);
2730
2731   __ bind(&slow_case_);
2732   call_helper.BeforeCall(masm);
2733   __ push(code_);
2734   __ CallRuntime(Runtime::kCharFromCode, 1);
2735   if (!result_.is(eax)) {
2736     __ mov(result_, eax);
2737   }
2738   call_helper.AfterCall(masm);
2739   __ jmp(&exit_);
2740
2741   __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
2742 }
2743
2744
2745 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm,
2746                                           Register dest,
2747                                           Register src,
2748                                           Register count,
2749                                           Register scratch,
2750                                           String::Encoding encoding) {
2751   DCHECK(!scratch.is(dest));
2752   DCHECK(!scratch.is(src));
2753   DCHECK(!scratch.is(count));
2754
2755   // Nothing to do for zero characters.
2756   Label done;
2757   __ test(count, count);
2758   __ j(zero, &done);
2759
2760   // Make count the number of bytes to copy.
2761   if (encoding == String::TWO_BYTE_ENCODING) {
2762     __ shl(count, 1);
2763   }
2764
2765   Label loop;
2766   __ bind(&loop);
2767   __ mov_b(scratch, Operand(src, 0));
2768   __ mov_b(Operand(dest, 0), scratch);
2769   __ inc(src);
2770   __ inc(dest);
2771   __ dec(count);
2772   __ j(not_zero, &loop);
2773
2774   __ bind(&done);
2775 }
2776
2777
2778 void SubStringStub::Generate(MacroAssembler* masm) {
2779   Label runtime;
2780
2781   // Stack frame on entry.
2782   //  esp[0]: return address
2783   //  esp[4]: to
2784   //  esp[8]: from
2785   //  esp[12]: string
2786
2787   // Make sure first argument is a string.
2788   __ mov(eax, Operand(esp, 3 * kPointerSize));
2789   STATIC_ASSERT(kSmiTag == 0);
2790   __ JumpIfSmi(eax, &runtime);
2791   Condition is_string = masm->IsObjectStringType(eax, ebx, ebx);
2792   __ j(NegateCondition(is_string), &runtime);
2793
2794   // eax: string
2795   // ebx: instance type
2796
2797   // Calculate length of sub string using the smi values.
2798   __ mov(ecx, Operand(esp, 1 * kPointerSize));  // To index.
2799   __ JumpIfNotSmi(ecx, &runtime);
2800   __ mov(edx, Operand(esp, 2 * kPointerSize));  // From index.
2801   __ JumpIfNotSmi(edx, &runtime);
2802   __ sub(ecx, edx);
2803   __ cmp(ecx, FieldOperand(eax, String::kLengthOffset));
2804   Label not_original_string;
2805   // Shorter than original string's length: an actual substring.
2806   __ j(below, &not_original_string, Label::kNear);
2807   // Longer than original string's length or negative: unsafe arguments.
2808   __ j(above, &runtime);
2809   // Return original string.
2810   Counters* counters = isolate()->counters();
2811   __ IncrementCounter(counters->sub_string_native(), 1);
2812   __ ret(3 * kPointerSize);
2813   __ bind(&not_original_string);
2814
2815   Label single_char;
2816   __ cmp(ecx, Immediate(Smi::FromInt(1)));
2817   __ j(equal, &single_char);
2818
2819   // eax: string
2820   // ebx: instance type
2821   // ecx: sub string length (smi)
2822   // edx: from index (smi)
2823   // Deal with different string types: update the index if necessary
2824   // and put the underlying string into edi.
2825   Label underlying_unpacked, sliced_string, seq_or_external_string;
2826   // If the string is not indirect, it can only be sequential or external.
2827   STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag));
2828   STATIC_ASSERT(kIsIndirectStringMask != 0);
2829   __ test(ebx, Immediate(kIsIndirectStringMask));
2830   __ j(zero, &seq_or_external_string, Label::kNear);
2831
2832   Factory* factory = isolate()->factory();
2833   __ test(ebx, Immediate(kSlicedNotConsMask));
2834   __ j(not_zero, &sliced_string, Label::kNear);
2835   // Cons string.  Check whether it is flat, then fetch first part.
2836   // Flat cons strings have an empty second part.
2837   __ cmp(FieldOperand(eax, ConsString::kSecondOffset),
2838          factory->empty_string());
2839   __ j(not_equal, &runtime);
2840   __ mov(edi, FieldOperand(eax, ConsString::kFirstOffset));
2841   // Update instance type.
2842   __ mov(ebx, FieldOperand(edi, HeapObject::kMapOffset));
2843   __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
2844   __ jmp(&underlying_unpacked, Label::kNear);
2845
2846   __ bind(&sliced_string);
2847   // Sliced string.  Fetch parent and adjust start index by offset.
2848   __ add(edx, FieldOperand(eax, SlicedString::kOffsetOffset));
2849   __ mov(edi, FieldOperand(eax, SlicedString::kParentOffset));
2850   // Update instance type.
2851   __ mov(ebx, FieldOperand(edi, HeapObject::kMapOffset));
2852   __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
2853   __ jmp(&underlying_unpacked, Label::kNear);
2854
2855   __ bind(&seq_or_external_string);
2856   // Sequential or external string.  Just move string to the expected register.
2857   __ mov(edi, eax);
2858
2859   __ bind(&underlying_unpacked);
2860
2861   if (FLAG_string_slices) {
2862     Label copy_routine;
2863     // edi: underlying subject string
2864     // ebx: instance type of underlying subject string
2865     // edx: adjusted start index (smi)
2866     // ecx: length (smi)
2867     __ cmp(ecx, Immediate(Smi::FromInt(SlicedString::kMinLength)));
2868     // Short slice.  Copy instead of slicing.
2869     __ j(less, &copy_routine);
2870     // Allocate new sliced string.  At this point we do not reload the instance
2871     // type including the string encoding because we simply rely on the info
2872     // provided by the original string.  It does not matter if the original
2873     // string's encoding is wrong because we always have to recheck encoding of
2874     // the newly created string's parent anyways due to externalized strings.
2875     Label two_byte_slice, set_slice_header;
2876     STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0);
2877     STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
2878     __ test(ebx, Immediate(kStringEncodingMask));
2879     __ j(zero, &two_byte_slice, Label::kNear);
2880     __ AllocateOneByteSlicedString(eax, ebx, no_reg, &runtime);
2881     __ jmp(&set_slice_header, Label::kNear);
2882     __ bind(&two_byte_slice);
2883     __ AllocateTwoByteSlicedString(eax, ebx, no_reg, &runtime);
2884     __ bind(&set_slice_header);
2885     __ mov(FieldOperand(eax, SlicedString::kLengthOffset), ecx);
2886     __ mov(FieldOperand(eax, SlicedString::kHashFieldOffset),
2887            Immediate(String::kEmptyHashField));
2888     __ mov(FieldOperand(eax, SlicedString::kParentOffset), edi);
2889     __ mov(FieldOperand(eax, SlicedString::kOffsetOffset), edx);
2890     __ IncrementCounter(counters->sub_string_native(), 1);
2891     __ ret(3 * kPointerSize);
2892
2893     __ bind(&copy_routine);
2894   }
2895
2896   // edi: underlying subject string
2897   // ebx: instance type of underlying subject string
2898   // edx: adjusted start index (smi)
2899   // ecx: length (smi)
2900   // The subject string can only be external or sequential string of either
2901   // encoding at this point.
2902   Label two_byte_sequential, runtime_drop_two, sequential_string;
2903   STATIC_ASSERT(kExternalStringTag != 0);
2904   STATIC_ASSERT(kSeqStringTag == 0);
2905   __ test_b(ebx, kExternalStringTag);
2906   __ j(zero, &sequential_string);
2907
2908   // Handle external string.
2909   // Rule out short external strings.
2910   STATIC_ASSERT(kShortExternalStringTag != 0);
2911   __ test_b(ebx, kShortExternalStringMask);
2912   __ j(not_zero, &runtime);
2913   __ mov(edi, FieldOperand(edi, ExternalString::kResourceDataOffset));
2914   // Move the pointer so that offset-wise, it looks like a sequential string.
2915   STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
2916   __ sub(edi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
2917
2918   __ bind(&sequential_string);
2919   // Stash away (adjusted) index and (underlying) string.
2920   __ push(edx);
2921   __ push(edi);
2922   __ SmiUntag(ecx);
2923   STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0);
2924   __ test_b(ebx, kStringEncodingMask);
2925   __ j(zero, &two_byte_sequential);
2926
2927   // Sequential one byte string.  Allocate the result.
2928   __ AllocateOneByteString(eax, ecx, ebx, edx, edi, &runtime_drop_two);
2929
2930   // eax: result string
2931   // ecx: result string length
2932   // Locate first character of result.
2933   __ mov(edi, eax);
2934   __ add(edi, Immediate(SeqOneByteString::kHeaderSize - kHeapObjectTag));
2935   // Load string argument and locate character of sub string start.
2936   __ pop(edx);
2937   __ pop(ebx);
2938   __ SmiUntag(ebx);
2939   __ lea(edx, FieldOperand(edx, ebx, times_1, SeqOneByteString::kHeaderSize));
2940
2941   // eax: result string
2942   // ecx: result length
2943   // edi: first character of result
2944   // edx: character of sub string start
2945   StringHelper::GenerateCopyCharacters(
2946       masm, edi, edx, ecx, ebx, String::ONE_BYTE_ENCODING);
2947   __ IncrementCounter(counters->sub_string_native(), 1);
2948   __ ret(3 * kPointerSize);
2949
2950   __ bind(&two_byte_sequential);
2951   // Sequential two-byte string.  Allocate the result.
2952   __ AllocateTwoByteString(eax, ecx, ebx, edx, edi, &runtime_drop_two);
2953
2954   // eax: result string
2955   // ecx: result string length
2956   // Locate first character of result.
2957   __ mov(edi, eax);
2958   __ add(edi,
2959          Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
2960   // Load string argument and locate character of sub string start.
2961   __ pop(edx);
2962   __ pop(ebx);
2963   // As from is a smi it is 2 times the value which matches the size of a two
2964   // byte character.
2965   STATIC_ASSERT(kSmiTag == 0);
2966   STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
2967   __ lea(edx, FieldOperand(edx, ebx, times_1, SeqTwoByteString::kHeaderSize));
2968
2969   // eax: result string
2970   // ecx: result length
2971   // edi: first character of result
2972   // edx: character of sub string start
2973   StringHelper::GenerateCopyCharacters(
2974       masm, edi, edx, ecx, ebx, String::TWO_BYTE_ENCODING);
2975   __ IncrementCounter(counters->sub_string_native(), 1);
2976   __ ret(3 * kPointerSize);
2977
2978   // Drop pushed values on the stack before tail call.
2979   __ bind(&runtime_drop_two);
2980   __ Drop(2);
2981
2982   // Just jump to runtime to create the sub string.
2983   __ bind(&runtime);
2984   __ TailCallRuntime(Runtime::kSubStringRT, 3, 1);
2985
2986   __ bind(&single_char);
2987   // eax: string
2988   // ebx: instance type
2989   // ecx: sub string length (smi)
2990   // edx: from index (smi)
2991   StringCharAtGenerator generator(eax, edx, ecx, eax, &runtime, &runtime,
2992                                   &runtime, STRING_INDEX_IS_NUMBER,
2993                                   RECEIVER_IS_STRING);
2994   generator.GenerateFast(masm);
2995   __ ret(3 * kPointerSize);
2996   generator.SkipSlow(masm, &runtime);
2997 }
2998
2999
3000 void ToNumberStub::Generate(MacroAssembler* masm) {
3001   // The ToNumber stub takes one argument in eax.
3002   Label not_smi;
3003   __ JumpIfNotSmi(eax, &not_smi, Label::kNear);
3004   __ Ret();
3005   __ bind(&not_smi);
3006
3007   Label not_heap_number;
3008   __ CompareMap(eax, masm->isolate()->factory()->heap_number_map());
3009   __ j(not_equal, &not_heap_number, Label::kNear);
3010   __ Ret();
3011   __ bind(&not_heap_number);
3012
3013   Label not_string, slow_string;
3014   __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edi);
3015   // eax: object
3016   // edi: object map
3017   __ j(above_equal, &not_string, Label::kNear);
3018   // Check if string has a cached array index.
3019   __ test(FieldOperand(eax, String::kHashFieldOffset),
3020           Immediate(String::kContainsCachedArrayIndexMask));
3021   __ j(not_zero, &slow_string, Label::kNear);
3022   __ mov(eax, FieldOperand(eax, String::kHashFieldOffset));
3023   __ IndexFromHash(eax, eax);
3024   __ Ret();
3025   __ bind(&slow_string);
3026   __ pop(ecx);   // Pop return address.
3027   __ push(eax);  // Push argument.
3028   __ push(ecx);  // Push return address.
3029   __ TailCallRuntime(Runtime::kStringToNumber, 1, 1);
3030   __ bind(&not_string);
3031
3032   Label not_oddball;
3033   __ CmpInstanceType(edi, ODDBALL_TYPE);
3034   __ j(not_equal, &not_oddball, Label::kNear);
3035   __ mov(eax, FieldOperand(eax, Oddball::kToNumberOffset));
3036   __ Ret();
3037   __ bind(&not_oddball);
3038
3039   __ pop(ecx);   // Pop return address.
3040   __ push(eax);  // Push argument.
3041   __ push(ecx);  // Push return address.
3042   __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION);
3043 }
3044
3045
3046 void StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm,
3047                                                    Register left,
3048                                                    Register right,
3049                                                    Register scratch1,
3050                                                    Register scratch2) {
3051   Register length = scratch1;
3052
3053   // Compare lengths.
3054   Label strings_not_equal, check_zero_length;
3055   __ mov(length, FieldOperand(left, String::kLengthOffset));
3056   __ cmp(length, FieldOperand(right, String::kLengthOffset));
3057   __ j(equal, &check_zero_length, Label::kNear);
3058   __ bind(&strings_not_equal);
3059   __ Move(eax, Immediate(Smi::FromInt(NOT_EQUAL)));
3060   __ ret(0);
3061
3062   // Check if the length is zero.
3063   Label compare_chars;
3064   __ bind(&check_zero_length);
3065   STATIC_ASSERT(kSmiTag == 0);
3066   __ test(length, length);
3067   __ j(not_zero, &compare_chars, Label::kNear);
3068   __ Move(eax, Immediate(Smi::FromInt(EQUAL)));
3069   __ ret(0);
3070
3071   // Compare characters.
3072   __ bind(&compare_chars);
3073   GenerateOneByteCharsCompareLoop(masm, left, right, length, scratch2,
3074                                   &strings_not_equal, Label::kNear);
3075
3076   // Characters are equal.
3077   __ Move(eax, Immediate(Smi::FromInt(EQUAL)));
3078   __ ret(0);
3079 }
3080
3081
3082 void StringHelper::GenerateCompareFlatOneByteStrings(
3083     MacroAssembler* masm, Register left, Register right, Register scratch1,
3084     Register scratch2, Register scratch3) {
3085   Counters* counters = masm->isolate()->counters();
3086   __ IncrementCounter(counters->string_compare_native(), 1);
3087
3088   // Find minimum length.
3089   Label left_shorter;
3090   __ mov(scratch1, FieldOperand(left, String::kLengthOffset));
3091   __ mov(scratch3, scratch1);
3092   __ sub(scratch3, FieldOperand(right, String::kLengthOffset));
3093
3094   Register length_delta = scratch3;
3095
3096   __ j(less_equal, &left_shorter, Label::kNear);
3097   // Right string is shorter. Change scratch1 to be length of right string.
3098   __ sub(scratch1, length_delta);
3099   __ bind(&left_shorter);
3100
3101   Register min_length = scratch1;
3102
3103   // If either length is zero, just compare lengths.
3104   Label compare_lengths;
3105   __ test(min_length, min_length);
3106   __ j(zero, &compare_lengths, Label::kNear);
3107
3108   // Compare characters.
3109   Label result_not_equal;
3110   GenerateOneByteCharsCompareLoop(masm, left, right, min_length, scratch2,
3111                                   &result_not_equal, Label::kNear);
3112
3113   // Compare lengths -  strings up to min-length are equal.
3114   __ bind(&compare_lengths);
3115   __ test(length_delta, length_delta);
3116   Label length_not_equal;
3117   __ j(not_zero, &length_not_equal, Label::kNear);
3118
3119   // Result is EQUAL.
3120   STATIC_ASSERT(EQUAL == 0);
3121   STATIC_ASSERT(kSmiTag == 0);
3122   __ Move(eax, Immediate(Smi::FromInt(EQUAL)));
3123   __ ret(0);
3124
3125   Label result_greater;
3126   Label result_less;
3127   __ bind(&length_not_equal);
3128   __ j(greater, &result_greater, Label::kNear);
3129   __ jmp(&result_less, Label::kNear);
3130   __ bind(&result_not_equal);
3131   __ j(above, &result_greater, Label::kNear);
3132   __ bind(&result_less);
3133
3134   // Result is LESS.
3135   __ Move(eax, Immediate(Smi::FromInt(LESS)));
3136   __ ret(0);
3137
3138   // Result is GREATER.
3139   __ bind(&result_greater);
3140   __ Move(eax, Immediate(Smi::FromInt(GREATER)));
3141   __ ret(0);
3142 }
3143
3144
3145 void StringHelper::GenerateOneByteCharsCompareLoop(
3146     MacroAssembler* masm, Register left, Register right, Register length,
3147     Register scratch, Label* chars_not_equal,
3148     Label::Distance chars_not_equal_near) {
3149   // Change index to run from -length to -1 by adding length to string
3150   // start. This means that loop ends when index reaches zero, which
3151   // doesn't need an additional compare.
3152   __ SmiUntag(length);
3153   __ lea(left,
3154          FieldOperand(left, length, times_1, SeqOneByteString::kHeaderSize));
3155   __ lea(right,
3156          FieldOperand(right, length, times_1, SeqOneByteString::kHeaderSize));
3157   __ neg(length);
3158   Register index = length;  // index = -length;
3159
3160   // Compare loop.
3161   Label loop;
3162   __ bind(&loop);
3163   __ mov_b(scratch, Operand(left, index, times_1, 0));
3164   __ cmpb(scratch, Operand(right, index, times_1, 0));
3165   __ j(not_equal, chars_not_equal, chars_not_equal_near);
3166   __ inc(index);
3167   __ j(not_zero, &loop);
3168 }
3169
3170
3171 void StringCompareStub::Generate(MacroAssembler* masm) {
3172   Label runtime;
3173
3174   // Stack frame on entry.
3175   //  esp[0]: return address
3176   //  esp[4]: right string
3177   //  esp[8]: left string
3178
3179   __ mov(edx, Operand(esp, 2 * kPointerSize));  // left
3180   __ mov(eax, Operand(esp, 1 * kPointerSize));  // right
3181
3182   Label not_same;
3183   __ cmp(edx, eax);
3184   __ j(not_equal, &not_same, Label::kNear);
3185   STATIC_ASSERT(EQUAL == 0);
3186   STATIC_ASSERT(kSmiTag == 0);
3187   __ Move(eax, Immediate(Smi::FromInt(EQUAL)));
3188   __ IncrementCounter(isolate()->counters()->string_compare_native(), 1);
3189   __ ret(2 * kPointerSize);
3190
3191   __ bind(&not_same);
3192
3193   // Check that both objects are sequential one-byte strings.
3194   __ JumpIfNotBothSequentialOneByteStrings(edx, eax, ecx, ebx, &runtime);
3195
3196   // Compare flat one-byte strings.
3197   // Drop arguments from the stack.
3198   __ pop(ecx);
3199   __ add(esp, Immediate(2 * kPointerSize));
3200   __ push(ecx);
3201   StringHelper::GenerateCompareFlatOneByteStrings(masm, edx, eax, ecx, ebx,
3202                                                   edi);
3203
3204   // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
3205   // tagged as a small integer.
3206   __ bind(&runtime);
3207   __ TailCallRuntime(Runtime::kStringCompareRT, 2, 1);
3208 }
3209
3210
3211 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) {
3212   // ----------- S t a t e -------------
3213   //  -- edx    : left
3214   //  -- eax    : right
3215   //  -- esp[0] : return address
3216   // -----------------------------------
3217
3218   // Load ecx with the allocation site.  We stick an undefined dummy value here
3219   // and replace it with the real allocation site later when we instantiate this
3220   // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate().
3221   __ mov(ecx, handle(isolate()->heap()->undefined_value()));
3222
3223   // Make sure that we actually patched the allocation site.
3224   if (FLAG_debug_code) {
3225     __ test(ecx, Immediate(kSmiTagMask));
3226     __ Assert(not_equal, kExpectedAllocationSite);
3227     __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
3228            isolate()->factory()->allocation_site_map());
3229     __ Assert(equal, kExpectedAllocationSite);
3230   }
3231
3232   // Tail call into the stub that handles binary operations with allocation
3233   // sites.
3234   BinaryOpWithAllocationSiteStub stub(isolate(), state());
3235   __ TailCallStub(&stub);
3236 }
3237
3238
3239 void CompareICStub::GenerateSmis(MacroAssembler* masm) {
3240   DCHECK(state() == CompareICState::SMI);
3241   Label miss;
3242   __ mov(ecx, edx);
3243   __ or_(ecx, eax);
3244   __ JumpIfNotSmi(ecx, &miss, Label::kNear);
3245
3246   if (GetCondition() == equal) {
3247     // For equality we do not care about the sign of the result.
3248     __ sub(eax, edx);
3249   } else {
3250     Label done;
3251     __ sub(edx, eax);
3252     __ j(no_overflow, &done, Label::kNear);
3253     // Correct sign of result in case of overflow.
3254     __ not_(edx);
3255     __ bind(&done);
3256     __ mov(eax, edx);
3257   }
3258   __ ret(0);
3259
3260   __ bind(&miss);
3261   GenerateMiss(masm);
3262 }
3263
3264
3265 void CompareICStub::GenerateNumbers(MacroAssembler* masm) {
3266   DCHECK(state() == CompareICState::NUMBER);
3267
3268   Label generic_stub, check_left;
3269   Label unordered, maybe_undefined1, maybe_undefined2;
3270   Label miss;
3271
3272   if (left() == CompareICState::SMI) {
3273     __ JumpIfNotSmi(edx, &miss);
3274   }
3275   if (right() == CompareICState::SMI) {
3276     __ JumpIfNotSmi(eax, &miss);
3277   }
3278
3279   // Inlining the double comparison and falling back to the general compare
3280   // stub if NaN is involved or SSE2 or CMOV is unsupported.
3281   __ JumpIfSmi(eax, &check_left, Label::kNear);
3282   __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
3283          isolate()->factory()->heap_number_map());
3284   __ j(not_equal, &maybe_undefined1, Label::kNear);
3285
3286   __ bind(&check_left);
3287   __ JumpIfSmi(edx, &generic_stub, Label::kNear);
3288   __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
3289          isolate()->factory()->heap_number_map());
3290   __ j(not_equal, &maybe_undefined2, Label::kNear);
3291
3292   __ bind(&unordered);
3293   __ bind(&generic_stub);
3294   CompareICStub stub(isolate(), op(), CompareICState::GENERIC,
3295                      CompareICState::GENERIC, CompareICState::GENERIC);
3296   __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET);
3297
3298   __ bind(&maybe_undefined1);
3299   if (Token::IsOrderedRelationalCompareOp(op())) {
3300     __ cmp(eax, Immediate(isolate()->factory()->undefined_value()));
3301     __ j(not_equal, &miss);
3302     __ JumpIfSmi(edx, &unordered);
3303     __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx);
3304     __ j(not_equal, &maybe_undefined2, Label::kNear);
3305     __ jmp(&unordered);
3306   }
3307
3308   __ bind(&maybe_undefined2);
3309   if (Token::IsOrderedRelationalCompareOp(op())) {
3310     __ cmp(edx, Immediate(isolate()->factory()->undefined_value()));
3311     __ j(equal, &unordered);
3312   }
3313
3314   __ bind(&miss);
3315   GenerateMiss(masm);
3316 }
3317
3318
3319 void CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) {
3320   DCHECK(state() == CompareICState::INTERNALIZED_STRING);
3321   DCHECK(GetCondition() == equal);
3322
3323   // Registers containing left and right operands respectively.
3324   Register left = edx;
3325   Register right = eax;
3326   Register tmp1 = ecx;
3327   Register tmp2 = ebx;
3328
3329   // Check that both operands are heap objects.
3330   Label miss;
3331   __ mov(tmp1, left);
3332   STATIC_ASSERT(kSmiTag == 0);
3333   __ and_(tmp1, right);
3334   __ JumpIfSmi(tmp1, &miss, Label::kNear);
3335
3336   // Check that both operands are internalized strings.
3337   __ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset));
3338   __ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset));
3339   __ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
3340   __ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
3341   STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
3342   __ or_(tmp1, tmp2);
3343   __ test(tmp1, Immediate(kIsNotStringMask | kIsNotInternalizedMask));
3344   __ j(not_zero, &miss, Label::kNear);
3345
3346   // Internalized strings are compared by identity.
3347   Label done;
3348   __ cmp(left, right);
3349   // Make sure eax is non-zero. At this point input operands are
3350   // guaranteed to be non-zero.
3351   DCHECK(right.is(eax));
3352   __ j(not_equal, &done, Label::kNear);
3353   STATIC_ASSERT(EQUAL == 0);
3354   STATIC_ASSERT(kSmiTag == 0);
3355   __ Move(eax, Immediate(Smi::FromInt(EQUAL)));
3356   __ bind(&done);
3357   __ ret(0);
3358
3359   __ bind(&miss);
3360   GenerateMiss(masm);
3361 }
3362
3363
3364 void CompareICStub::GenerateUniqueNames(MacroAssembler* masm) {
3365   DCHECK(state() == CompareICState::UNIQUE_NAME);
3366   DCHECK(GetCondition() == equal);
3367
3368   // Registers containing left and right operands respectively.
3369   Register left = edx;
3370   Register right = eax;
3371   Register tmp1 = ecx;
3372   Register tmp2 = ebx;
3373
3374   // Check that both operands are heap objects.
3375   Label miss;
3376   __ mov(tmp1, left);
3377   STATIC_ASSERT(kSmiTag == 0);
3378   __ and_(tmp1, right);
3379   __ JumpIfSmi(tmp1, &miss, Label::kNear);
3380
3381   // Check that both operands are unique names. This leaves the instance
3382   // types loaded in tmp1 and tmp2.
3383   __ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset));
3384   __ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset));
3385   __ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
3386   __ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
3387
3388   __ JumpIfNotUniqueNameInstanceType(tmp1, &miss, Label::kNear);
3389   __ JumpIfNotUniqueNameInstanceType(tmp2, &miss, Label::kNear);
3390
3391   // Unique names are compared by identity.
3392   Label done;
3393   __ cmp(left, right);
3394   // Make sure eax is non-zero. At this point input operands are
3395   // guaranteed to be non-zero.
3396   DCHECK(right.is(eax));
3397   __ j(not_equal, &done, Label::kNear);
3398   STATIC_ASSERT(EQUAL == 0);
3399   STATIC_ASSERT(kSmiTag == 0);
3400   __ Move(eax, Immediate(Smi::FromInt(EQUAL)));
3401   __ bind(&done);
3402   __ ret(0);
3403
3404   __ bind(&miss);
3405   GenerateMiss(masm);
3406 }
3407
3408
3409 void CompareICStub::GenerateStrings(MacroAssembler* masm) {
3410   DCHECK(state() == CompareICState::STRING);
3411   Label miss;
3412
3413   bool equality = Token::IsEqualityOp(op());
3414
3415   // Registers containing left and right operands respectively.
3416   Register left = edx;
3417   Register right = eax;
3418   Register tmp1 = ecx;
3419   Register tmp2 = ebx;
3420   Register tmp3 = edi;
3421
3422   // Check that both operands are heap objects.
3423   __ mov(tmp1, left);
3424   STATIC_ASSERT(kSmiTag == 0);
3425   __ and_(tmp1, right);
3426   __ JumpIfSmi(tmp1, &miss);
3427
3428   // Check that both operands are strings. This leaves the instance
3429   // types loaded in tmp1 and tmp2.
3430   __ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset));
3431   __ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset));
3432   __ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
3433   __ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
3434   __ mov(tmp3, tmp1);
3435   STATIC_ASSERT(kNotStringTag != 0);
3436   __ or_(tmp3, tmp2);
3437   __ test(tmp3, Immediate(kIsNotStringMask));
3438   __ j(not_zero, &miss);
3439
3440   // Fast check for identical strings.
3441   Label not_same;
3442   __ cmp(left, right);
3443   __ j(not_equal, &not_same, Label::kNear);
3444   STATIC_ASSERT(EQUAL == 0);
3445   STATIC_ASSERT(kSmiTag == 0);
3446   __ Move(eax, Immediate(Smi::FromInt(EQUAL)));
3447   __ ret(0);
3448
3449   // Handle not identical strings.
3450   __ bind(&not_same);
3451
3452   // Check that both strings are internalized. If they are, we're done
3453   // because we already know they are not identical.  But in the case of
3454   // non-equality compare, we still need to determine the order. We
3455   // also know they are both strings.
3456   if (equality) {
3457     Label do_compare;
3458     STATIC_ASSERT(kInternalizedTag == 0);
3459     __ or_(tmp1, tmp2);
3460     __ test(tmp1, Immediate(kIsNotInternalizedMask));
3461     __ j(not_zero, &do_compare, Label::kNear);
3462     // Make sure eax is non-zero. At this point input operands are
3463     // guaranteed to be non-zero.
3464     DCHECK(right.is(eax));
3465     __ ret(0);
3466     __ bind(&do_compare);
3467   }
3468
3469   // Check that both strings are sequential one-byte.
3470   Label runtime;
3471   __ JumpIfNotBothSequentialOneByteStrings(left, right, tmp1, tmp2, &runtime);
3472
3473   // Compare flat one byte strings. Returns when done.
3474   if (equality) {
3475     StringHelper::GenerateFlatOneByteStringEquals(masm, left, right, tmp1,
3476                                                   tmp2);
3477   } else {
3478     StringHelper::GenerateCompareFlatOneByteStrings(masm, left, right, tmp1,
3479                                                     tmp2, tmp3);
3480   }
3481
3482   // Handle more complex cases in runtime.
3483   __ bind(&runtime);
3484   __ pop(tmp1);  // Return address.
3485   __ push(left);
3486   __ push(right);
3487   __ push(tmp1);
3488   if (equality) {
3489     __ TailCallRuntime(Runtime::kStringEquals, 2, 1);
3490   } else {
3491     __ TailCallRuntime(Runtime::kStringCompareRT, 2, 1);
3492   }
3493
3494   __ bind(&miss);
3495   GenerateMiss(masm);
3496 }
3497
3498
3499 void CompareICStub::GenerateObjects(MacroAssembler* masm) {
3500   DCHECK(state() == CompareICState::OBJECT);
3501   Label miss;
3502   __ mov(ecx, edx);
3503   __ and_(ecx, eax);
3504   __ JumpIfSmi(ecx, &miss, Label::kNear);
3505
3506   __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx);
3507   __ j(not_equal, &miss, Label::kNear);
3508   __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx);
3509   __ j(not_equal, &miss, Label::kNear);
3510
3511   DCHECK(GetCondition() == equal);
3512   __ sub(eax, edx);
3513   __ ret(0);
3514
3515   __ bind(&miss);
3516   GenerateMiss(masm);
3517 }
3518
3519
3520 void CompareICStub::GenerateKnownObjects(MacroAssembler* masm) {
3521   Label miss;
3522   Handle<WeakCell> cell = Map::WeakCellForMap(known_map_);
3523   __ mov(ecx, edx);
3524   __ and_(ecx, eax);
3525   __ JumpIfSmi(ecx, &miss, Label::kNear);
3526
3527   __ GetWeakValue(edi, cell);
3528   __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
3529   __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
3530   __ cmp(ecx, edi);
3531   __ j(not_equal, &miss, Label::kNear);
3532   __ cmp(ebx, edi);
3533   __ j(not_equal, &miss, Label::kNear);
3534
3535   __ sub(eax, edx);
3536   __ ret(0);
3537
3538   __ bind(&miss);
3539   GenerateMiss(masm);
3540 }
3541
3542
3543 void CompareICStub::GenerateMiss(MacroAssembler* masm) {
3544   {
3545     // Call the runtime system in a fresh internal frame.
3546     ExternalReference miss = ExternalReference(IC_Utility(IC::kCompareIC_Miss),
3547                                                isolate());
3548     FrameScope scope(masm, StackFrame::INTERNAL);
3549     __ push(edx);  // Preserve edx and eax.
3550     __ push(eax);
3551     __ push(edx);  // And also use them as the arguments.
3552     __ push(eax);
3553     __ push(Immediate(Smi::FromInt(op())));
3554     __ CallExternalReference(miss, 3);
3555     // Compute the entry point of the rewritten stub.
3556     __ lea(edi, FieldOperand(eax, Code::kHeaderSize));
3557     __ pop(eax);
3558     __ pop(edx);
3559   }
3560
3561   // Do a tail call to the rewritten stub.
3562   __ jmp(edi);
3563 }
3564
3565
3566 // Helper function used to check that the dictionary doesn't contain
3567 // the property. This function may return false negatives, so miss_label
3568 // must always call a backup property check that is complete.
3569 // This function is safe to call if the receiver has fast properties.
3570 // Name must be a unique name and receiver must be a heap object.
3571 void NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
3572                                                       Label* miss,
3573                                                       Label* done,
3574                                                       Register properties,
3575                                                       Handle<Name> name,
3576                                                       Register r0) {
3577   DCHECK(name->IsUniqueName());
3578
3579   // If names of slots in range from 1 to kProbes - 1 for the hash value are
3580   // not equal to the name and kProbes-th slot is not used (its name is the
3581   // undefined value), it guarantees the hash table doesn't contain the
3582   // property. It's true even if some slots represent deleted properties
3583   // (their names are the hole value).
3584   for (int i = 0; i < kInlinedProbes; i++) {
3585     // Compute the masked index: (hash + i + i * i) & mask.
3586     Register index = r0;
3587     // Capacity is smi 2^n.
3588     __ mov(index, FieldOperand(properties, kCapacityOffset));
3589     __ dec(index);
3590     __ and_(index,
3591             Immediate(Smi::FromInt(name->Hash() +
3592                                    NameDictionary::GetProbeOffset(i))));
3593
3594     // Scale the index by multiplying by the entry size.
3595     DCHECK(NameDictionary::kEntrySize == 3);
3596     __ lea(index, Operand(index, index, times_2, 0));  // index *= 3.
3597     Register entity_name = r0;
3598     // Having undefined at this place means the name is not contained.
3599     DCHECK_EQ(kSmiTagSize, 1);
3600     __ mov(entity_name, Operand(properties, index, times_half_pointer_size,
3601                                 kElementsStartOffset - kHeapObjectTag));
3602     __ cmp(entity_name, masm->isolate()->factory()->undefined_value());
3603     __ j(equal, done);
3604
3605     // Stop if found the property.
3606     __ cmp(entity_name, Handle<Name>(name));
3607     __ j(equal, miss);
3608
3609     Label good;
3610     // Check for the hole and skip.
3611     __ cmp(entity_name, masm->isolate()->factory()->the_hole_value());
3612     __ j(equal, &good, Label::kNear);
3613
3614     // Check if the entry name is not a unique name.
3615     __ mov(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset));
3616     __ JumpIfNotUniqueNameInstanceType(
3617         FieldOperand(entity_name, Map::kInstanceTypeOffset), miss);
3618     __ bind(&good);
3619   }
3620
3621   NameDictionaryLookupStub stub(masm->isolate(), properties, r0, r0,
3622                                 NEGATIVE_LOOKUP);
3623   __ push(Immediate(Handle<Object>(name)));
3624   __ push(Immediate(name->Hash()));
3625   __ CallStub(&stub);
3626   __ test(r0, r0);
3627   __ j(not_zero, miss);
3628   __ jmp(done);
3629 }
3630
3631
3632 // Probe the name dictionary in the |elements| register. Jump to the
3633 // |done| label if a property with the given name is found leaving the
3634 // index into the dictionary in |r0|. Jump to the |miss| label
3635 // otherwise.
3636 void NameDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
3637                                                       Label* miss,
3638                                                       Label* done,
3639                                                       Register elements,
3640                                                       Register name,
3641                                                       Register r0,
3642                                                       Register r1) {
3643   DCHECK(!elements.is(r0));
3644   DCHECK(!elements.is(r1));
3645   DCHECK(!name.is(r0));
3646   DCHECK(!name.is(r1));
3647
3648   __ AssertName(name);
3649
3650   __ mov(r1, FieldOperand(elements, kCapacityOffset));
3651   __ shr(r1, kSmiTagSize);  // convert smi to int
3652   __ dec(r1);
3653
3654   // Generate an unrolled loop that performs a few probes before
3655   // giving up. Measurements done on Gmail indicate that 2 probes
3656   // cover ~93% of loads from dictionaries.
3657   for (int i = 0; i < kInlinedProbes; i++) {
3658     // Compute the masked index: (hash + i + i * i) & mask.
3659     __ mov(r0, FieldOperand(name, Name::kHashFieldOffset));
3660     __ shr(r0, Name::kHashShift);
3661     if (i > 0) {
3662       __ add(r0, Immediate(NameDictionary::GetProbeOffset(i)));
3663     }
3664     __ and_(r0, r1);
3665
3666     // Scale the index by multiplying by the entry size.
3667     DCHECK(NameDictionary::kEntrySize == 3);
3668     __ lea(r0, Operand(r0, r0, times_2, 0));  // r0 = r0 * 3
3669
3670     // Check if the key is identical to the name.
3671     __ cmp(name, Operand(elements,
3672                          r0,
3673                          times_4,
3674                          kElementsStartOffset - kHeapObjectTag));
3675     __ j(equal, done);
3676   }
3677
3678   NameDictionaryLookupStub stub(masm->isolate(), elements, r1, r0,
3679                                 POSITIVE_LOOKUP);
3680   __ push(name);
3681   __ mov(r0, FieldOperand(name, Name::kHashFieldOffset));
3682   __ shr(r0, Name::kHashShift);
3683   __ push(r0);
3684   __ CallStub(&stub);
3685
3686   __ test(r1, r1);
3687   __ j(zero, miss);
3688   __ jmp(done);
3689 }
3690
3691
3692 void NameDictionaryLookupStub::Generate(MacroAssembler* masm) {
3693   // This stub overrides SometimesSetsUpAFrame() to return false.  That means
3694   // we cannot call anything that could cause a GC from this stub.
3695   // Stack frame on entry:
3696   //  esp[0 * kPointerSize]: return address.
3697   //  esp[1 * kPointerSize]: key's hash.
3698   //  esp[2 * kPointerSize]: key.
3699   // Registers:
3700   //  dictionary_: NameDictionary to probe.
3701   //  result_: used as scratch.
3702   //  index_: will hold an index of entry if lookup is successful.
3703   //          might alias with result_.
3704   // Returns:
3705   //  result_ is zero if lookup failed, non zero otherwise.
3706
3707   Label in_dictionary, maybe_in_dictionary, not_in_dictionary;
3708
3709   Register scratch = result();
3710
3711   __ mov(scratch, FieldOperand(dictionary(), kCapacityOffset));
3712   __ dec(scratch);
3713   __ SmiUntag(scratch);
3714   __ push(scratch);
3715
3716   // If names of slots in range from 1 to kProbes - 1 for the hash value are
3717   // not equal to the name and kProbes-th slot is not used (its name is the
3718   // undefined value), it guarantees the hash table doesn't contain the
3719   // property. It's true even if some slots represent deleted properties
3720   // (their names are the null value).
3721   for (int i = kInlinedProbes; i < kTotalProbes; i++) {
3722     // Compute the masked index: (hash + i + i * i) & mask.
3723     __ mov(scratch, Operand(esp, 2 * kPointerSize));
3724     if (i > 0) {
3725       __ add(scratch, Immediate(NameDictionary::GetProbeOffset(i)));
3726     }
3727     __ and_(scratch, Operand(esp, 0));
3728
3729     // Scale the index by multiplying by the entry size.
3730     DCHECK(NameDictionary::kEntrySize == 3);
3731     __ lea(index(), Operand(scratch, scratch, times_2, 0));  // index *= 3.
3732
3733     // Having undefined at this place means the name is not contained.
3734     DCHECK_EQ(kSmiTagSize, 1);
3735     __ mov(scratch, Operand(dictionary(), index(), times_pointer_size,
3736                             kElementsStartOffset - kHeapObjectTag));
3737     __ cmp(scratch, isolate()->factory()->undefined_value());
3738     __ j(equal, &not_in_dictionary);
3739
3740     // Stop if found the property.
3741     __ cmp(scratch, Operand(esp, 3 * kPointerSize));
3742     __ j(equal, &in_dictionary);
3743
3744     if (i != kTotalProbes - 1 && mode() == NEGATIVE_LOOKUP) {
3745       // If we hit a key that is not a unique name during negative
3746       // lookup we have to bailout as this key might be equal to the
3747       // key we are looking for.
3748
3749       // Check if the entry name is not a unique name.
3750       __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
3751       __ JumpIfNotUniqueNameInstanceType(
3752           FieldOperand(scratch, Map::kInstanceTypeOffset),
3753           &maybe_in_dictionary);
3754     }
3755   }
3756
3757   __ bind(&maybe_in_dictionary);
3758   // If we are doing negative lookup then probing failure should be
3759   // treated as a lookup success. For positive lookup probing failure
3760   // should be treated as lookup failure.
3761   if (mode() == POSITIVE_LOOKUP) {
3762     __ mov(result(), Immediate(0));
3763     __ Drop(1);
3764     __ ret(2 * kPointerSize);
3765   }
3766
3767   __ bind(&in_dictionary);
3768   __ mov(result(), Immediate(1));
3769   __ Drop(1);
3770   __ ret(2 * kPointerSize);
3771
3772   __ bind(&not_in_dictionary);
3773   __ mov(result(), Immediate(0));
3774   __ Drop(1);
3775   __ ret(2 * kPointerSize);
3776 }
3777
3778
3779 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(
3780     Isolate* isolate) {
3781   StoreBufferOverflowStub stub(isolate, kDontSaveFPRegs);
3782   stub.GetCode();
3783   StoreBufferOverflowStub stub2(isolate, kSaveFPRegs);
3784   stub2.GetCode();
3785 }
3786
3787
3788 // Takes the input in 3 registers: address_ value_ and object_.  A pointer to
3789 // the value has just been written into the object, now this stub makes sure
3790 // we keep the GC informed.  The word in the object where the value has been
3791 // written is in the address register.
3792 void RecordWriteStub::Generate(MacroAssembler* masm) {
3793   Label skip_to_incremental_noncompacting;
3794   Label skip_to_incremental_compacting;
3795
3796   // The first two instructions are generated with labels so as to get the
3797   // offset fixed up correctly by the bind(Label*) call.  We patch it back and
3798   // forth between a compare instructions (a nop in this position) and the
3799   // real branch when we start and stop incremental heap marking.
3800   __ jmp(&skip_to_incremental_noncompacting, Label::kNear);
3801   __ jmp(&skip_to_incremental_compacting, Label::kFar);
3802
3803   if (remembered_set_action() == EMIT_REMEMBERED_SET) {
3804     __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(),
3805                            MacroAssembler::kReturnAtEnd);
3806   } else {
3807     __ ret(0);
3808   }
3809
3810   __ bind(&skip_to_incremental_noncompacting);
3811   GenerateIncremental(masm, INCREMENTAL);
3812
3813   __ bind(&skip_to_incremental_compacting);
3814   GenerateIncremental(masm, INCREMENTAL_COMPACTION);
3815
3816   // Initial mode of the stub is expected to be STORE_BUFFER_ONLY.
3817   // Will be checked in IncrementalMarking::ActivateGeneratedStub.
3818   masm->set_byte_at(0, kTwoByteNopInstruction);
3819   masm->set_byte_at(2, kFiveByteNopInstruction);
3820 }
3821
3822
3823 void RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) {
3824   regs_.Save(masm);
3825
3826   if (remembered_set_action() == EMIT_REMEMBERED_SET) {
3827     Label dont_need_remembered_set;
3828
3829     __ mov(regs_.scratch0(), Operand(regs_.address(), 0));
3830     __ JumpIfNotInNewSpace(regs_.scratch0(),  // Value.
3831                            regs_.scratch0(),
3832                            &dont_need_remembered_set);
3833
3834     __ CheckPageFlag(regs_.object(),
3835                      regs_.scratch0(),
3836                      1 << MemoryChunk::SCAN_ON_SCAVENGE,
3837                      not_zero,
3838                      &dont_need_remembered_set);
3839
3840     // First notify the incremental marker if necessary, then update the
3841     // remembered set.
3842     CheckNeedsToInformIncrementalMarker(
3843         masm,
3844         kUpdateRememberedSetOnNoNeedToInformIncrementalMarker,
3845         mode);
3846     InformIncrementalMarker(masm);
3847     regs_.Restore(masm);
3848     __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(),
3849                            MacroAssembler::kReturnAtEnd);
3850
3851     __ bind(&dont_need_remembered_set);
3852   }
3853
3854   CheckNeedsToInformIncrementalMarker(
3855       masm,
3856       kReturnOnNoNeedToInformIncrementalMarker,
3857       mode);
3858   InformIncrementalMarker(masm);
3859   regs_.Restore(masm);
3860   __ ret(0);
3861 }
3862
3863
3864 void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm) {
3865   regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode());
3866   int argument_count = 3;
3867   __ PrepareCallCFunction(argument_count, regs_.scratch0());
3868   __ mov(Operand(esp, 0 * kPointerSize), regs_.object());
3869   __ mov(Operand(esp, 1 * kPointerSize), regs_.address());  // Slot.
3870   __ mov(Operand(esp, 2 * kPointerSize),
3871          Immediate(ExternalReference::isolate_address(isolate())));
3872
3873   AllowExternalCallThatCantCauseGC scope(masm);
3874   __ CallCFunction(
3875       ExternalReference::incremental_marking_record_write_function(isolate()),
3876       argument_count);
3877
3878   regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode());
3879 }
3880
3881
3882 void RecordWriteStub::CheckNeedsToInformIncrementalMarker(
3883     MacroAssembler* masm,
3884     OnNoNeedToInformIncrementalMarker on_no_need,
3885     Mode mode) {
3886   Label object_is_black, need_incremental, need_incremental_pop_object;
3887
3888   __ mov(regs_.scratch0(), Immediate(~Page::kPageAlignmentMask));
3889   __ and_(regs_.scratch0(), regs_.object());
3890   __ mov(regs_.scratch1(),
3891          Operand(regs_.scratch0(),
3892                  MemoryChunk::kWriteBarrierCounterOffset));
3893   __ sub(regs_.scratch1(), Immediate(1));
3894   __ mov(Operand(regs_.scratch0(),
3895                  MemoryChunk::kWriteBarrierCounterOffset),
3896          regs_.scratch1());
3897   __ j(negative, &need_incremental);
3898
3899   // Let's look at the color of the object:  If it is not black we don't have
3900   // to inform the incremental marker.
3901   __ JumpIfBlack(regs_.object(),
3902                  regs_.scratch0(),
3903                  regs_.scratch1(),
3904                  &object_is_black,
3905                  Label::kNear);
3906
3907   regs_.Restore(masm);
3908   if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) {
3909     __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(),
3910                            MacroAssembler::kReturnAtEnd);
3911   } else {
3912     __ ret(0);
3913   }
3914
3915   __ bind(&object_is_black);
3916
3917   // Get the value from the slot.
3918   __ mov(regs_.scratch0(), Operand(regs_.address(), 0));
3919
3920   if (mode == INCREMENTAL_COMPACTION) {
3921     Label ensure_not_white;
3922
3923     __ CheckPageFlag(regs_.scratch0(),  // Contains value.
3924                      regs_.scratch1(),  // Scratch.
3925                      MemoryChunk::kEvacuationCandidateMask,
3926                      zero,
3927                      &ensure_not_white,
3928                      Label::kNear);
3929
3930     __ CheckPageFlag(regs_.object(),
3931                      regs_.scratch1(),  // Scratch.
3932                      MemoryChunk::kSkipEvacuationSlotsRecordingMask,
3933                      not_zero,
3934                      &ensure_not_white,
3935                      Label::kNear);
3936
3937     __ jmp(&need_incremental);
3938
3939     __ bind(&ensure_not_white);
3940   }
3941
3942   // We need an extra register for this, so we push the object register
3943   // temporarily.
3944   __ push(regs_.object());
3945   __ EnsureNotWhite(regs_.scratch0(),  // The value.
3946                     regs_.scratch1(),  // Scratch.
3947                     regs_.object(),  // Scratch.
3948                     &need_incremental_pop_object,
3949                     Label::kNear);
3950   __ pop(regs_.object());
3951
3952   regs_.Restore(masm);
3953   if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) {
3954     __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(),
3955                            MacroAssembler::kReturnAtEnd);
3956   } else {
3957     __ ret(0);
3958   }
3959
3960   __ bind(&need_incremental_pop_object);
3961   __ pop(regs_.object());
3962
3963   __ bind(&need_incremental);
3964
3965   // Fall through when we need to inform the incremental marker.
3966 }
3967
3968
3969 void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) {
3970   // ----------- S t a t e -------------
3971   //  -- eax    : element value to store
3972   //  -- ecx    : element index as smi
3973   //  -- esp[0] : return address
3974   //  -- esp[4] : array literal index in function
3975   //  -- esp[8] : array literal
3976   // clobbers ebx, edx, edi
3977   // -----------------------------------
3978
3979   Label element_done;
3980   Label double_elements;
3981   Label smi_element;
3982   Label slow_elements;
3983   Label slow_elements_from_double;
3984   Label fast_elements;
3985
3986   // Get array literal index, array literal and its map.
3987   __ mov(edx, Operand(esp, 1 * kPointerSize));
3988   __ mov(ebx, Operand(esp, 2 * kPointerSize));
3989   __ mov(edi, FieldOperand(ebx, JSObject::kMapOffset));
3990
3991   __ CheckFastElements(edi, &double_elements);
3992
3993   // Check for FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS elements
3994   __ JumpIfSmi(eax, &smi_element);
3995   __ CheckFastSmiElements(edi, &fast_elements, Label::kNear);
3996
3997   // Store into the array literal requires a elements transition. Call into
3998   // the runtime.
3999
4000   __ bind(&slow_elements);
4001   __ pop(edi);  // Pop return address and remember to put back later for tail
4002                 // call.
4003   __ push(ebx);
4004   __ push(ecx);
4005   __ push(eax);
4006   __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
4007   __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset));
4008   __ push(edx);
4009   __ push(edi);  // Return return address so that tail call returns to right
4010                  // place.
4011   __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1);
4012
4013   __ bind(&slow_elements_from_double);
4014   __ pop(edx);
4015   __ jmp(&slow_elements);
4016
4017   // Array literal has ElementsKind of FAST_*_ELEMENTS and value is an object.
4018   __ bind(&fast_elements);
4019   __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset));
4020   __ lea(ecx, FieldOperand(ebx, ecx, times_half_pointer_size,
4021                            FixedArrayBase::kHeaderSize));
4022   __ mov(Operand(ecx, 0), eax);
4023   // Update the write barrier for the array store.
4024   __ RecordWrite(ebx, ecx, eax, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
4025                  OMIT_SMI_CHECK);
4026   __ ret(0);
4027
4028   // Array literal has ElementsKind of FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS,
4029   // and value is Smi.
4030   __ bind(&smi_element);
4031   __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset));
4032   __ mov(FieldOperand(ebx, ecx, times_half_pointer_size,
4033                       FixedArrayBase::kHeaderSize), eax);
4034   __ ret(0);
4035
4036   // Array literal has ElementsKind of FAST_*_DOUBLE_ELEMENTS.
4037   __ bind(&double_elements);
4038
4039   __ push(edx);
4040   __ mov(edx, FieldOperand(ebx, JSObject::kElementsOffset));
4041   __ StoreNumberToDoubleElements(eax,
4042                                  edx,
4043                                  ecx,
4044                                  edi,
4045                                  &slow_elements_from_double,
4046                                  false);
4047   __ pop(edx);
4048   __ ret(0);
4049 }
4050
4051
4052 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) {
4053   CEntryStub ces(isolate(), 1, kSaveFPRegs);
4054   __ call(ces.GetCode(), RelocInfo::CODE_TARGET);
4055   int parameter_count_offset =
4056       StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset;
4057   __ mov(ebx, MemOperand(ebp, parameter_count_offset));
4058   masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE);
4059   __ pop(ecx);
4060   int additional_offset =
4061       function_mode() == JS_FUNCTION_STUB_MODE ? kPointerSize : 0;
4062   __ lea(esp, MemOperand(esp, ebx, times_pointer_size, additional_offset));
4063   __ jmp(ecx);  // Return to IC Miss stub, continuation still on stack.
4064 }
4065
4066
4067 void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
4068   EmitLoadTypeFeedbackVector(masm, VectorLoadICDescriptor::VectorRegister());
4069   VectorRawLoadStub stub(isolate(), state());
4070   stub.GenerateForTrampoline(masm);
4071 }
4072
4073
4074 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
4075   EmitLoadTypeFeedbackVector(masm, VectorLoadICDescriptor::VectorRegister());
4076   VectorRawKeyedLoadStub stub(isolate());
4077   stub.GenerateForTrampoline(masm);
4078 }
4079
4080
4081 static void HandleArrayCases(MacroAssembler* masm, Register receiver,
4082                              Register key, Register vector, Register slot,
4083                              Register feedback, bool is_polymorphic,
4084                              Label* miss) {
4085   // feedback initially contains the feedback array
4086   Label next, next_loop, prepare_next;
4087   Label load_smi_map, compare_map;
4088   Label start_polymorphic;
4089
4090   __ push(receiver);
4091   __ push(vector);
4092
4093   Register receiver_map = receiver;
4094   Register cached_map = vector;
4095
4096   // Receiver might not be a heap object.
4097   __ JumpIfSmi(receiver, &load_smi_map);
4098   __ mov(receiver_map, FieldOperand(receiver, 0));
4099   __ bind(&compare_map);
4100   __ mov(cached_map, FieldOperand(feedback, FixedArray::OffsetOfElementAt(0)));
4101
4102   // A named keyed load might have a 2 element array, all other cases can count
4103   // on an array with at least 2 {map, handler} pairs, so they can go right
4104   // into polymorphic array handling.
4105   __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset));
4106   __ j(not_equal, is_polymorphic ? &start_polymorphic : &next);
4107
4108   // found, now call handler.
4109   Register handler = feedback;
4110   __ mov(handler, FieldOperand(feedback, FixedArray::OffsetOfElementAt(1)));
4111   __ pop(vector);
4112   __ pop(receiver);
4113   __ lea(handler, FieldOperand(handler, Code::kHeaderSize));
4114   __ jmp(handler);
4115
4116   if (!is_polymorphic) {
4117     __ bind(&next);
4118     __ cmp(FieldOperand(feedback, FixedArray::kLengthOffset),
4119            Immediate(Smi::FromInt(2)));
4120     __ j(not_equal, &start_polymorphic);
4121     __ pop(vector);
4122     __ pop(receiver);
4123     __ jmp(miss);
4124   }
4125
4126   // Polymorphic, we have to loop from 2 to N
4127   __ bind(&start_polymorphic);
4128   __ push(key);
4129   Register counter = key;
4130   __ mov(counter, Immediate(Smi::FromInt(2)));
4131   __ bind(&next_loop);
4132   __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size,
4133                                   FixedArray::kHeaderSize));
4134   __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset));
4135   __ j(not_equal, &prepare_next);
4136   __ mov(handler, FieldOperand(feedback, counter, times_half_pointer_size,
4137                                FixedArray::kHeaderSize + kPointerSize));
4138   __ pop(key);
4139   __ pop(vector);
4140   __ pop(receiver);
4141   __ lea(handler, FieldOperand(handler, Code::kHeaderSize));
4142   __ jmp(handler);
4143
4144   __ bind(&prepare_next);
4145   __ add(counter, Immediate(Smi::FromInt(2)));
4146   __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset));
4147   __ j(less, &next_loop);
4148
4149   // We exhausted our array of map handler pairs.
4150   __ pop(key);
4151   __ pop(vector);
4152   __ pop(receiver);
4153   __ jmp(miss);
4154
4155   __ bind(&load_smi_map);
4156   __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex);
4157   __ jmp(&compare_map);
4158 }
4159
4160
4161 static void HandleMonomorphicCase(MacroAssembler* masm, Register receiver,
4162                                   Register key, Register vector, Register slot,
4163                                   Register weak_cell, Label* miss) {
4164   // feedback initially contains the feedback array
4165   Label compare_smi_map;
4166
4167   // Move the weak map into the weak_cell register.
4168   Register ic_map = weak_cell;
4169   __ mov(ic_map, FieldOperand(weak_cell, WeakCell::kValueOffset));
4170
4171   // Receiver might not be a heap object.
4172   __ JumpIfSmi(receiver, &compare_smi_map);
4173   __ cmp(ic_map, FieldOperand(receiver, 0));
4174   __ j(not_equal, miss);
4175   Register handler = weak_cell;
4176   __ mov(handler, FieldOperand(vector, slot, times_half_pointer_size,
4177                                FixedArray::kHeaderSize + kPointerSize));
4178   __ lea(handler, FieldOperand(handler, Code::kHeaderSize));
4179   __ jmp(handler);
4180
4181   // In microbenchmarks, it made sense to unroll this code so that the call to
4182   // the handler is duplicated for a HeapObject receiver and a Smi receiver.
4183   __ bind(&compare_smi_map);
4184   __ CompareRoot(ic_map, Heap::kHeapNumberMapRootIndex);
4185   __ j(not_equal, miss);
4186   __ mov(handler, FieldOperand(vector, slot, times_half_pointer_size,
4187                                FixedArray::kHeaderSize + kPointerSize));
4188   __ lea(handler, FieldOperand(handler, Code::kHeaderSize));
4189   __ jmp(handler);
4190 }
4191
4192
4193 void VectorRawLoadStub::Generate(MacroAssembler* masm) {
4194   GenerateImpl(masm, false);
4195 }
4196
4197
4198 void VectorRawLoadStub::GenerateForTrampoline(MacroAssembler* masm) {
4199   GenerateImpl(masm, true);
4200 }
4201
4202
4203 void VectorRawLoadStub::GenerateImpl(MacroAssembler* masm, bool in_frame) {
4204   Register receiver = VectorLoadICDescriptor::ReceiverRegister();  // edx
4205   Register name = VectorLoadICDescriptor::NameRegister();          // ecx
4206   Register vector = VectorLoadICDescriptor::VectorRegister();      // ebx
4207   Register slot = VectorLoadICDescriptor::SlotRegister();          // eax
4208   Register scratch = edi;
4209   __ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size,
4210                                FixedArray::kHeaderSize));
4211
4212   // Is it a weak cell?
4213   Label try_array;
4214   Label not_array, smi_key, key_okay, miss;
4215   __ CompareRoot(FieldOperand(scratch, 0), Heap::kWeakCellMapRootIndex);
4216   __ j(not_equal, &try_array);
4217   HandleMonomorphicCase(masm, receiver, name, vector, slot, scratch, &miss);
4218
4219   // Is it a fixed array?
4220   __ bind(&try_array);
4221   __ CompareRoot(FieldOperand(scratch, 0), Heap::kFixedArrayMapRootIndex);
4222   __ j(not_equal, &not_array);
4223   HandleArrayCases(masm, receiver, name, vector, slot, scratch, true, &miss);
4224
4225   __ bind(&not_array);
4226   __ CompareRoot(scratch, Heap::kmegamorphic_symbolRootIndex);
4227   __ j(not_equal, &miss);
4228   __ push(slot);
4229   __ push(vector);
4230   Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags(
4231       Code::ComputeHandlerFlags(Code::LOAD_IC));
4232   masm->isolate()->stub_cache()->GenerateProbe(
4233       masm, Code::LOAD_IC, code_flags, false, receiver, name, vector, scratch);
4234   __ pop(vector);
4235   __ pop(slot);
4236
4237   __ bind(&miss);
4238   LoadIC::GenerateMiss(masm);
4239 }
4240
4241
4242 void VectorRawKeyedLoadStub::Generate(MacroAssembler* masm) {
4243   GenerateImpl(masm, false);
4244 }
4245
4246
4247 void VectorRawKeyedLoadStub::GenerateForTrampoline(MacroAssembler* masm) {
4248   GenerateImpl(masm, true);
4249 }
4250
4251
4252 void VectorRawKeyedLoadStub::GenerateImpl(MacroAssembler* masm, bool in_frame) {
4253   Register receiver = VectorLoadICDescriptor::ReceiverRegister();  // edx
4254   Register key = VectorLoadICDescriptor::NameRegister();           // ecx
4255   Register vector = VectorLoadICDescriptor::VectorRegister();      // ebx
4256   Register slot = VectorLoadICDescriptor::SlotRegister();          // eax
4257   Register feedback = edi;
4258   __ mov(feedback, FieldOperand(vector, slot, times_half_pointer_size,
4259                                 FixedArray::kHeaderSize));
4260   // Is it a weak cell?
4261   Label try_array;
4262   Label not_array, smi_key, key_okay, miss;
4263   __ CompareRoot(FieldOperand(feedback, 0), Heap::kWeakCellMapRootIndex);
4264   __ j(not_equal, &try_array);
4265   HandleMonomorphicCase(masm, receiver, key, vector, slot, feedback, &miss);
4266
4267   __ bind(&try_array);
4268   // Is it a fixed array?
4269   __ CompareRoot(FieldOperand(feedback, 0), Heap::kFixedArrayMapRootIndex);
4270   __ j(not_equal, &not_array);
4271
4272   // We have a polymorphic element handler.
4273   Label polymorphic, try_poly_name;
4274   __ bind(&polymorphic);
4275   HandleArrayCases(masm, receiver, key, vector, slot, feedback, true, &miss);
4276
4277   __ bind(&not_array);
4278   // Is it generic?
4279   __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex);
4280   __ j(not_equal, &try_poly_name);
4281   Handle<Code> megamorphic_stub =
4282       KeyedLoadIC::ChooseMegamorphicStub(masm->isolate());
4283   __ jmp(megamorphic_stub, RelocInfo::CODE_TARGET);
4284
4285   __ bind(&try_poly_name);
4286   // We might have a name in feedback, and a fixed array in the next slot.
4287   __ cmp(key, feedback);
4288   __ j(not_equal, &miss);
4289   // If the name comparison succeeded, we know we have a fixed array with
4290   // at least one map/handler pair.
4291   __ mov(feedback, FieldOperand(vector, slot, times_half_pointer_size,
4292                                 FixedArray::kHeaderSize + kPointerSize));
4293   HandleArrayCases(masm, receiver, key, vector, slot, feedback, false, &miss);
4294
4295   __ bind(&miss);
4296   KeyedLoadIC::GenerateMiss(masm);
4297 }
4298
4299
4300 void CallICTrampolineStub::Generate(MacroAssembler* masm) {
4301   EmitLoadTypeFeedbackVector(masm, ebx);
4302   CallICStub stub(isolate(), state());
4303   __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET);
4304 }
4305
4306
4307 void CallIC_ArrayTrampolineStub::Generate(MacroAssembler* masm) {
4308   EmitLoadTypeFeedbackVector(masm, ebx);
4309   CallIC_ArrayStub stub(isolate(), state());
4310   __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET);
4311 }
4312
4313
4314 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) {
4315   if (masm->isolate()->function_entry_hook() != NULL) {
4316     ProfileEntryHookStub stub(masm->isolate());
4317     masm->CallStub(&stub);
4318   }
4319 }
4320
4321
4322 void ProfileEntryHookStub::Generate(MacroAssembler* masm) {
4323   // Save volatile registers.
4324   const int kNumSavedRegisters = 3;
4325   __ push(eax);
4326   __ push(ecx);
4327   __ push(edx);
4328
4329   // Calculate and push the original stack pointer.
4330   __ lea(eax, Operand(esp, (kNumSavedRegisters + 1) * kPointerSize));
4331   __ push(eax);
4332
4333   // Retrieve our return address and use it to calculate the calling
4334   // function's address.
4335   __ mov(eax, Operand(esp, (kNumSavedRegisters + 1) * kPointerSize));
4336   __ sub(eax, Immediate(Assembler::kCallInstructionLength));
4337   __ push(eax);
4338
4339   // Call the entry hook.
4340   DCHECK(isolate()->function_entry_hook() != NULL);
4341   __ call(FUNCTION_ADDR(isolate()->function_entry_hook()),
4342           RelocInfo::RUNTIME_ENTRY);
4343   __ add(esp, Immediate(2 * kPointerSize));
4344
4345   // Restore ecx.
4346   __ pop(edx);
4347   __ pop(ecx);
4348   __ pop(eax);
4349
4350   __ ret(0);
4351 }
4352
4353
4354 template<class T>
4355 static void CreateArrayDispatch(MacroAssembler* masm,
4356                                 AllocationSiteOverrideMode mode) {
4357   if (mode == DISABLE_ALLOCATION_SITES) {
4358     T stub(masm->isolate(),
4359            GetInitialFastElementsKind(),
4360            mode);
4361     __ TailCallStub(&stub);
4362   } else if (mode == DONT_OVERRIDE) {
4363     int last_index = GetSequenceIndexFromFastElementsKind(
4364         TERMINAL_FAST_ELEMENTS_KIND);
4365     for (int i = 0; i <= last_index; ++i) {
4366       Label next;
4367       ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
4368       __ cmp(edx, kind);
4369       __ j(not_equal, &next);
4370       T stub(masm->isolate(), kind);
4371       __ TailCallStub(&stub);
4372       __ bind(&next);
4373     }
4374
4375     // If we reached this point there is a problem.
4376     __ Abort(kUnexpectedElementsKindInArrayConstructor);
4377   } else {
4378     UNREACHABLE();
4379   }
4380 }
4381
4382
4383 static void CreateArrayDispatchOneArgument(MacroAssembler* masm,
4384                                            AllocationSiteOverrideMode mode) {
4385   // ebx - allocation site (if mode != DISABLE_ALLOCATION_SITES)
4386   // edx - kind (if mode != DISABLE_ALLOCATION_SITES)
4387   // eax - number of arguments
4388   // edi - constructor?
4389   // esp[0] - return address
4390   // esp[4] - last argument
4391   Label normal_sequence;
4392   if (mode == DONT_OVERRIDE) {
4393     DCHECK(FAST_SMI_ELEMENTS == 0);
4394     DCHECK(FAST_HOLEY_SMI_ELEMENTS == 1);
4395     DCHECK(FAST_ELEMENTS == 2);
4396     DCHECK(FAST_HOLEY_ELEMENTS == 3);
4397     DCHECK(FAST_DOUBLE_ELEMENTS == 4);
4398     DCHECK(FAST_HOLEY_DOUBLE_ELEMENTS == 5);
4399
4400     // is the low bit set? If so, we are holey and that is good.
4401     __ test_b(edx, 1);
4402     __ j(not_zero, &normal_sequence);
4403   }
4404
4405   // look at the first argument
4406   __ mov(ecx, Operand(esp, kPointerSize));
4407   __ test(ecx, ecx);
4408   __ j(zero, &normal_sequence);
4409
4410   if (mode == DISABLE_ALLOCATION_SITES) {
4411     ElementsKind initial = GetInitialFastElementsKind();
4412     ElementsKind holey_initial = GetHoleyElementsKind(initial);
4413
4414     ArraySingleArgumentConstructorStub stub_holey(masm->isolate(),
4415                                                   holey_initial,
4416                                                   DISABLE_ALLOCATION_SITES);
4417     __ TailCallStub(&stub_holey);
4418
4419     __ bind(&normal_sequence);
4420     ArraySingleArgumentConstructorStub stub(masm->isolate(),
4421                                             initial,
4422                                             DISABLE_ALLOCATION_SITES);
4423     __ TailCallStub(&stub);
4424   } else if (mode == DONT_OVERRIDE) {
4425     // We are going to create a holey array, but our kind is non-holey.
4426     // Fix kind and retry.
4427     __ inc(edx);
4428
4429     if (FLAG_debug_code) {
4430       Handle<Map> allocation_site_map =
4431           masm->isolate()->factory()->allocation_site_map();
4432       __ cmp(FieldOperand(ebx, 0), Immediate(allocation_site_map));
4433       __ Assert(equal, kExpectedAllocationSite);
4434     }
4435
4436     // Save the resulting elements kind in type info. We can't just store r3
4437     // in the AllocationSite::transition_info field because elements kind is
4438     // restricted to a portion of the field...upper bits need to be left alone.
4439     STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
4440     __ add(FieldOperand(ebx, AllocationSite::kTransitionInfoOffset),
4441            Immediate(Smi::FromInt(kFastElementsKindPackedToHoley)));
4442
4443     __ bind(&normal_sequence);
4444     int last_index = GetSequenceIndexFromFastElementsKind(
4445         TERMINAL_FAST_ELEMENTS_KIND);
4446     for (int i = 0; i <= last_index; ++i) {
4447       Label next;
4448       ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
4449       __ cmp(edx, kind);
4450       __ j(not_equal, &next);
4451       ArraySingleArgumentConstructorStub stub(masm->isolate(), kind);
4452       __ TailCallStub(&stub);
4453       __ bind(&next);
4454     }
4455
4456     // If we reached this point there is a problem.
4457     __ Abort(kUnexpectedElementsKindInArrayConstructor);
4458   } else {
4459     UNREACHABLE();
4460   }
4461 }
4462
4463
4464 template<class T>
4465 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) {
4466   int to_index = GetSequenceIndexFromFastElementsKind(
4467       TERMINAL_FAST_ELEMENTS_KIND);
4468   for (int i = 0; i <= to_index; ++i) {
4469     ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
4470     T stub(isolate, kind);
4471     stub.GetCode();
4472     if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) {
4473       T stub1(isolate, kind, DISABLE_ALLOCATION_SITES);
4474       stub1.GetCode();
4475     }
4476   }
4477 }
4478
4479
4480 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) {
4481   ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>(
4482       isolate);
4483   ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>(
4484       isolate);
4485   ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>(
4486       isolate);
4487 }
4488
4489
4490 void InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(
4491     Isolate* isolate) {
4492   ElementsKind kinds[2] = { FAST_ELEMENTS, FAST_HOLEY_ELEMENTS };
4493   for (int i = 0; i < 2; i++) {
4494     // For internal arrays we only need a few things
4495     InternalArrayNoArgumentConstructorStub stubh1(isolate, kinds[i]);
4496     stubh1.GetCode();
4497     InternalArraySingleArgumentConstructorStub stubh2(isolate, kinds[i]);
4498     stubh2.GetCode();
4499     InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]);
4500     stubh3.GetCode();
4501   }
4502 }
4503
4504
4505 void ArrayConstructorStub::GenerateDispatchToArrayStub(
4506     MacroAssembler* masm,
4507     AllocationSiteOverrideMode mode) {
4508   if (argument_count() == ANY) {
4509     Label not_zero_case, not_one_case;
4510     __ test(eax, eax);
4511     __ j(not_zero, &not_zero_case);
4512     CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
4513
4514     __ bind(&not_zero_case);
4515     __ cmp(eax, 1);
4516     __ j(greater, &not_one_case);
4517     CreateArrayDispatchOneArgument(masm, mode);
4518
4519     __ bind(&not_one_case);
4520     CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
4521   } else if (argument_count() == NONE) {
4522     CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
4523   } else if (argument_count() == ONE) {
4524     CreateArrayDispatchOneArgument(masm, mode);
4525   } else if (argument_count() == MORE_THAN_ONE) {
4526     CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
4527   } else {
4528     UNREACHABLE();
4529   }
4530 }
4531
4532
4533 void ArrayConstructorStub::Generate(MacroAssembler* masm) {
4534   // ----------- S t a t e -------------
4535   //  -- eax : argc (only if argument_count() is ANY or MORE_THAN_ONE)
4536   //  -- ebx : AllocationSite or undefined
4537   //  -- edi : constructor
4538   //  -- edx : Original constructor
4539   //  -- esp[0] : return address
4540   //  -- esp[4] : last argument
4541   // -----------------------------------
4542   if (FLAG_debug_code) {
4543     // The array construct code is only set for the global and natives
4544     // builtin Array functions which always have maps.
4545
4546     // Initial map for the builtin Array function should be a map.
4547     __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
4548     // Will both indicate a NULL and a Smi.
4549     __ test(ecx, Immediate(kSmiTagMask));
4550     __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction);
4551     __ CmpObjectType(ecx, MAP_TYPE, ecx);
4552     __ Assert(equal, kUnexpectedInitialMapForArrayFunction);
4553
4554     // We should either have undefined in ebx or a valid AllocationSite
4555     __ AssertUndefinedOrAllocationSite(ebx);
4556   }
4557
4558   Label subclassing;
4559
4560   __ cmp(edx, edi);
4561   __ j(not_equal, &subclassing);
4562
4563   Label no_info;
4564   // If the feedback vector is the undefined value call an array constructor
4565   // that doesn't use AllocationSites.
4566   __ cmp(ebx, isolate()->factory()->undefined_value());
4567   __ j(equal, &no_info);
4568
4569   // Only look at the lower 16 bits of the transition info.
4570   __ mov(edx, FieldOperand(ebx, AllocationSite::kTransitionInfoOffset));
4571   __ SmiUntag(edx);
4572   STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
4573   __ and_(edx, Immediate(AllocationSite::ElementsKindBits::kMask));
4574   GenerateDispatchToArrayStub(masm, DONT_OVERRIDE);
4575
4576   __ bind(&no_info);
4577   GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES);
4578
4579   // Subclassing.
4580   __ bind(&subclassing);
4581   __ pop(ecx);  // return address.
4582   __ push(edi);
4583   __ push(edx);
4584
4585   // Adjust argc.
4586   switch (argument_count()) {
4587     case ANY:
4588     case MORE_THAN_ONE:
4589       __ add(eax, Immediate(2));
4590       break;
4591     case NONE:
4592       __ mov(eax, Immediate(2));
4593       break;
4594     case ONE:
4595       __ mov(eax, Immediate(3));
4596       break;
4597   }
4598
4599   __ push(ecx);
4600   __ JumpToExternalReference(
4601       ExternalReference(Runtime::kArrayConstructorWithSubclassing, isolate()));
4602 }
4603
4604
4605 void InternalArrayConstructorStub::GenerateCase(
4606     MacroAssembler* masm, ElementsKind kind) {
4607   Label not_zero_case, not_one_case;
4608   Label normal_sequence;
4609
4610   __ test(eax, eax);
4611   __ j(not_zero, &not_zero_case);
4612   InternalArrayNoArgumentConstructorStub stub0(isolate(), kind);
4613   __ TailCallStub(&stub0);
4614
4615   __ bind(&not_zero_case);
4616   __ cmp(eax, 1);
4617   __ j(greater, &not_one_case);
4618
4619   if (IsFastPackedElementsKind(kind)) {
4620     // We might need to create a holey array
4621     // look at the first argument
4622     __ mov(ecx, Operand(esp, kPointerSize));
4623     __ test(ecx, ecx);
4624     __ j(zero, &normal_sequence);
4625
4626     InternalArraySingleArgumentConstructorStub
4627         stub1_holey(isolate(), GetHoleyElementsKind(kind));
4628     __ TailCallStub(&stub1_holey);
4629   }
4630
4631   __ bind(&normal_sequence);
4632   InternalArraySingleArgumentConstructorStub stub1(isolate(), kind);
4633   __ TailCallStub(&stub1);
4634
4635   __ bind(&not_one_case);
4636   InternalArrayNArgumentsConstructorStub stubN(isolate(), kind);
4637   __ TailCallStub(&stubN);
4638 }
4639
4640
4641 void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
4642   // ----------- S t a t e -------------
4643   //  -- eax : argc
4644   //  -- edi : constructor
4645   //  -- esp[0] : return address
4646   //  -- esp[4] : last argument
4647   // -----------------------------------
4648
4649   if (FLAG_debug_code) {
4650     // The array construct code is only set for the global and natives
4651     // builtin Array functions which always have maps.
4652
4653     // Initial map for the builtin Array function should be a map.
4654     __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
4655     // Will both indicate a NULL and a Smi.
4656     __ test(ecx, Immediate(kSmiTagMask));
4657     __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction);
4658     __ CmpObjectType(ecx, MAP_TYPE, ecx);
4659     __ Assert(equal, kUnexpectedInitialMapForArrayFunction);
4660   }
4661
4662   // Figure out the right elements kind
4663   __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
4664
4665   // Load the map's "bit field 2" into |result|. We only need the first byte,
4666   // but the following masking takes care of that anyway.
4667   __ mov(ecx, FieldOperand(ecx, Map::kBitField2Offset));
4668   // Retrieve elements_kind from bit field 2.
4669   __ DecodeField<Map::ElementsKindBits>(ecx);
4670
4671   if (FLAG_debug_code) {
4672     Label done;
4673     __ cmp(ecx, Immediate(FAST_ELEMENTS));
4674     __ j(equal, &done);
4675     __ cmp(ecx, Immediate(FAST_HOLEY_ELEMENTS));
4676     __ Assert(equal,
4677               kInvalidElementsKindForInternalArrayOrInternalPackedArray);
4678     __ bind(&done);
4679   }
4680
4681   Label fast_elements_case;
4682   __ cmp(ecx, Immediate(FAST_ELEMENTS));
4683   __ j(equal, &fast_elements_case);
4684   GenerateCase(masm, FAST_HOLEY_ELEMENTS);
4685
4686   __ bind(&fast_elements_case);
4687   GenerateCase(masm, FAST_ELEMENTS);
4688 }
4689
4690
4691 // Generates an Operand for saving parameters after PrepareCallApiFunction.
4692 static Operand ApiParameterOperand(int index) {
4693   return Operand(esp, index * kPointerSize);
4694 }
4695
4696
4697 // Prepares stack to put arguments (aligns and so on). Reserves
4698 // space for return value if needed (assumes the return value is a handle).
4699 // Arguments must be stored in ApiParameterOperand(0), ApiParameterOperand(1)
4700 // etc. Saves context (esi). If space was reserved for return value then
4701 // stores the pointer to the reserved slot into esi.
4702 static void PrepareCallApiFunction(MacroAssembler* masm, int argc) {
4703   __ EnterApiExitFrame(argc);
4704   if (__ emit_debug_code()) {
4705     __ mov(esi, Immediate(bit_cast<int32_t>(kZapValue)));
4706   }
4707 }
4708
4709
4710 // Calls an API function.  Allocates HandleScope, extracts returned value
4711 // from handle and propagates exceptions.  Clobbers ebx, edi and
4712 // caller-save registers.  Restores context.  On return removes
4713 // stack_space * kPointerSize (GCed).
4714 static void CallApiFunctionAndReturn(MacroAssembler* masm,
4715                                      Register function_address,
4716                                      ExternalReference thunk_ref,
4717                                      Operand thunk_last_arg, int stack_space,
4718                                      Operand* stack_space_operand,
4719                                      Operand return_value_operand,
4720                                      Operand* context_restore_operand) {
4721   Isolate* isolate = masm->isolate();
4722
4723   ExternalReference next_address =
4724       ExternalReference::handle_scope_next_address(isolate);
4725   ExternalReference limit_address =
4726       ExternalReference::handle_scope_limit_address(isolate);
4727   ExternalReference level_address =
4728       ExternalReference::handle_scope_level_address(isolate);
4729
4730   DCHECK(edx.is(function_address));
4731   // Allocate HandleScope in callee-save registers.
4732   __ mov(ebx, Operand::StaticVariable(next_address));
4733   __ mov(edi, Operand::StaticVariable(limit_address));
4734   __ add(Operand::StaticVariable(level_address), Immediate(1));
4735
4736   if (FLAG_log_timer_events) {
4737     FrameScope frame(masm, StackFrame::MANUAL);
4738     __ PushSafepointRegisters();
4739     __ PrepareCallCFunction(1, eax);
4740     __ mov(Operand(esp, 0),
4741            Immediate(ExternalReference::isolate_address(isolate)));
4742     __ CallCFunction(ExternalReference::log_enter_external_function(isolate),
4743                      1);
4744     __ PopSafepointRegisters();
4745   }
4746
4747
4748   Label profiler_disabled;
4749   Label end_profiler_check;
4750   __ mov(eax, Immediate(ExternalReference::is_profiling_address(isolate)));
4751   __ cmpb(Operand(eax, 0), 0);
4752   __ j(zero, &profiler_disabled);
4753
4754   // Additional parameter is the address of the actual getter function.
4755   __ mov(thunk_last_arg, function_address);
4756   // Call the api function.
4757   __ mov(eax, Immediate(thunk_ref));
4758   __ call(eax);
4759   __ jmp(&end_profiler_check);
4760
4761   __ bind(&profiler_disabled);
4762   // Call the api function.
4763   __ call(function_address);
4764   __ bind(&end_profiler_check);
4765
4766   if (FLAG_log_timer_events) {
4767     FrameScope frame(masm, StackFrame::MANUAL);
4768     __ PushSafepointRegisters();
4769     __ PrepareCallCFunction(1, eax);
4770     __ mov(Operand(esp, 0),
4771            Immediate(ExternalReference::isolate_address(isolate)));
4772     __ CallCFunction(ExternalReference::log_leave_external_function(isolate),
4773                      1);
4774     __ PopSafepointRegisters();
4775   }
4776
4777   Label prologue;
4778   // Load the value from ReturnValue
4779   __ mov(eax, return_value_operand);
4780
4781   Label promote_scheduled_exception;
4782   Label delete_allocated_handles;
4783   Label leave_exit_frame;
4784
4785   __ bind(&prologue);
4786   // No more valid handles (the result handle was the last one). Restore
4787   // previous handle scope.
4788   __ mov(Operand::StaticVariable(next_address), ebx);
4789   __ sub(Operand::StaticVariable(level_address), Immediate(1));
4790   __ Assert(above_equal, kInvalidHandleScopeLevel);
4791   __ cmp(edi, Operand::StaticVariable(limit_address));
4792   __ j(not_equal, &delete_allocated_handles);
4793
4794   // Leave the API exit frame.
4795   __ bind(&leave_exit_frame);
4796   bool restore_context = context_restore_operand != NULL;
4797   if (restore_context) {
4798     __ mov(esi, *context_restore_operand);
4799   }
4800   if (stack_space_operand != nullptr) {
4801     __ mov(ebx, *stack_space_operand);
4802   }
4803   __ LeaveApiExitFrame(!restore_context);
4804
4805   // Check if the function scheduled an exception.
4806   ExternalReference scheduled_exception_address =
4807       ExternalReference::scheduled_exception_address(isolate);
4808   __ cmp(Operand::StaticVariable(scheduled_exception_address),
4809          Immediate(isolate->factory()->the_hole_value()));
4810   __ j(not_equal, &promote_scheduled_exception);
4811
4812 #if DEBUG
4813   // Check if the function returned a valid JavaScript value.
4814   Label ok;
4815   Register return_value = eax;
4816   Register map = ecx;
4817
4818   __ JumpIfSmi(return_value, &ok, Label::kNear);
4819   __ mov(map, FieldOperand(return_value, HeapObject::kMapOffset));
4820
4821   __ CmpInstanceType(map, LAST_NAME_TYPE);
4822   __ j(below_equal, &ok, Label::kNear);
4823
4824   __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
4825   __ j(above_equal, &ok, Label::kNear);
4826
4827   __ cmp(map, isolate->factory()->heap_number_map());
4828   __ j(equal, &ok, Label::kNear);
4829
4830   __ cmp(return_value, isolate->factory()->undefined_value());
4831   __ j(equal, &ok, Label::kNear);
4832
4833   __ cmp(return_value, isolate->factory()->true_value());
4834   __ j(equal, &ok, Label::kNear);
4835
4836   __ cmp(return_value, isolate->factory()->false_value());
4837   __ j(equal, &ok, Label::kNear);
4838
4839   __ cmp(return_value, isolate->factory()->null_value());
4840   __ j(equal, &ok, Label::kNear);
4841
4842   __ Abort(kAPICallReturnedInvalidObject);
4843
4844   __ bind(&ok);
4845 #endif
4846
4847   if (stack_space_operand != nullptr) {
4848     DCHECK_EQ(0, stack_space);
4849     __ pop(ecx);
4850     __ add(esp, ebx);
4851     __ jmp(ecx);
4852   } else {
4853     __ ret(stack_space * kPointerSize);
4854   }
4855
4856   // Re-throw by promoting a scheduled exception.
4857   __ bind(&promote_scheduled_exception);
4858   __ TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1);
4859
4860   // HandleScope limit has changed. Delete allocated extensions.
4861   ExternalReference delete_extensions =
4862       ExternalReference::delete_handle_scope_extensions(isolate);
4863   __ bind(&delete_allocated_handles);
4864   __ mov(Operand::StaticVariable(limit_address), edi);
4865   __ mov(edi, eax);
4866   __ mov(Operand(esp, 0),
4867          Immediate(ExternalReference::isolate_address(isolate)));
4868   __ mov(eax, Immediate(delete_extensions));
4869   __ call(eax);
4870   __ mov(eax, edi);
4871   __ jmp(&leave_exit_frame);
4872 }
4873
4874
4875 static void CallApiFunctionStubHelper(MacroAssembler* masm,
4876                                       const ParameterCount& argc,
4877                                       bool return_first_arg,
4878                                       bool call_data_undefined) {
4879   // ----------- S t a t e -------------
4880   //  -- edi                 : callee
4881   //  -- ebx                 : call_data
4882   //  -- ecx                 : holder
4883   //  -- edx                 : api_function_address
4884   //  -- esi                 : context
4885   //  -- eax                 : number of arguments if argc is a register
4886   //  --
4887   //  -- esp[0]              : return address
4888   //  -- esp[4]              : last argument
4889   //  -- ...
4890   //  -- esp[argc * 4]       : first argument
4891   //  -- esp[(argc + 1) * 4] : receiver
4892   // -----------------------------------
4893
4894   Register callee = edi;
4895   Register call_data = ebx;
4896   Register holder = ecx;
4897   Register api_function_address = edx;
4898   Register context = esi;
4899   Register return_address = eax;
4900
4901   typedef FunctionCallbackArguments FCA;
4902
4903   STATIC_ASSERT(FCA::kContextSaveIndex == 6);
4904   STATIC_ASSERT(FCA::kCalleeIndex == 5);
4905   STATIC_ASSERT(FCA::kDataIndex == 4);
4906   STATIC_ASSERT(FCA::kReturnValueOffset == 3);
4907   STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
4908   STATIC_ASSERT(FCA::kIsolateIndex == 1);
4909   STATIC_ASSERT(FCA::kHolderIndex == 0);
4910   STATIC_ASSERT(FCA::kArgsLength == 7);
4911
4912   DCHECK(argc.is_immediate() || eax.is(argc.reg()));
4913
4914   if (argc.is_immediate()) {
4915     __ pop(return_address);
4916     // context save.
4917     __ push(context);
4918   } else {
4919     // pop return address and save context
4920     __ xchg(context, Operand(esp, 0));
4921     return_address = context;
4922   }
4923
4924   // callee
4925   __ push(callee);
4926
4927   // call data
4928   __ push(call_data);
4929
4930   Register scratch = call_data;
4931   if (!call_data_undefined) {
4932     // return value
4933     __ push(Immediate(masm->isolate()->factory()->undefined_value()));
4934     // return value default
4935     __ push(Immediate(masm->isolate()->factory()->undefined_value()));
4936   } else {
4937     // return value
4938     __ push(scratch);
4939     // return value default
4940     __ push(scratch);
4941   }
4942   // isolate
4943   __ push(Immediate(reinterpret_cast<int>(masm->isolate())));
4944   // holder
4945   __ push(holder);
4946
4947   __ mov(scratch, esp);
4948
4949   // push return address
4950   __ push(return_address);
4951
4952   // load context from callee
4953   __ mov(context, FieldOperand(callee, JSFunction::kContextOffset));
4954
4955   // API function gets reference to the v8::Arguments. If CPU profiler
4956   // is enabled wrapper function will be called and we need to pass
4957   // address of the callback as additional parameter, always allocate
4958   // space for it.
4959   const int kApiArgc = 1 + 1;
4960
4961   // Allocate the v8::Arguments structure in the arguments' space since
4962   // it's not controlled by GC.
4963   const int kApiStackSpace = 4;
4964
4965   PrepareCallApiFunction(masm, kApiArgc + kApiStackSpace);
4966
4967   // FunctionCallbackInfo::implicit_args_.
4968   __ mov(ApiParameterOperand(2), scratch);
4969   if (argc.is_immediate()) {
4970     __ add(scratch,
4971            Immediate((argc.immediate() + FCA::kArgsLength - 1) * kPointerSize));
4972     // FunctionCallbackInfo::values_.
4973     __ mov(ApiParameterOperand(3), scratch);
4974     // FunctionCallbackInfo::length_.
4975     __ Move(ApiParameterOperand(4), Immediate(argc.immediate()));
4976     // FunctionCallbackInfo::is_construct_call_.
4977     __ Move(ApiParameterOperand(5), Immediate(0));
4978   } else {
4979     __ lea(scratch, Operand(scratch, argc.reg(), times_pointer_size,
4980                             (FCA::kArgsLength - 1) * kPointerSize));
4981     // FunctionCallbackInfo::values_.
4982     __ mov(ApiParameterOperand(3), scratch);
4983     // FunctionCallbackInfo::length_.
4984     __ mov(ApiParameterOperand(4), argc.reg());
4985     // FunctionCallbackInfo::is_construct_call_.
4986     __ lea(argc.reg(), Operand(argc.reg(), times_pointer_size,
4987                                (FCA::kArgsLength + 1) * kPointerSize));
4988     __ mov(ApiParameterOperand(5), argc.reg());
4989   }
4990
4991   // v8::InvocationCallback's argument.
4992   __ lea(scratch, ApiParameterOperand(2));
4993   __ mov(ApiParameterOperand(0), scratch);
4994
4995   ExternalReference thunk_ref =
4996       ExternalReference::invoke_function_callback(masm->isolate());
4997
4998   Operand context_restore_operand(ebp,
4999                                   (2 + FCA::kContextSaveIndex) * kPointerSize);
5000   // Stores return the first js argument
5001   int return_value_offset = 0;
5002   if (return_first_arg) {
5003     return_value_offset = 2 + FCA::kArgsLength;
5004   } else {
5005     return_value_offset = 2 + FCA::kReturnValueOffset;
5006   }
5007   Operand return_value_operand(ebp, return_value_offset * kPointerSize);
5008   int stack_space = 0;
5009   Operand is_construct_call_operand = ApiParameterOperand(5);
5010   Operand* stack_space_operand = &is_construct_call_operand;
5011   if (argc.is_immediate()) {
5012     stack_space = argc.immediate() + FCA::kArgsLength + 1;
5013     stack_space_operand = nullptr;
5014   }
5015   CallApiFunctionAndReturn(masm, api_function_address, thunk_ref,
5016                            ApiParameterOperand(1), stack_space,
5017                            stack_space_operand, return_value_operand,
5018                            &context_restore_operand);
5019 }
5020
5021
5022 void CallApiFunctionStub::Generate(MacroAssembler* masm) {
5023   bool call_data_undefined = this->call_data_undefined();
5024   CallApiFunctionStubHelper(masm, ParameterCount(eax), false,
5025                             call_data_undefined);
5026 }
5027
5028
5029 void CallApiAccessorStub::Generate(MacroAssembler* masm) {
5030   bool is_store = this->is_store();
5031   int argc = this->argc();
5032   bool call_data_undefined = this->call_data_undefined();
5033   CallApiFunctionStubHelper(masm, ParameterCount(argc), is_store,
5034                             call_data_undefined);
5035 }
5036
5037
5038 void CallApiGetterStub::Generate(MacroAssembler* masm) {
5039   // ----------- S t a t e -------------
5040   //  -- esp[0]                  : return address
5041   //  -- esp[4]                  : name
5042   //  -- esp[8 - kArgsLength*4]  : PropertyCallbackArguments object
5043   //  -- ...
5044   //  -- edx                    : api_function_address
5045   // -----------------------------------
5046   DCHECK(edx.is(ApiGetterDescriptor::function_address()));
5047
5048   // array for v8::Arguments::values_, handler for name and pointer
5049   // to the values (it considered as smi in GC).
5050   const int kStackSpace = PropertyCallbackArguments::kArgsLength + 2;
5051   // Allocate space for opional callback address parameter in case
5052   // CPU profiler is active.
5053   const int kApiArgc = 2 + 1;
5054
5055   Register api_function_address = edx;
5056   Register scratch = ebx;
5057
5058   // load address of name
5059   __ lea(scratch, Operand(esp, 1 * kPointerSize));
5060
5061   PrepareCallApiFunction(masm, kApiArgc);
5062   __ mov(ApiParameterOperand(0), scratch);  // name.
5063   __ add(scratch, Immediate(kPointerSize));
5064   __ mov(ApiParameterOperand(1), scratch);  // arguments pointer.
5065
5066   ExternalReference thunk_ref =
5067       ExternalReference::invoke_accessor_getter_callback(isolate());
5068
5069   CallApiFunctionAndReturn(masm, api_function_address, thunk_ref,
5070                            ApiParameterOperand(2), kStackSpace, nullptr,
5071                            Operand(ebp, 7 * kPointerSize), NULL);
5072 }
5073
5074
5075 #undef __
5076
5077 } }  // namespace v8::internal
5078
5079 #endif  // V8_TARGET_ARCH_X87