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