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