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