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