Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / v8 / src / code-stubs.h
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 #ifndef V8_CODE_STUBS_H_
6 #define V8_CODE_STUBS_H_
7
8 #include "src/allocation.h"
9 #include "src/assembler.h"
10 #include "src/codegen.h"
11 #include "src/globals.h"
12 #include "src/ic/ic-state.h"
13 #include "src/interface-descriptors.h"
14 #include "src/macro-assembler.h"
15 #include "src/ostreams.h"
16
17 namespace v8 {
18 namespace internal {
19
20 // List of code stubs used on all platforms.
21 #define CODE_STUB_LIST_ALL_PLATFORMS(V)     \
22   /* PlatformCodeStubs */                   \
23   V(ArgumentsAccess)                        \
24   V(ArrayConstructor)                       \
25   V(BinaryOpICWithAllocationSite)           \
26   V(CallApiFunction)                        \
27   V(CallApiGetter)                          \
28   V(CallConstruct)                          \
29   V(CallFunction)                           \
30   V(CallIC)                                 \
31   V(CallIC_Array)                           \
32   V(CEntry)                                 \
33   V(CompareIC)                              \
34   V(DoubleToI)                              \
35   V(FunctionPrototype)                      \
36   V(Instanceof)                             \
37   V(InternalArrayConstructor)               \
38   V(JSEntry)                                \
39   V(KeyedLoadICTrampoline)                  \
40   V(LoadICTrampoline)                       \
41   V(LoadIndexedInterceptor)                 \
42   V(MathPow)                                \
43   V(ProfileEntryHook)                       \
44   V(RecordWrite)                            \
45   V(RegExpExec)                             \
46   V(StoreArrayLiteralElement)               \
47   V(StoreBufferOverflow)                    \
48   V(StoreElement)                           \
49   V(StringCompare)                          \
50   V(StubFailureTrampoline)                  \
51   V(SubString)                              \
52   /* HydrogenCodeStubs */                   \
53   V(ArrayNArgumentsConstructor)             \
54   V(ArrayNoArgumentConstructor)             \
55   V(ArraySingleArgumentConstructor)         \
56   V(BinaryOpIC)                             \
57   V(BinaryOpWithAllocationSite)             \
58   V(CompareNilIC)                           \
59   V(CreateAllocationSite)                   \
60   V(ElementsTransitionAndStore)             \
61   V(FastCloneShallowArray)                  \
62   V(FastCloneShallowObject)                 \
63   V(FastNewClosure)                         \
64   V(FastNewContext)                         \
65   V(InternalArrayNArgumentsConstructor)     \
66   V(InternalArrayNoArgumentConstructor)     \
67   V(InternalArraySingleArgumentConstructor) \
68   V(KeyedLoadGeneric)                       \
69   V(LoadDictionaryElement)                  \
70   V(LoadFastElement)                        \
71   V(MegamorphicLoad)                        \
72   V(NameDictionaryLookup)                   \
73   V(NumberToString)                         \
74   V(RegExpConstructResult)                  \
75   V(StoreFastElement)                       \
76   V(StringAdd)                              \
77   V(ToBoolean)                              \
78   V(ToNumber)                               \
79   V(TransitionElementsKind)                 \
80   V(VectorKeyedLoad)                        \
81   V(VectorLoad)                             \
82   /* IC Handler stubs */                    \
83   V(LoadConstant)                           \
84   V(LoadField)                              \
85   V(KeyedLoadSloppyArguments)               \
86   V(StoreField)                             \
87   V(StoreGlobal)                            \
88   V(StringLength)
89
90 // List of code stubs only used on ARM 32 bits platforms.
91 #if V8_TARGET_ARCH_ARM
92 #define CODE_STUB_LIST_ARM(V) \
93   V(DirectCEntry)             \
94   V(WriteInt32ToHeapNumber)
95
96 #else
97 #define CODE_STUB_LIST_ARM(V)
98 #endif
99
100 // List of code stubs only used on ARM 64 bits platforms.
101 #if V8_TARGET_ARCH_ARM64
102 #define CODE_STUB_LIST_ARM64(V) \
103   V(DirectCEntry)               \
104   V(RestoreRegistersState)      \
105   V(StoreRegistersState)
106
107 #else
108 #define CODE_STUB_LIST_ARM64(V)
109 #endif
110
111 // List of code stubs only used on MIPS platforms.
112 #if V8_TARGET_ARCH_MIPS
113 #define CODE_STUB_LIST_MIPS(V)  \
114   V(DirectCEntry)               \
115   V(RestoreRegistersState)      \
116   V(StoreRegistersState)        \
117   V(WriteInt32ToHeapNumber)
118 #elif V8_TARGET_ARCH_MIPS64
119 #define CODE_STUB_LIST_MIPS(V)  \
120   V(DirectCEntry)               \
121   V(RestoreRegistersState)      \
122   V(StoreRegistersState)        \
123   V(WriteInt32ToHeapNumber)
124 #else
125 #define CODE_STUB_LIST_MIPS(V)
126 #endif
127
128 // Combined list of code stubs.
129 #define CODE_STUB_LIST(V)            \
130   CODE_STUB_LIST_ALL_PLATFORMS(V)    \
131   CODE_STUB_LIST_ARM(V)              \
132   CODE_STUB_LIST_ARM64(V)           \
133   CODE_STUB_LIST_MIPS(V)
134
135 // Stub is base classes of all stubs.
136 class CodeStub BASE_EMBEDDED {
137  public:
138   enum Major {
139 #define DEF_ENUM(name) name,
140     CODE_STUB_LIST(DEF_ENUM)
141 #undef DEF_ENUM
142     NoCache,  // marker for stubs that do custom caching
143     NUMBER_OF_IDS
144   };
145
146   // Retrieve the code for the stub. Generate the code if needed.
147   Handle<Code> GetCode();
148
149   // Retrieve the code for the stub, make and return a copy of the code.
150   Handle<Code> GetCodeCopy(const Code::FindAndReplacePattern& pattern);
151
152   static Major MajorKeyFromKey(uint32_t key) {
153     return static_cast<Major>(MajorKeyBits::decode(key));
154   }
155   static uint32_t MinorKeyFromKey(uint32_t key) {
156     return MinorKeyBits::decode(key);
157   }
158
159   // Gets the major key from a code object that is a code stub or binary op IC.
160   static Major GetMajorKey(Code* code_stub) {
161     return MajorKeyFromKey(code_stub->stub_key());
162   }
163
164   static uint32_t NoCacheKey() { return MajorKeyBits::encode(NoCache); }
165
166   static const char* MajorName(Major major_key, bool allow_unknown_keys);
167
168   explicit CodeStub(Isolate* isolate) : minor_key_(0), isolate_(isolate) {}
169   virtual ~CodeStub() {}
170
171   static void GenerateStubsAheadOfTime(Isolate* isolate);
172   static void GenerateFPStubs(Isolate* isolate);
173
174   // Some stubs put untagged junk on the stack that cannot be scanned by the
175   // GC.  This means that we must be statically sure that no GC can occur while
176   // they are running.  If that is the case they should override this to return
177   // true, which will cause an assertion if we try to call something that can
178   // GC or if we try to put a stack frame on top of the junk, which would not
179   // result in a traversable stack.
180   virtual bool SometimesSetsUpAFrame() { return true; }
181
182   // Lookup the code in the (possibly custom) cache.
183   bool FindCodeInCache(Code** code_out);
184
185   virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() = 0;
186
187   virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) {}
188
189   static void InitializeDescriptor(Isolate* isolate, uint32_t key,
190                                    CodeStubDescriptor* desc);
191
192   static MaybeHandle<Code> GetCode(Isolate* isolate, uint32_t key);
193
194   // Returns information for computing the number key.
195   virtual Major MajorKey() const = 0;
196   uint32_t MinorKey() const { return minor_key_; }
197
198   virtual InlineCacheState GetICState() const { return UNINITIALIZED; }
199   virtual ExtraICState GetExtraICState() const { return kNoExtraICState; }
200   virtual Code::StubType GetStubType() {
201     return Code::NORMAL;
202   }
203
204   friend OStream& operator<<(OStream& os, const CodeStub& s) {
205     s.PrintName(os);
206     return os;
207   }
208
209   Isolate* isolate() const { return isolate_; }
210
211  protected:
212   CodeStub(uint32_t key, Isolate* isolate)
213       : minor_key_(MinorKeyFromKey(key)), isolate_(isolate) {}
214
215   // Generates the assembler code for the stub.
216   virtual Handle<Code> GenerateCode() = 0;
217
218   // Returns whether the code generated for this stub needs to be allocated as
219   // a fixed (non-moveable) code object.
220   virtual bool NeedsImmovableCode() { return false; }
221
222   virtual void PrintName(OStream& os) const;        // NOLINT
223   virtual void PrintBaseName(OStream& os) const;    // NOLINT
224   virtual void PrintState(OStream& os) const { ; }  // NOLINT
225
226   // Computes the key based on major and minor.
227   uint32_t GetKey() {
228     DCHECK(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
229     return MinorKeyBits::encode(MinorKey()) | MajorKeyBits::encode(MajorKey());
230   }
231
232   uint32_t minor_key_;
233
234  private:
235   // Perform bookkeeping required after code generation when stub code is
236   // initially generated.
237   void RecordCodeGeneration(Handle<Code> code);
238
239   // Finish the code object after it has been generated.
240   virtual void FinishCode(Handle<Code> code) { }
241
242   // Activate newly generated stub. Is called after
243   // registering stub in the stub cache.
244   virtual void Activate(Code* code) { }
245
246   // BinaryOpStub needs to override this.
247   virtual Code::Kind GetCodeKind() const;
248
249   // Add the code to a specialized cache, specific to an individual
250   // stub type. Please note, this method must add the code object to a
251   // roots object, otherwise we will remove the code during GC.
252   virtual void AddToSpecialCache(Handle<Code> new_object) { }
253
254   // Find code in a specialized cache, work is delegated to the specific stub.
255   virtual bool FindCodeInSpecialCache(Code** code_out) {
256     return false;
257   }
258
259   // If a stub uses a special cache override this.
260   virtual bool UseSpecialCache() { return false; }
261
262   // We use this dispatch to statically instantiate the correct code stub for
263   // the given stub key and call the passed function with that code stub.
264   typedef void (*DispatchedCall)(CodeStub* stub, void** value_out);
265   static void Dispatch(Isolate* isolate, uint32_t key, void** value_out,
266                        DispatchedCall call);
267
268   static void GetCodeDispatchCall(CodeStub* stub, void** value_out);
269
270   STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits));
271   class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
272   class MinorKeyBits: public BitField<uint32_t,
273       kStubMajorKeyBits, kStubMinorKeyBits> {};  // NOLINT
274
275   friend class BreakPointIterator;
276
277   Isolate* isolate_;
278 };
279
280
281 #define DEFINE_CODE_STUB_BASE(NAME, SUPER)                      \
282  public:                                                        \
283   NAME(uint32_t key, Isolate* isolate) : SUPER(key, isolate) {} \
284                                                                 \
285  private:                                                       \
286   DISALLOW_COPY_AND_ASSIGN(NAME)
287
288
289 #define DEFINE_CODE_STUB(NAME, SUPER)              \
290  protected:                                        \
291   virtual inline Major MajorKey() const OVERRIDE { \
292     return NAME;                                   \
293   };                                               \
294   DEFINE_CODE_STUB_BASE(NAME##Stub, SUPER)
295
296
297 #define DEFINE_PLATFORM_CODE_STUB(NAME, SUPER)          \
298  private:                                               \
299   virtual void Generate(MacroAssembler* masm) OVERRIDE; \
300   DEFINE_CODE_STUB(NAME, SUPER)
301
302
303 #define DEFINE_HYDROGEN_CODE_STUB(NAME, SUPER)                                \
304  public:                                                                      \
305   virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) OVERRIDE; \
306   virtual Handle<Code> GenerateCode() OVERRIDE;                               \
307   DEFINE_CODE_STUB(NAME, SUPER)
308
309 #define DEFINE_HANDLER_CODE_STUB(NAME, SUPER)   \
310  public:                                        \
311   virtual Handle<Code> GenerateCode() OVERRIDE; \
312   DEFINE_CODE_STUB(NAME, SUPER)
313
314 #define DEFINE_CALL_INTERFACE_DESCRIPTOR(NAME)                            \
315  public:                                                                  \
316   virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE { \
317     return NAME##Descriptor(isolate());                                   \
318   }
319
320 // There are some code stubs we just can't describe right now with a
321 // CallInterfaceDescriptor. Isolate behavior for those cases with this macro.
322 // An attempt to retrieve a descriptor will fail.
323 #define DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR()                           \
324  public:                                                                  \
325   virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE { \
326     UNREACHABLE();                                                        \
327     return CallInterfaceDescriptor();                                     \
328   }
329
330
331 class PlatformCodeStub : public CodeStub {
332  public:
333   // Retrieve the code for the stub. Generate the code if needed.
334   virtual Handle<Code> GenerateCode() OVERRIDE;
335
336   virtual Code::Kind GetCodeKind() const { return Code::STUB; }
337
338  protected:
339   explicit PlatformCodeStub(Isolate* isolate) : CodeStub(isolate) {}
340
341   // Generates the assembler code for the stub.
342   virtual void Generate(MacroAssembler* masm) = 0;
343
344   DEFINE_CODE_STUB_BASE(PlatformCodeStub, CodeStub);
345 };
346
347
348 enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
349 enum HandlerArgumentsMode { DONT_PASS_ARGUMENTS, PASS_ARGUMENTS };
350
351
352 class CodeStubDescriptor {
353  public:
354   explicit CodeStubDescriptor(CodeStub* stub);
355
356   CodeStubDescriptor(Isolate* isolate, uint32_t stub_key);
357
358   void Initialize(Address deoptimization_handler = NULL,
359                   int hint_stack_parameter_count = -1,
360                   StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
361   void Initialize(Register stack_parameter_count,
362                   Address deoptimization_handler = NULL,
363                   int hint_stack_parameter_count = -1,
364                   StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE,
365                   HandlerArgumentsMode handler_mode = DONT_PASS_ARGUMENTS);
366
367   void SetMissHandler(ExternalReference handler) {
368     miss_handler_ = handler;
369     has_miss_handler_ = true;
370     // Our miss handler infrastructure doesn't currently support
371     // variable stack parameter counts.
372     DCHECK(!stack_parameter_count_.is_valid());
373   }
374
375   void set_call_descriptor(CallInterfaceDescriptor d) { call_descriptor_ = d; }
376   CallInterfaceDescriptor call_descriptor() const { return call_descriptor_; }
377
378   int GetEnvironmentParameterCount() const {
379     return call_descriptor().GetEnvironmentParameterCount();
380   }
381
382   Representation GetEnvironmentParameterRepresentation(int index) const {
383     return call_descriptor().GetEnvironmentParameterRepresentation(index);
384   }
385
386   ExternalReference miss_handler() const {
387     DCHECK(has_miss_handler_);
388     return miss_handler_;
389   }
390
391   bool has_miss_handler() const {
392     return has_miss_handler_;
393   }
394
395   bool IsEnvironmentParameterCountRegister(int index) const {
396     return call_descriptor().GetEnvironmentParameterRegister(index).is(
397         stack_parameter_count_);
398   }
399
400   int GetHandlerParameterCount() const {
401     int params = call_descriptor().GetEnvironmentParameterCount();
402     if (handler_arguments_mode_ == PASS_ARGUMENTS) {
403       params += 1;
404     }
405     return params;
406   }
407
408   int hint_stack_parameter_count() const { return hint_stack_parameter_count_; }
409   Register stack_parameter_count() const { return stack_parameter_count_; }
410   StubFunctionMode function_mode() const { return function_mode_; }
411   Address deoptimization_handler() const { return deoptimization_handler_; }
412
413  private:
414   CallInterfaceDescriptor call_descriptor_;
415   Register stack_parameter_count_;
416   // If hint_stack_parameter_count_ > 0, the code stub can optimize the
417   // return sequence. Default value is -1, which means it is ignored.
418   int hint_stack_parameter_count_;
419   StubFunctionMode function_mode_;
420
421   Address deoptimization_handler_;
422   HandlerArgumentsMode handler_arguments_mode_;
423
424   ExternalReference miss_handler_;
425   bool has_miss_handler_;
426 };
427
428
429 class HydrogenCodeStub : public CodeStub {
430  public:
431   enum InitializationState {
432     UNINITIALIZED,
433     INITIALIZED
434   };
435
436   virtual Code::Kind GetCodeKind() const { return Code::STUB; }
437
438   template<class SubClass>
439   static Handle<Code> GetUninitialized(Isolate* isolate) {
440     SubClass::GenerateAheadOfTime(isolate);
441     return SubClass().GetCode(isolate);
442   }
443
444   // Retrieve the code for the stub. Generate the code if needed.
445   virtual Handle<Code> GenerateCode() = 0;
446
447   bool IsUninitialized() const { return IsMissBits::decode(minor_key_); }
448
449   Handle<Code> GenerateLightweightMissCode(ExternalReference miss);
450
451   template<class StateType>
452   void TraceTransition(StateType from, StateType to);
453
454  protected:
455   explicit HydrogenCodeStub(Isolate* isolate,
456                             InitializationState state = INITIALIZED)
457       : CodeStub(isolate) {
458     minor_key_ = IsMissBits::encode(state == UNINITIALIZED);
459   }
460
461   void set_sub_minor_key(uint32_t key) {
462     minor_key_ = SubMinorKeyBits::update(minor_key_, key);
463   }
464
465   uint32_t sub_minor_key() const { return SubMinorKeyBits::decode(minor_key_); }
466
467   static const int kSubMinorKeyBits = kStubMinorKeyBits - 1;
468
469  private:
470   class IsMissBits : public BitField<bool, kSubMinorKeyBits, 1> {};
471   class SubMinorKeyBits : public BitField<int, 0, kSubMinorKeyBits> {};
472
473   void GenerateLightweightMiss(MacroAssembler* masm, ExternalReference miss);
474
475   DEFINE_CODE_STUB_BASE(HydrogenCodeStub, CodeStub);
476 };
477
478
479 // Helper interface to prepare to/restore after making runtime calls.
480 class RuntimeCallHelper {
481  public:
482   virtual ~RuntimeCallHelper() {}
483
484   virtual void BeforeCall(MacroAssembler* masm) const = 0;
485
486   virtual void AfterCall(MacroAssembler* masm) const = 0;
487
488  protected:
489   RuntimeCallHelper() {}
490
491  private:
492   DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
493 };
494
495
496 } }  // namespace v8::internal
497
498 #if V8_TARGET_ARCH_IA32
499 #include "src/ia32/code-stubs-ia32.h"
500 #elif V8_TARGET_ARCH_X64
501 #include "src/x64/code-stubs-x64.h"
502 #elif V8_TARGET_ARCH_ARM64
503 #include "src/arm64/code-stubs-arm64.h"
504 #elif V8_TARGET_ARCH_ARM
505 #include "src/arm/code-stubs-arm.h"
506 #elif V8_TARGET_ARCH_MIPS
507 #include "src/mips/code-stubs-mips.h"
508 #elif V8_TARGET_ARCH_MIPS64
509 #include "src/mips64/code-stubs-mips64.h"
510 #elif V8_TARGET_ARCH_X87
511 #include "src/x87/code-stubs-x87.h"
512 #else
513 #error Unsupported target architecture.
514 #endif
515
516 namespace v8 {
517 namespace internal {
518
519
520 // RuntimeCallHelper implementation used in stubs: enters/leaves a
521 // newly created internal frame before/after the runtime call.
522 class StubRuntimeCallHelper : public RuntimeCallHelper {
523  public:
524   StubRuntimeCallHelper() {}
525
526   virtual void BeforeCall(MacroAssembler* masm) const;
527
528   virtual void AfterCall(MacroAssembler* masm) const;
529 };
530
531
532 // Trivial RuntimeCallHelper implementation.
533 class NopRuntimeCallHelper : public RuntimeCallHelper {
534  public:
535   NopRuntimeCallHelper() {}
536
537   virtual void BeforeCall(MacroAssembler* masm) const {}
538
539   virtual void AfterCall(MacroAssembler* masm) const {}
540 };
541
542
543 class ToNumberStub: public HydrogenCodeStub {
544  public:
545   explicit ToNumberStub(Isolate* isolate) : HydrogenCodeStub(isolate) { }
546
547   DEFINE_CALL_INTERFACE_DESCRIPTOR(ToNumber);
548   DEFINE_HYDROGEN_CODE_STUB(ToNumber, HydrogenCodeStub);
549 };
550
551
552 class NumberToStringStub FINAL : public HydrogenCodeStub {
553  public:
554   explicit NumberToStringStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
555
556   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
557   static const int kNumber = 0;
558
559   DEFINE_CALL_INTERFACE_DESCRIPTOR(NumberToString);
560   DEFINE_HYDROGEN_CODE_STUB(NumberToString, HydrogenCodeStub);
561 };
562
563
564 class FastNewClosureStub : public HydrogenCodeStub {
565  public:
566   FastNewClosureStub(Isolate* isolate, StrictMode strict_mode,
567                      FunctionKind kind)
568       : HydrogenCodeStub(isolate) {
569     DCHECK(IsValidFunctionKind(kind));
570     set_sub_minor_key(StrictModeBits::encode(strict_mode) |
571                       FunctionKindBits::encode(kind));
572   }
573
574   StrictMode strict_mode() const {
575     return StrictModeBits::decode(sub_minor_key());
576   }
577
578   FunctionKind kind() const {
579     return FunctionKindBits::decode(sub_minor_key());
580   }
581   bool is_arrow() const { return IsArrowFunction(kind()); }
582   bool is_generator() const { return IsGeneratorFunction(kind()); }
583   bool is_concise_method() const { return IsConciseMethod(kind()); }
584
585  private:
586   class StrictModeBits : public BitField<StrictMode, 0, 1> {};
587   class FunctionKindBits : public BitField<FunctionKind, 1, 3> {};
588
589   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewClosure);
590   DEFINE_HYDROGEN_CODE_STUB(FastNewClosure, HydrogenCodeStub);
591 };
592
593
594 class FastNewContextStub FINAL : public HydrogenCodeStub {
595  public:
596   static const int kMaximumSlots = 64;
597
598   FastNewContextStub(Isolate* isolate, int slots) : HydrogenCodeStub(isolate) {
599     DCHECK(slots > 0 && slots <= kMaximumSlots);
600     set_sub_minor_key(SlotsBits::encode(slots));
601   }
602
603   int slots() const { return SlotsBits::decode(sub_minor_key()); }
604
605   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
606   static const int kFunction = 0;
607
608  private:
609   class SlotsBits : public BitField<int, 0, 8> {};
610
611   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewContext);
612   DEFINE_HYDROGEN_CODE_STUB(FastNewContext, HydrogenCodeStub);
613 };
614
615
616 class FastCloneShallowArrayStub : public HydrogenCodeStub {
617  public:
618   FastCloneShallowArrayStub(Isolate* isolate,
619                             AllocationSiteMode allocation_site_mode)
620       : HydrogenCodeStub(isolate) {
621     set_sub_minor_key(AllocationSiteModeBits::encode(allocation_site_mode));
622   }
623
624   AllocationSiteMode allocation_site_mode() const {
625     return AllocationSiteModeBits::decode(sub_minor_key());
626   }
627
628  private:
629   class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {};
630
631   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowArray);
632   DEFINE_HYDROGEN_CODE_STUB(FastCloneShallowArray, HydrogenCodeStub);
633 };
634
635
636 class FastCloneShallowObjectStub : public HydrogenCodeStub {
637  public:
638   // Maximum number of properties in copied object.
639   static const int kMaximumClonedProperties = 6;
640
641   FastCloneShallowObjectStub(Isolate* isolate, int length)
642       : HydrogenCodeStub(isolate) {
643     DCHECK_GE(length, 0);
644     DCHECK_LE(length, kMaximumClonedProperties);
645     set_sub_minor_key(LengthBits::encode(length));
646   }
647
648   int length() const { return LengthBits::decode(sub_minor_key()); }
649
650  private:
651   class LengthBits : public BitField<int, 0, 4> {};
652
653   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowObject);
654   DEFINE_HYDROGEN_CODE_STUB(FastCloneShallowObject, HydrogenCodeStub);
655 };
656
657
658 class CreateAllocationSiteStub : public HydrogenCodeStub {
659  public:
660   explicit CreateAllocationSiteStub(Isolate* isolate)
661       : HydrogenCodeStub(isolate) { }
662
663   static void GenerateAheadOfTime(Isolate* isolate);
664
665   DEFINE_CALL_INTERFACE_DESCRIPTOR(CreateAllocationSite);
666   DEFINE_HYDROGEN_CODE_STUB(CreateAllocationSite, HydrogenCodeStub);
667 };
668
669
670 class InstanceofStub: public PlatformCodeStub {
671  public:
672   enum Flags {
673     kNoFlags = 0,
674     kArgsInRegisters = 1 << 0,
675     kCallSiteInlineCheck = 1 << 1,
676     kReturnTrueFalseObject = 1 << 2
677   };
678
679   InstanceofStub(Isolate* isolate, Flags flags) : PlatformCodeStub(isolate) {
680     minor_key_ = FlagBits::encode(flags);
681   }
682
683   static Register left() { return InstanceofDescriptor::left(); }
684   static Register right() { return InstanceofDescriptor::right(); }
685
686   virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
687     if (HasArgsInRegisters()) {
688       return InstanceofDescriptor(isolate());
689     }
690     return ContextOnlyDescriptor(isolate());
691   }
692
693  private:
694   Flags flags() const { return FlagBits::decode(minor_key_); }
695
696   bool HasArgsInRegisters() const { return (flags() & kArgsInRegisters) != 0; }
697
698   bool HasCallSiteInlineCheck() const {
699     return (flags() & kCallSiteInlineCheck) != 0;
700   }
701
702   bool ReturnTrueFalseObject() const {
703     return (flags() & kReturnTrueFalseObject) != 0;
704   }
705
706   virtual void PrintName(OStream& os) const OVERRIDE;  // NOLINT
707
708   class FlagBits : public BitField<Flags, 0, 3> {};
709
710   DEFINE_PLATFORM_CODE_STUB(Instanceof, PlatformCodeStub);
711 };
712
713
714 enum AllocationSiteOverrideMode {
715   DONT_OVERRIDE,
716   DISABLE_ALLOCATION_SITES,
717   LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
718 };
719
720
721 class ArrayConstructorStub: public PlatformCodeStub {
722  public:
723   enum ArgumentCountKey { ANY, NONE, ONE, MORE_THAN_ONE };
724
725   ArrayConstructorStub(Isolate* isolate, int argument_count);
726
727   explicit ArrayConstructorStub(Isolate* isolate);
728
729  private:
730   ArgumentCountKey argument_count() const {
731     return ArgumentCountBits::decode(minor_key_);
732   }
733
734   void GenerateDispatchToArrayStub(MacroAssembler* masm,
735                                    AllocationSiteOverrideMode mode);
736
737   virtual void PrintName(OStream& os) const OVERRIDE;  // NOLINT
738
739   class ArgumentCountBits : public BitField<ArgumentCountKey, 0, 2> {};
740
741   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
742   DEFINE_PLATFORM_CODE_STUB(ArrayConstructor, PlatformCodeStub);
743 };
744
745
746 class InternalArrayConstructorStub: public PlatformCodeStub {
747  public:
748   explicit InternalArrayConstructorStub(Isolate* isolate);
749
750  private:
751   void GenerateCase(MacroAssembler* masm, ElementsKind kind);
752
753   DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
754   DEFINE_PLATFORM_CODE_STUB(InternalArrayConstructor, PlatformCodeStub);
755 };
756
757
758 class MathPowStub: public PlatformCodeStub {
759  public:
760   enum ExponentType { INTEGER, DOUBLE, TAGGED, ON_STACK };
761
762   MathPowStub(Isolate* isolate, ExponentType exponent_type)
763       : PlatformCodeStub(isolate) {
764     minor_key_ = ExponentTypeBits::encode(exponent_type);
765   }
766
767   virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
768     if (exponent_type() == TAGGED) {
769       return MathPowTaggedDescriptor(isolate());
770     } else if (exponent_type() == INTEGER) {
771       return MathPowIntegerDescriptor(isolate());
772     }
773     // A CallInterfaceDescriptor doesn't specify double registers (yet).
774     return ContextOnlyDescriptor(isolate());
775   }
776
777  private:
778   ExponentType exponent_type() const {
779     return ExponentTypeBits::decode(minor_key_);
780   }
781
782   class ExponentTypeBits : public BitField<ExponentType, 0, 2> {};
783
784   DEFINE_PLATFORM_CODE_STUB(MathPow, PlatformCodeStub);
785 };
786
787
788 class CallICStub: public PlatformCodeStub {
789  public:
790   CallICStub(Isolate* isolate, const CallICState& state)
791       : PlatformCodeStub(isolate) {
792     minor_key_ = state.GetExtraICState();
793   }
794
795   static int ExtractArgcFromMinorKey(int minor_key) {
796     CallICState state(static_cast<ExtraICState>(minor_key));
797     return state.arg_count();
798   }
799
800   virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::CALL_IC; }
801
802   virtual InlineCacheState GetICState() const OVERRIDE { return DEFAULT; }
803
804   virtual ExtraICState GetExtraICState() const FINAL OVERRIDE {
805     return static_cast<ExtraICState>(minor_key_);
806   }
807
808  protected:
809   bool CallAsMethod() const {
810     return state().call_type() == CallICState::METHOD;
811   }
812
813   int arg_count() const { return state().arg_count(); }
814
815   CallICState state() const {
816     return CallICState(static_cast<ExtraICState>(minor_key_));
817   }
818
819   // Code generation helpers.
820   void GenerateMiss(MacroAssembler* masm);
821
822  private:
823   virtual void PrintState(OStream& os) const OVERRIDE;  // NOLINT
824
825   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunctionWithFeedback);
826   DEFINE_PLATFORM_CODE_STUB(CallIC, PlatformCodeStub);
827 };
828
829
830 class CallIC_ArrayStub: public CallICStub {
831  public:
832   CallIC_ArrayStub(Isolate* isolate, const CallICState& state_in)
833       : CallICStub(isolate, state_in) {}
834
835   virtual InlineCacheState GetICState() const FINAL OVERRIDE {
836     return MONOMORPHIC;
837   }
838
839  private:
840   virtual void PrintState(OStream& os) const OVERRIDE;  // NOLINT
841
842   DEFINE_PLATFORM_CODE_STUB(CallIC_Array, CallICStub);
843 };
844
845
846 // TODO(verwaest): Translate to hydrogen code stub.
847 class FunctionPrototypeStub : public PlatformCodeStub {
848  public:
849   explicit FunctionPrototypeStub(Isolate* isolate)
850       : PlatformCodeStub(isolate) {}
851
852   virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
853
854   // TODO(mvstanton): only the receiver register is accessed. When this is
855   // translated to a hydrogen code stub, a new CallInterfaceDescriptor
856   // should be created that just uses that register for more efficient code.
857   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
858   DEFINE_PLATFORM_CODE_STUB(FunctionPrototype, PlatformCodeStub);
859 };
860
861
862 // TODO(mvstanton): Translate to hydrogen code stub.
863 class LoadIndexedInterceptorStub : public PlatformCodeStub {
864  public:
865   explicit LoadIndexedInterceptorStub(Isolate* isolate)
866       : PlatformCodeStub(isolate) {}
867
868   virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
869   virtual Code::StubType GetStubType() { return Code::FAST; }
870
871   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
872   DEFINE_PLATFORM_CODE_STUB(LoadIndexedInterceptor, PlatformCodeStub);
873 };
874
875
876 class HandlerStub : public HydrogenCodeStub {
877  public:
878   virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
879   virtual ExtraICState GetExtraICState() const { return kind(); }
880   virtual InlineCacheState GetICState() const { return MONOMORPHIC; }
881
882   virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) OVERRIDE;
883
884   virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE;
885
886  protected:
887   explicit HandlerStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
888
889   virtual Code::Kind kind() const = 0;
890
891   DEFINE_CODE_STUB_BASE(HandlerStub, HydrogenCodeStub);
892 };
893
894
895 class LoadFieldStub: public HandlerStub {
896  public:
897   LoadFieldStub(Isolate* isolate, FieldIndex index) : HandlerStub(isolate) {
898     int property_index_key = index.GetFieldAccessStubKey();
899     set_sub_minor_key(LoadFieldByIndexBits::encode(property_index_key));
900   }
901
902   FieldIndex index() const {
903     int property_index_key = LoadFieldByIndexBits::decode(sub_minor_key());
904     return FieldIndex::FromFieldAccessStubKey(property_index_key);
905   }
906
907  protected:
908   virtual Code::Kind kind() const { return Code::LOAD_IC; }
909   virtual Code::StubType GetStubType() { return Code::FAST; }
910
911  private:
912   class LoadFieldByIndexBits : public BitField<int, 0, 13> {};
913
914   DEFINE_HANDLER_CODE_STUB(LoadField, HandlerStub);
915 };
916
917
918 class KeyedLoadSloppyArgumentsStub : public HandlerStub {
919  public:
920   explicit KeyedLoadSloppyArgumentsStub(Isolate* isolate)
921       : HandlerStub(isolate) {}
922
923  protected:
924   virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
925   virtual Code::StubType GetStubType() { return Code::FAST; }
926
927  private:
928   DEFINE_HANDLER_CODE_STUB(KeyedLoadSloppyArguments, HandlerStub);
929 };
930
931
932 class LoadConstantStub : public HandlerStub {
933  public:
934   LoadConstantStub(Isolate* isolate, int constant_index)
935       : HandlerStub(isolate) {
936     set_sub_minor_key(ConstantIndexBits::encode(constant_index));
937   }
938
939   int constant_index() const {
940     return ConstantIndexBits::decode(sub_minor_key());
941   }
942
943  protected:
944   virtual Code::Kind kind() const { return Code::LOAD_IC; }
945   virtual Code::StubType GetStubType() { return Code::FAST; }
946
947  private:
948   class ConstantIndexBits : public BitField<int, 0, kSubMinorKeyBits> {};
949
950   DEFINE_HANDLER_CODE_STUB(LoadConstant, HandlerStub);
951 };
952
953
954 class StringLengthStub: public HandlerStub {
955  public:
956   explicit StringLengthStub(Isolate* isolate) : HandlerStub(isolate) {}
957
958  protected:
959   virtual Code::Kind kind() const { return Code::LOAD_IC; }
960   virtual Code::StubType GetStubType() { return Code::FAST; }
961
962   DEFINE_HANDLER_CODE_STUB(StringLength, HandlerStub);
963 };
964
965
966 class StoreFieldStub : public HandlerStub {
967  public:
968   StoreFieldStub(Isolate* isolate, FieldIndex index,
969                  Representation representation)
970       : HandlerStub(isolate) {
971     int property_index_key = index.GetFieldAccessStubKey();
972     uint8_t repr = PropertyDetails::EncodeRepresentation(representation);
973     set_sub_minor_key(StoreFieldByIndexBits::encode(property_index_key) |
974                       RepresentationBits::encode(repr));
975   }
976
977   FieldIndex index() const {
978     int property_index_key = StoreFieldByIndexBits::decode(sub_minor_key());
979     return FieldIndex::FromFieldAccessStubKey(property_index_key);
980   }
981
982   Representation representation() {
983     uint8_t repr = RepresentationBits::decode(sub_minor_key());
984     return PropertyDetails::DecodeRepresentation(repr);
985   }
986
987  protected:
988   virtual Code::Kind kind() const { return Code::STORE_IC; }
989   virtual Code::StubType GetStubType() { return Code::FAST; }
990
991  private:
992   class StoreFieldByIndexBits : public BitField<int, 0, 13> {};
993   class RepresentationBits : public BitField<uint8_t, 13, 4> {};
994
995   DEFINE_HANDLER_CODE_STUB(StoreField, HandlerStub);
996 };
997
998
999 class StoreGlobalStub : public HandlerStub {
1000  public:
1001   StoreGlobalStub(Isolate* isolate, bool is_constant, bool check_global)
1002       : HandlerStub(isolate) {
1003     set_sub_minor_key(IsConstantBits::encode(is_constant) |
1004                       CheckGlobalBits::encode(check_global));
1005   }
1006
1007   static Handle<HeapObject> global_placeholder(Isolate* isolate) {
1008     return isolate->factory()->uninitialized_value();
1009   }
1010
1011   Handle<Code> GetCodeCopyFromTemplate(Handle<GlobalObject> global,
1012                                        Handle<PropertyCell> cell) {
1013     if (check_global()) {
1014       Code::FindAndReplacePattern pattern;
1015       pattern.Add(Handle<Map>(global_placeholder(isolate())->map()), global);
1016       pattern.Add(isolate()->factory()->meta_map(), Handle<Map>(global->map()));
1017       pattern.Add(isolate()->factory()->global_property_cell_map(), cell);
1018       return CodeStub::GetCodeCopy(pattern);
1019     } else {
1020       Code::FindAndReplacePattern pattern;
1021       pattern.Add(isolate()->factory()->global_property_cell_map(), cell);
1022       return CodeStub::GetCodeCopy(pattern);
1023     }
1024   }
1025
1026   virtual Code::Kind kind() const { return Code::STORE_IC; }
1027
1028   bool is_constant() const { return IsConstantBits::decode(sub_minor_key()); }
1029
1030   bool check_global() const { return CheckGlobalBits::decode(sub_minor_key()); }
1031
1032   void set_is_constant(bool value) {
1033     set_sub_minor_key(IsConstantBits::update(sub_minor_key(), value));
1034   }
1035
1036   Representation representation() {
1037     return Representation::FromKind(
1038         RepresentationBits::decode(sub_minor_key()));
1039   }
1040
1041   void set_representation(Representation r) {
1042     set_sub_minor_key(RepresentationBits::update(sub_minor_key(), r.kind()));
1043   }
1044
1045  private:
1046   class IsConstantBits: public BitField<bool, 0, 1> {};
1047   class RepresentationBits: public BitField<Representation::Kind, 1, 8> {};
1048   class CheckGlobalBits: public BitField<bool, 9, 1> {};
1049
1050   DEFINE_HANDLER_CODE_STUB(StoreGlobal, HandlerStub);
1051 };
1052
1053
1054 class CallApiFunctionStub : public PlatformCodeStub {
1055  public:
1056   CallApiFunctionStub(Isolate* isolate,
1057                       bool is_store,
1058                       bool call_data_undefined,
1059                       int argc) : PlatformCodeStub(isolate) {
1060     minor_key_ = IsStoreBits::encode(is_store) |
1061                  CallDataUndefinedBits::encode(call_data_undefined) |
1062                  ArgumentBits::encode(argc);
1063     DCHECK(!is_store || argc == 1);
1064   }
1065
1066  private:
1067   bool is_store() const { return IsStoreBits::decode(minor_key_); }
1068   bool call_data_undefined() const {
1069     return CallDataUndefinedBits::decode(minor_key_);
1070   }
1071   int argc() const { return ArgumentBits::decode(minor_key_); }
1072
1073   class IsStoreBits: public BitField<bool, 0, 1> {};
1074   class CallDataUndefinedBits: public BitField<bool, 1, 1> {};
1075   class ArgumentBits: public BitField<int, 2, Code::kArgumentsBits> {};
1076   STATIC_ASSERT(Code::kArgumentsBits + 2 <= kStubMinorKeyBits);
1077
1078   DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiFunction);
1079   DEFINE_PLATFORM_CODE_STUB(CallApiFunction, PlatformCodeStub);
1080 };
1081
1082
1083 class CallApiGetterStub : public PlatformCodeStub {
1084  public:
1085   explicit CallApiGetterStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
1086
1087   DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiGetter);
1088   DEFINE_PLATFORM_CODE_STUB(CallApiGetter, PlatformCodeStub);
1089 };
1090
1091
1092 class BinaryOpICStub : public HydrogenCodeStub {
1093  public:
1094   BinaryOpICStub(Isolate* isolate, Token::Value op,
1095                  OverwriteMode mode = NO_OVERWRITE)
1096       : HydrogenCodeStub(isolate, UNINITIALIZED) {
1097     BinaryOpICState state(isolate, op, mode);
1098     set_sub_minor_key(state.GetExtraICState());
1099   }
1100
1101   BinaryOpICStub(Isolate* isolate, const BinaryOpICState& state)
1102       : HydrogenCodeStub(isolate) {
1103     set_sub_minor_key(state.GetExtraICState());
1104   }
1105
1106   static void GenerateAheadOfTime(Isolate* isolate);
1107
1108   virtual Code::Kind GetCodeKind() const OVERRIDE {
1109     return Code::BINARY_OP_IC;
1110   }
1111
1112   virtual InlineCacheState GetICState() const FINAL OVERRIDE {
1113     return state().GetICState();
1114   }
1115
1116   virtual ExtraICState GetExtraICState() const FINAL OVERRIDE {
1117     return static_cast<ExtraICState>(sub_minor_key());
1118   }
1119
1120   BinaryOpICState state() const {
1121     return BinaryOpICState(isolate(), GetExtraICState());
1122   }
1123
1124   virtual void PrintState(OStream& os) const FINAL OVERRIDE;  // NOLINT
1125
1126   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1127   static const int kLeft = 0;
1128   static const int kRight = 1;
1129
1130  private:
1131   static void GenerateAheadOfTime(Isolate* isolate,
1132                                   const BinaryOpICState& state);
1133
1134   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1135   DEFINE_HYDROGEN_CODE_STUB(BinaryOpIC, HydrogenCodeStub);
1136 };
1137
1138
1139 // TODO(bmeurer): Merge this into the BinaryOpICStub once we have proper tail
1140 // call support for stubs in Hydrogen.
1141 class BinaryOpICWithAllocationSiteStub FINAL : public PlatformCodeStub {
1142  public:
1143   BinaryOpICWithAllocationSiteStub(Isolate* isolate,
1144                                    const BinaryOpICState& state)
1145       : PlatformCodeStub(isolate) {
1146     minor_key_ = state.GetExtraICState();
1147   }
1148
1149   static void GenerateAheadOfTime(Isolate* isolate);
1150
1151   Handle<Code> GetCodeCopyFromTemplate(Handle<AllocationSite> allocation_site) {
1152     Code::FindAndReplacePattern pattern;
1153     pattern.Add(isolate()->factory()->undefined_map(), allocation_site);
1154     return CodeStub::GetCodeCopy(pattern);
1155   }
1156
1157   virtual Code::Kind GetCodeKind() const OVERRIDE {
1158     return Code::BINARY_OP_IC;
1159   }
1160
1161   virtual InlineCacheState GetICState() const OVERRIDE {
1162     return state().GetICState();
1163   }
1164
1165   virtual ExtraICState GetExtraICState() const OVERRIDE {
1166     return static_cast<ExtraICState>(minor_key_);
1167   }
1168
1169   virtual void PrintState(OStream& os) const OVERRIDE;  // NOLINT
1170
1171  private:
1172   BinaryOpICState state() const {
1173     return BinaryOpICState(isolate(), static_cast<ExtraICState>(minor_key_));
1174   }
1175
1176   static void GenerateAheadOfTime(Isolate* isolate,
1177                                   const BinaryOpICState& state);
1178
1179   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1180   DEFINE_PLATFORM_CODE_STUB(BinaryOpICWithAllocationSite, PlatformCodeStub);
1181 };
1182
1183
1184 class BinaryOpWithAllocationSiteStub FINAL : public BinaryOpICStub {
1185  public:
1186   BinaryOpWithAllocationSiteStub(Isolate* isolate,
1187                                  Token::Value op,
1188                                  OverwriteMode mode)
1189       : BinaryOpICStub(isolate, op, mode) {}
1190
1191   BinaryOpWithAllocationSiteStub(Isolate* isolate, const BinaryOpICState& state)
1192       : BinaryOpICStub(isolate, state) {}
1193
1194   virtual Code::Kind GetCodeKind() const FINAL OVERRIDE {
1195     return Code::STUB;
1196   }
1197
1198   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1199   static const int kAllocationSite = 0;
1200   static const int kLeft = 1;
1201   static const int kRight = 2;
1202
1203   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1204   DEFINE_HYDROGEN_CODE_STUB(BinaryOpWithAllocationSite, BinaryOpICStub);
1205 };
1206
1207
1208 enum StringAddFlags {
1209   // Omit both parameter checks.
1210   STRING_ADD_CHECK_NONE = 0,
1211   // Check left parameter.
1212   STRING_ADD_CHECK_LEFT = 1 << 0,
1213   // Check right parameter.
1214   STRING_ADD_CHECK_RIGHT = 1 << 1,
1215   // Check both parameters.
1216   STRING_ADD_CHECK_BOTH = STRING_ADD_CHECK_LEFT | STRING_ADD_CHECK_RIGHT
1217 };
1218
1219
1220 class StringAddStub FINAL : public HydrogenCodeStub {
1221  public:
1222   StringAddStub(Isolate* isolate, StringAddFlags flags,
1223                 PretenureFlag pretenure_flag)
1224       : HydrogenCodeStub(isolate) {
1225     set_sub_minor_key(StringAddFlagsBits::encode(flags) |
1226                       PretenureFlagBits::encode(pretenure_flag));
1227   }
1228
1229   StringAddFlags flags() const {
1230     return StringAddFlagsBits::decode(sub_minor_key());
1231   }
1232
1233   PretenureFlag pretenure_flag() const {
1234     return PretenureFlagBits::decode(sub_minor_key());
1235   }
1236
1237   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1238   static const int kLeft = 0;
1239   static const int kRight = 1;
1240
1241  private:
1242   class StringAddFlagsBits: public BitField<StringAddFlags, 0, 2> {};
1243   class PretenureFlagBits: public BitField<PretenureFlag, 2, 1> {};
1244
1245   virtual void PrintBaseName(OStream& os) const OVERRIDE;  // NOLINT
1246
1247   DEFINE_CALL_INTERFACE_DESCRIPTOR(StringAdd);
1248   DEFINE_HYDROGEN_CODE_STUB(StringAdd, HydrogenCodeStub);
1249 };
1250
1251
1252 class CompareICStub : public PlatformCodeStub {
1253  public:
1254   CompareICStub(Isolate* isolate, Token::Value op, CompareICState::State left,
1255                 CompareICState::State right, CompareICState::State state)
1256       : PlatformCodeStub(isolate) {
1257     DCHECK(Token::IsCompareOp(op));
1258     minor_key_ = OpBits::encode(op - Token::EQ) | LeftStateBits::encode(left) |
1259                  RightStateBits::encode(right) | StateBits::encode(state);
1260   }
1261
1262   void set_known_map(Handle<Map> map) { known_map_ = map; }
1263
1264   virtual InlineCacheState GetICState() const;
1265
1266   Token::Value op() const {
1267     return static_cast<Token::Value>(Token::EQ + OpBits::decode(minor_key_));
1268   }
1269
1270   CompareICState::State left() const {
1271     return LeftStateBits::decode(minor_key_);
1272   }
1273   CompareICState::State right() const {
1274     return RightStateBits::decode(minor_key_);
1275   }
1276   CompareICState::State state() const { return StateBits::decode(minor_key_); }
1277
1278  private:
1279   virtual Code::Kind GetCodeKind() const { return Code::COMPARE_IC; }
1280
1281   void GenerateSmis(MacroAssembler* masm);
1282   void GenerateNumbers(MacroAssembler* masm);
1283   void GenerateInternalizedStrings(MacroAssembler* masm);
1284   void GenerateStrings(MacroAssembler* masm);
1285   void GenerateUniqueNames(MacroAssembler* masm);
1286   void GenerateObjects(MacroAssembler* masm);
1287   void GenerateMiss(MacroAssembler* masm);
1288   void GenerateKnownObjects(MacroAssembler* masm);
1289   void GenerateGeneric(MacroAssembler* masm);
1290
1291   bool strict() const { return op() == Token::EQ_STRICT; }
1292   Condition GetCondition() const;
1293
1294   virtual void AddToSpecialCache(Handle<Code> new_object);
1295   virtual bool FindCodeInSpecialCache(Code** code_out);
1296   virtual bool UseSpecialCache() {
1297     return state() == CompareICState::KNOWN_OBJECT;
1298   }
1299
1300   class OpBits : public BitField<int, 0, 3> {};
1301   class LeftStateBits : public BitField<CompareICState::State, 3, 4> {};
1302   class RightStateBits : public BitField<CompareICState::State, 7, 4> {};
1303   class StateBits : public BitField<CompareICState::State, 11, 4> {};
1304
1305   Handle<Map> known_map_;
1306
1307   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1308   DEFINE_PLATFORM_CODE_STUB(CompareIC, PlatformCodeStub);
1309 };
1310
1311
1312 class CompareNilICStub : public HydrogenCodeStub  {
1313  public:
1314   Type* GetType(Zone* zone, Handle<Map> map = Handle<Map>());
1315   Type* GetInputType(Zone* zone, Handle<Map> map);
1316
1317   CompareNilICStub(Isolate* isolate, NilValue nil) : HydrogenCodeStub(isolate) {
1318     set_sub_minor_key(NilValueBits::encode(nil));
1319   }
1320
1321   CompareNilICStub(Isolate* isolate, ExtraICState ic_state,
1322                    InitializationState init_state = INITIALIZED)
1323       : HydrogenCodeStub(isolate, init_state) {
1324     set_sub_minor_key(ic_state);
1325   }
1326
1327   static Handle<Code> GetUninitialized(Isolate* isolate,
1328                                        NilValue nil) {
1329     return CompareNilICStub(isolate, nil, UNINITIALIZED).GetCode();
1330   }
1331
1332   virtual InlineCacheState GetICState() const {
1333     State state = this->state();
1334     if (state.Contains(GENERIC)) {
1335       return MEGAMORPHIC;
1336     } else if (state.Contains(MONOMORPHIC_MAP)) {
1337       return MONOMORPHIC;
1338     } else {
1339       return PREMONOMORPHIC;
1340     }
1341   }
1342
1343   virtual Code::Kind GetCodeKind() const { return Code::COMPARE_NIL_IC; }
1344
1345   virtual ExtraICState GetExtraICState() const { return sub_minor_key(); }
1346
1347   void UpdateStatus(Handle<Object> object);
1348
1349   bool IsMonomorphic() const { return state().Contains(MONOMORPHIC_MAP); }
1350
1351   NilValue nil_value() const { return NilValueBits::decode(sub_minor_key()); }
1352
1353   void ClearState() {
1354     set_sub_minor_key(TypesBits::update(sub_minor_key(), 0));
1355   }
1356
1357   virtual void PrintState(OStream& os) const OVERRIDE;     // NOLINT
1358   virtual void PrintBaseName(OStream& os) const OVERRIDE;  // NOLINT
1359
1360  private:
1361   CompareNilICStub(Isolate* isolate, NilValue nil,
1362                    InitializationState init_state)
1363       : HydrogenCodeStub(isolate, init_state) {
1364     set_sub_minor_key(NilValueBits::encode(nil));
1365   }
1366
1367   enum CompareNilType {
1368     UNDEFINED,
1369     NULL_TYPE,
1370     MONOMORPHIC_MAP,
1371     GENERIC,
1372     NUMBER_OF_TYPES
1373   };
1374
1375   // At most 6 different types can be distinguished, because the Code object
1376   // only has room for a single byte to hold a set and there are two more
1377   // boolean flags we need to store. :-P
1378   STATIC_ASSERT(NUMBER_OF_TYPES <= 6);
1379
1380   class State : public EnumSet<CompareNilType, byte> {
1381    public:
1382     State() : EnumSet<CompareNilType, byte>(0) { }
1383     explicit State(byte bits) : EnumSet<CompareNilType, byte>(bits) { }
1384   };
1385   friend OStream& operator<<(OStream& os, const State& s);
1386
1387   State state() const { return State(TypesBits::decode(sub_minor_key())); }
1388
1389   class NilValueBits : public BitField<NilValue, 0, 1> {};
1390   class TypesBits : public BitField<byte, 1, NUMBER_OF_TYPES> {};
1391
1392   friend class CompareNilIC;
1393
1394   DEFINE_CALL_INTERFACE_DESCRIPTOR(CompareNil);
1395   DEFINE_HYDROGEN_CODE_STUB(CompareNilIC, HydrogenCodeStub);
1396 };
1397
1398
1399 OStream& operator<<(OStream& os, const CompareNilICStub::State& s);
1400
1401
1402 class CEntryStub : public PlatformCodeStub {
1403  public:
1404   CEntryStub(Isolate* isolate, int result_size,
1405              SaveFPRegsMode save_doubles = kDontSaveFPRegs)
1406       : PlatformCodeStub(isolate) {
1407     minor_key_ = SaveDoublesBits::encode(save_doubles == kSaveFPRegs);
1408     DCHECK(result_size == 1 || result_size == 2);
1409 #ifdef _WIN64
1410     minor_key_ = ResultSizeBits::update(minor_key_, result_size);
1411 #endif  // _WIN64
1412   }
1413
1414   // The version of this stub that doesn't save doubles is generated ahead of
1415   // time, so it's OK to call it from other stubs that can't cope with GC during
1416   // their code generation.  On machines that always have gp registers (x64) we
1417   // can generate both variants ahead of time.
1418   static void GenerateAheadOfTime(Isolate* isolate);
1419
1420  private:
1421   bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
1422 #ifdef _WIN64
1423   int result_size() const { return ResultSizeBits::decode(minor_key_); }
1424 #endif  // _WIN64
1425
1426   bool NeedsImmovableCode();
1427
1428   class SaveDoublesBits : public BitField<bool, 0, 1> {};
1429   class ResultSizeBits : public BitField<int, 1, 3> {};
1430
1431   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1432   DEFINE_PLATFORM_CODE_STUB(CEntry, PlatformCodeStub);
1433 };
1434
1435
1436 class JSEntryStub : public PlatformCodeStub {
1437  public:
1438   JSEntryStub(Isolate* isolate, StackFrame::Type type)
1439       : PlatformCodeStub(isolate) {
1440     DCHECK(type == StackFrame::ENTRY || type == StackFrame::ENTRY_CONSTRUCT);
1441     minor_key_ = StackFrameTypeBits::encode(type);
1442   }
1443
1444  private:
1445   virtual void FinishCode(Handle<Code> code);
1446
1447   virtual void PrintName(OStream& os) const OVERRIDE {  // NOLINT
1448     os << (type() == StackFrame::ENTRY ? "JSEntryStub"
1449                                        : "JSConstructEntryStub");
1450   }
1451
1452   StackFrame::Type type() const {
1453     return StackFrameTypeBits::decode(minor_key_);
1454   }
1455
1456   class StackFrameTypeBits : public BitField<StackFrame::Type, 0, 5> {};
1457
1458   int handler_offset_;
1459
1460   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1461   DEFINE_PLATFORM_CODE_STUB(JSEntry, PlatformCodeStub);
1462 };
1463
1464
1465 class ArgumentsAccessStub: public PlatformCodeStub {
1466  public:
1467   enum Type {
1468     READ_ELEMENT,
1469     NEW_SLOPPY_FAST,
1470     NEW_SLOPPY_SLOW,
1471     NEW_STRICT
1472   };
1473
1474   ArgumentsAccessStub(Isolate* isolate, Type type) : PlatformCodeStub(isolate) {
1475     minor_key_ = TypeBits::encode(type);
1476   }
1477
1478   virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
1479     if (type() == READ_ELEMENT) {
1480       return ArgumentsAccessReadDescriptor(isolate());
1481     }
1482     return ContextOnlyDescriptor(isolate());
1483   }
1484
1485  private:
1486   Type type() const { return TypeBits::decode(minor_key_); }
1487
1488   void GenerateReadElement(MacroAssembler* masm);
1489   void GenerateNewStrict(MacroAssembler* masm);
1490   void GenerateNewSloppyFast(MacroAssembler* masm);
1491   void GenerateNewSloppySlow(MacroAssembler* masm);
1492
1493   virtual void PrintName(OStream& os) const OVERRIDE;  // NOLINT
1494
1495   class TypeBits : public BitField<Type, 0, 2> {};
1496
1497   DEFINE_PLATFORM_CODE_STUB(ArgumentsAccess, PlatformCodeStub);
1498 };
1499
1500
1501 class RegExpExecStub: public PlatformCodeStub {
1502  public:
1503   explicit RegExpExecStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
1504
1505   DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
1506   DEFINE_PLATFORM_CODE_STUB(RegExpExec, PlatformCodeStub);
1507 };
1508
1509
1510 class RegExpConstructResultStub FINAL : public HydrogenCodeStub {
1511  public:
1512   explicit RegExpConstructResultStub(Isolate* isolate)
1513       : HydrogenCodeStub(isolate) { }
1514
1515   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1516   static const int kLength = 0;
1517   static const int kIndex = 1;
1518   static const int kInput = 2;
1519
1520   DEFINE_CALL_INTERFACE_DESCRIPTOR(RegExpConstructResult);
1521   DEFINE_HYDROGEN_CODE_STUB(RegExpConstructResult, HydrogenCodeStub);
1522 };
1523
1524
1525 class CallFunctionStub: public PlatformCodeStub {
1526  public:
1527   CallFunctionStub(Isolate* isolate, int argc, CallFunctionFlags flags)
1528       : PlatformCodeStub(isolate) {
1529     DCHECK(argc >= 0 && argc <= Code::kMaxArguments);
1530     minor_key_ = ArgcBits::encode(argc) | FlagBits::encode(flags);
1531   }
1532
1533   static int ExtractArgcFromMinorKey(int minor_key) {
1534     return ArgcBits::decode(minor_key);
1535   }
1536
1537  private:
1538   int argc() const { return ArgcBits::decode(minor_key_); }
1539   int flags() const { return FlagBits::decode(minor_key_); }
1540
1541   bool CallAsMethod() const {
1542     return flags() == CALL_AS_METHOD || flags() == WRAP_AND_CALL;
1543   }
1544
1545   bool NeedsChecks() const { return flags() != WRAP_AND_CALL; }
1546
1547   virtual void PrintName(OStream& os) const OVERRIDE;  // NOLINT
1548
1549   // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
1550   class FlagBits : public BitField<CallFunctionFlags, 0, 2> {};
1551   class ArgcBits : public BitField<unsigned, 2, Code::kArgumentsBits> {};
1552   STATIC_ASSERT(Code::kArgumentsBits + 2 <= kStubMinorKeyBits);
1553
1554   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction);
1555   DEFINE_PLATFORM_CODE_STUB(CallFunction, PlatformCodeStub);
1556 };
1557
1558
1559 class CallConstructStub: public PlatformCodeStub {
1560  public:
1561   CallConstructStub(Isolate* isolate, CallConstructorFlags flags)
1562       : PlatformCodeStub(isolate) {
1563     minor_key_ = FlagBits::encode(flags);
1564   }
1565
1566   virtual void FinishCode(Handle<Code> code) {
1567     code->set_has_function_cache(RecordCallTarget());
1568   }
1569
1570  private:
1571   CallConstructorFlags flags() const { return FlagBits::decode(minor_key_); }
1572
1573   bool RecordCallTarget() const {
1574     return (flags() & RECORD_CONSTRUCTOR_TARGET) != 0;
1575   }
1576
1577   virtual void PrintName(OStream& os) const OVERRIDE;  // NOLINT
1578
1579   class FlagBits : public BitField<CallConstructorFlags, 0, 1> {};
1580
1581   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallConstruct);
1582   DEFINE_PLATFORM_CODE_STUB(CallConstruct, PlatformCodeStub);
1583 };
1584
1585
1586 enum StringIndexFlags {
1587   // Accepts smis or heap numbers.
1588   STRING_INDEX_IS_NUMBER,
1589
1590   // Accepts smis or heap numbers that are valid array indices
1591   // (ECMA-262 15.4). Invalid indices are reported as being out of
1592   // range.
1593   STRING_INDEX_IS_ARRAY_INDEX
1594 };
1595
1596
1597 // Generates code implementing String.prototype.charCodeAt.
1598 //
1599 // Only supports the case when the receiver is a string and the index
1600 // is a number (smi or heap number) that is a valid index into the
1601 // string. Additional index constraints are specified by the
1602 // flags. Otherwise, bails out to the provided labels.
1603 //
1604 // Register usage: |object| may be changed to another string in a way
1605 // that doesn't affect charCodeAt/charAt semantics, |index| is
1606 // preserved, |scratch| and |result| are clobbered.
1607 class StringCharCodeAtGenerator {
1608  public:
1609   StringCharCodeAtGenerator(Register object,
1610                             Register index,
1611                             Register result,
1612                             Label* receiver_not_string,
1613                             Label* index_not_number,
1614                             Label* index_out_of_range,
1615                             StringIndexFlags index_flags)
1616       : object_(object),
1617         index_(index),
1618         result_(result),
1619         receiver_not_string_(receiver_not_string),
1620         index_not_number_(index_not_number),
1621         index_out_of_range_(index_out_of_range),
1622         index_flags_(index_flags) {
1623     DCHECK(!result_.is(object_));
1624     DCHECK(!result_.is(index_));
1625   }
1626
1627   // Generates the fast case code. On the fallthrough path |result|
1628   // register contains the result.
1629   void GenerateFast(MacroAssembler* masm);
1630
1631   // Generates the slow case code. Must not be naturally
1632   // reachable. Expected to be put after a ret instruction (e.g., in
1633   // deferred code). Always jumps back to the fast case.
1634   void GenerateSlow(MacroAssembler* masm,
1635                     const RuntimeCallHelper& call_helper);
1636
1637   // Skip handling slow case and directly jump to bailout.
1638   void SkipSlow(MacroAssembler* masm, Label* bailout) {
1639     masm->bind(&index_not_smi_);
1640     masm->bind(&call_runtime_);
1641     masm->jmp(bailout);
1642   }
1643
1644  private:
1645   Register object_;
1646   Register index_;
1647   Register result_;
1648
1649   Label* receiver_not_string_;
1650   Label* index_not_number_;
1651   Label* index_out_of_range_;
1652
1653   StringIndexFlags index_flags_;
1654
1655   Label call_runtime_;
1656   Label index_not_smi_;
1657   Label got_smi_index_;
1658   Label exit_;
1659
1660   DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
1661 };
1662
1663
1664 // Generates code for creating a one-char string from a char code.
1665 class StringCharFromCodeGenerator {
1666  public:
1667   StringCharFromCodeGenerator(Register code,
1668                               Register result)
1669       : code_(code),
1670         result_(result) {
1671     DCHECK(!code_.is(result_));
1672   }
1673
1674   // Generates the fast case code. On the fallthrough path |result|
1675   // register contains the result.
1676   void GenerateFast(MacroAssembler* masm);
1677
1678   // Generates the slow case code. Must not be naturally
1679   // reachable. Expected to be put after a ret instruction (e.g., in
1680   // deferred code). Always jumps back to the fast case.
1681   void GenerateSlow(MacroAssembler* masm,
1682                     const RuntimeCallHelper& call_helper);
1683
1684   // Skip handling slow case and directly jump to bailout.
1685   void SkipSlow(MacroAssembler* masm, Label* bailout) {
1686     masm->bind(&slow_case_);
1687     masm->jmp(bailout);
1688   }
1689
1690  private:
1691   Register code_;
1692   Register result_;
1693
1694   Label slow_case_;
1695   Label exit_;
1696
1697   DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
1698 };
1699
1700
1701 // Generates code implementing String.prototype.charAt.
1702 //
1703 // Only supports the case when the receiver is a string and the index
1704 // is a number (smi or heap number) that is a valid index into the
1705 // string. Additional index constraints are specified by the
1706 // flags. Otherwise, bails out to the provided labels.
1707 //
1708 // Register usage: |object| may be changed to another string in a way
1709 // that doesn't affect charCodeAt/charAt semantics, |index| is
1710 // preserved, |scratch1|, |scratch2|, and |result| are clobbered.
1711 class StringCharAtGenerator {
1712  public:
1713   StringCharAtGenerator(Register object,
1714                         Register index,
1715                         Register scratch,
1716                         Register result,
1717                         Label* receiver_not_string,
1718                         Label* index_not_number,
1719                         Label* index_out_of_range,
1720                         StringIndexFlags index_flags)
1721       : char_code_at_generator_(object,
1722                                 index,
1723                                 scratch,
1724                                 receiver_not_string,
1725                                 index_not_number,
1726                                 index_out_of_range,
1727                                 index_flags),
1728         char_from_code_generator_(scratch, result) {}
1729
1730   // Generates the fast case code. On the fallthrough path |result|
1731   // register contains the result.
1732   void GenerateFast(MacroAssembler* masm) {
1733     char_code_at_generator_.GenerateFast(masm);
1734     char_from_code_generator_.GenerateFast(masm);
1735   }
1736
1737   // Generates the slow case code. Must not be naturally
1738   // reachable. Expected to be put after a ret instruction (e.g., in
1739   // deferred code). Always jumps back to the fast case.
1740   void GenerateSlow(MacroAssembler* masm,
1741                     const RuntimeCallHelper& call_helper) {
1742     char_code_at_generator_.GenerateSlow(masm, call_helper);
1743     char_from_code_generator_.GenerateSlow(masm, call_helper);
1744   }
1745
1746   // Skip handling slow case and directly jump to bailout.
1747   void SkipSlow(MacroAssembler* masm, Label* bailout) {
1748     char_code_at_generator_.SkipSlow(masm, bailout);
1749     char_from_code_generator_.SkipSlow(masm, bailout);
1750   }
1751
1752  private:
1753   StringCharCodeAtGenerator char_code_at_generator_;
1754   StringCharFromCodeGenerator char_from_code_generator_;
1755
1756   DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
1757 };
1758
1759
1760 class LoadDictionaryElementStub : public HydrogenCodeStub {
1761  public:
1762   explicit LoadDictionaryElementStub(Isolate* isolate)
1763       : HydrogenCodeStub(isolate) {}
1764
1765   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1766   DEFINE_HYDROGEN_CODE_STUB(LoadDictionaryElement, HydrogenCodeStub);
1767 };
1768
1769
1770 class KeyedLoadGenericStub : public HydrogenCodeStub {
1771  public:
1772   explicit KeyedLoadGenericStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
1773
1774   virtual Code::Kind GetCodeKind() const { return Code::KEYED_LOAD_IC; }
1775   virtual InlineCacheState GetICState() const { return GENERIC; }
1776
1777   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1778   DEFINE_HYDROGEN_CODE_STUB(KeyedLoadGeneric, HydrogenCodeStub);
1779 };
1780
1781
1782 class LoadICTrampolineStub : public PlatformCodeStub {
1783  public:
1784   LoadICTrampolineStub(Isolate* isolate, const LoadICState& state)
1785       : PlatformCodeStub(isolate) {
1786     minor_key_ = state.GetExtraICState();
1787   }
1788
1789   virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::LOAD_IC; }
1790
1791   virtual InlineCacheState GetICState() const FINAL OVERRIDE {
1792     return GENERIC;
1793   }
1794
1795   virtual ExtraICState GetExtraICState() const FINAL OVERRIDE {
1796     return static_cast<ExtraICState>(minor_key_);
1797   }
1798
1799  private:
1800   LoadICState state() const {
1801     return LoadICState(static_cast<ExtraICState>(minor_key_));
1802   }
1803
1804   DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorLoadICTrampoline);
1805   DEFINE_PLATFORM_CODE_STUB(LoadICTrampoline, PlatformCodeStub);
1806 };
1807
1808
1809 class KeyedLoadICTrampolineStub : public LoadICTrampolineStub {
1810  public:
1811   explicit KeyedLoadICTrampolineStub(Isolate* isolate)
1812       : LoadICTrampolineStub(isolate, LoadICState(0)) {}
1813
1814   virtual Code::Kind GetCodeKind() const OVERRIDE {
1815     return Code::KEYED_LOAD_IC;
1816   }
1817
1818   DEFINE_PLATFORM_CODE_STUB(KeyedLoadICTrampoline, LoadICTrampolineStub);
1819 };
1820
1821
1822 class MegamorphicLoadStub : public HydrogenCodeStub {
1823  public:
1824   MegamorphicLoadStub(Isolate* isolate, const LoadICState& state)
1825       : HydrogenCodeStub(isolate) {
1826     set_sub_minor_key(state.GetExtraICState());
1827   }
1828
1829   virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::LOAD_IC; }
1830
1831   virtual InlineCacheState GetICState() const FINAL OVERRIDE {
1832     return MEGAMORPHIC;
1833   }
1834
1835   virtual ExtraICState GetExtraICState() const FINAL OVERRIDE {
1836     return static_cast<ExtraICState>(sub_minor_key());
1837   }
1838
1839   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1840   DEFINE_HYDROGEN_CODE_STUB(MegamorphicLoad, HydrogenCodeStub);
1841 };
1842
1843
1844 class VectorLoadStub : public HydrogenCodeStub {
1845  public:
1846   explicit VectorLoadStub(Isolate* isolate, const LoadICState& state)
1847       : HydrogenCodeStub(isolate) {
1848     set_sub_minor_key(state.GetExtraICState());
1849   }
1850
1851   virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::LOAD_IC; }
1852
1853   virtual InlineCacheState GetICState() const FINAL OVERRIDE {
1854     return GENERIC;
1855   }
1856
1857   virtual ExtraICState GetExtraICState() const FINAL OVERRIDE {
1858     return static_cast<ExtraICState>(sub_minor_key());
1859   }
1860
1861  private:
1862   LoadICState state() const { return LoadICState(GetExtraICState()); }
1863
1864   DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorLoadIC);
1865   DEFINE_HYDROGEN_CODE_STUB(VectorLoad, HydrogenCodeStub);
1866 };
1867
1868
1869 class VectorKeyedLoadStub : public VectorLoadStub {
1870  public:
1871   explicit VectorKeyedLoadStub(Isolate* isolate)
1872       : VectorLoadStub(isolate, LoadICState(0)) {}
1873
1874   virtual Code::Kind GetCodeKind() const OVERRIDE {
1875     return Code::KEYED_LOAD_IC;
1876   }
1877
1878   DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorLoadIC);
1879   DEFINE_HYDROGEN_CODE_STUB(VectorKeyedLoad, VectorLoadStub);
1880 };
1881
1882
1883 class DoubleToIStub : public PlatformCodeStub {
1884  public:
1885   DoubleToIStub(Isolate* isolate, Register source, Register destination,
1886                 int offset, bool is_truncating, bool skip_fastpath = false)
1887       : PlatformCodeStub(isolate) {
1888     minor_key_ = SourceRegisterBits::encode(source.code()) |
1889                  DestinationRegisterBits::encode(destination.code()) |
1890                  OffsetBits::encode(offset) |
1891                  IsTruncatingBits::encode(is_truncating) |
1892                  SkipFastPathBits::encode(skip_fastpath) |
1893                  SSE3Bits::encode(CpuFeatures::IsSupported(SSE3) ? 1 : 0);
1894   }
1895
1896   virtual bool SometimesSetsUpAFrame() { return false; }
1897
1898  private:
1899   Register source() const {
1900     return Register::from_code(SourceRegisterBits::decode(minor_key_));
1901   }
1902   Register destination() const {
1903     return Register::from_code(DestinationRegisterBits::decode(minor_key_));
1904   }
1905   bool is_truncating() const { return IsTruncatingBits::decode(minor_key_); }
1906   bool skip_fastpath() const { return SkipFastPathBits::decode(minor_key_); }
1907   int offset() const { return OffsetBits::decode(minor_key_); }
1908
1909   static const int kBitsPerRegisterNumber = 6;
1910   STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
1911   class SourceRegisterBits:
1912       public BitField<int, 0, kBitsPerRegisterNumber> {};  // NOLINT
1913   class DestinationRegisterBits:
1914       public BitField<int, kBitsPerRegisterNumber,
1915         kBitsPerRegisterNumber> {};  // NOLINT
1916   class IsTruncatingBits:
1917       public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {};  // NOLINT
1918   class OffsetBits:
1919       public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {};  // NOLINT
1920   class SkipFastPathBits:
1921       public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {};  // NOLINT
1922   class SSE3Bits:
1923       public BitField<int, 2 * kBitsPerRegisterNumber + 5, 1> {};  // NOLINT
1924
1925   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1926   DEFINE_PLATFORM_CODE_STUB(DoubleToI, PlatformCodeStub);
1927 };
1928
1929
1930 class LoadFastElementStub : public HydrogenCodeStub {
1931  public:
1932   LoadFastElementStub(Isolate* isolate, bool is_js_array,
1933                       ElementsKind elements_kind)
1934       : HydrogenCodeStub(isolate) {
1935     set_sub_minor_key(ElementsKindBits::encode(elements_kind) |
1936                       IsJSArrayBits::encode(is_js_array));
1937   }
1938
1939   bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
1940
1941   ElementsKind elements_kind() const {
1942     return ElementsKindBits::decode(sub_minor_key());
1943   }
1944
1945  private:
1946   class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
1947   class IsJSArrayBits: public BitField<bool, 8, 1> {};
1948
1949   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1950   DEFINE_HYDROGEN_CODE_STUB(LoadFastElement, HydrogenCodeStub);
1951 };
1952
1953
1954 class StoreFastElementStub : public HydrogenCodeStub {
1955  public:
1956   StoreFastElementStub(Isolate* isolate, bool is_js_array,
1957                        ElementsKind elements_kind, KeyedAccessStoreMode mode)
1958       : HydrogenCodeStub(isolate) {
1959     set_sub_minor_key(ElementsKindBits::encode(elements_kind) |
1960                       IsJSArrayBits::encode(is_js_array) |
1961                       StoreModeBits::encode(mode));
1962   }
1963
1964   bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
1965
1966   ElementsKind elements_kind() const {
1967     return ElementsKindBits::decode(sub_minor_key());
1968   }
1969
1970   KeyedAccessStoreMode store_mode() const {
1971     return StoreModeBits::decode(sub_minor_key());
1972   }
1973
1974  private:
1975   class ElementsKindBits: public BitField<ElementsKind,      0, 8> {};
1976   class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
1977   class IsJSArrayBits: public BitField<bool,                12, 1> {};
1978
1979   DEFINE_CALL_INTERFACE_DESCRIPTOR(Store);
1980   DEFINE_HYDROGEN_CODE_STUB(StoreFastElement, HydrogenCodeStub);
1981 };
1982
1983
1984 class TransitionElementsKindStub : public HydrogenCodeStub {
1985  public:
1986   TransitionElementsKindStub(Isolate* isolate,
1987                              ElementsKind from_kind,
1988                              ElementsKind to_kind,
1989                              bool is_js_array) : HydrogenCodeStub(isolate) {
1990     set_sub_minor_key(FromKindBits::encode(from_kind) |
1991                       ToKindBits::encode(to_kind) |
1992                       IsJSArrayBits::encode(is_js_array));
1993   }
1994
1995   ElementsKind from_kind() const {
1996     return FromKindBits::decode(sub_minor_key());
1997   }
1998
1999   ElementsKind to_kind() const { return ToKindBits::decode(sub_minor_key()); }
2000
2001   bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2002
2003  private:
2004   class FromKindBits: public BitField<ElementsKind, 8, 8> {};
2005   class ToKindBits: public BitField<ElementsKind, 0, 8> {};
2006   class IsJSArrayBits: public BitField<bool, 16, 1> {};
2007
2008   DEFINE_CALL_INTERFACE_DESCRIPTOR(TransitionElementsKind);
2009   DEFINE_HYDROGEN_CODE_STUB(TransitionElementsKind, HydrogenCodeStub);
2010 };
2011
2012
2013 class ArrayConstructorStubBase : public HydrogenCodeStub {
2014  public:
2015   ArrayConstructorStubBase(Isolate* isolate,
2016                            ElementsKind kind,
2017                            AllocationSiteOverrideMode override_mode)
2018       : HydrogenCodeStub(isolate) {
2019     // It only makes sense to override local allocation site behavior
2020     // if there is a difference between the global allocation site policy
2021     // for an ElementsKind and the desired usage of the stub.
2022     DCHECK(override_mode != DISABLE_ALLOCATION_SITES ||
2023            AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE);
2024     set_sub_minor_key(ElementsKindBits::encode(kind) |
2025                       AllocationSiteOverrideModeBits::encode(override_mode));
2026   }
2027
2028   ElementsKind elements_kind() const {
2029     return ElementsKindBits::decode(sub_minor_key());
2030   }
2031
2032   AllocationSiteOverrideMode override_mode() const {
2033     return AllocationSiteOverrideModeBits::decode(sub_minor_key());
2034   }
2035
2036   static void GenerateStubsAheadOfTime(Isolate* isolate);
2037
2038   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2039   static const int kConstructor = 0;
2040   static const int kAllocationSite = 1;
2041
2042  protected:
2043   OStream& BasePrintName(OStream& os, const char* name) const;  // NOLINT
2044
2045  private:
2046   // Ensure data fits within available bits.
2047   STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
2048
2049   class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2050   class AllocationSiteOverrideModeBits: public
2051       BitField<AllocationSiteOverrideMode, 8, 1> {};  // NOLINT
2052
2053   DEFINE_CODE_STUB_BASE(ArrayConstructorStubBase, HydrogenCodeStub);
2054 };
2055
2056
2057 class ArrayNoArgumentConstructorStub : public ArrayConstructorStubBase {
2058  public:
2059   ArrayNoArgumentConstructorStub(
2060       Isolate* isolate,
2061       ElementsKind kind,
2062       AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2063       : ArrayConstructorStubBase(isolate, kind, override_mode) {
2064   }
2065
2066  private:
2067   virtual void PrintName(OStream& os) const OVERRIDE {  // NOLINT
2068     BasePrintName(os, "ArrayNoArgumentConstructorStub");
2069   }
2070
2071   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructorConstantArgCount);
2072   DEFINE_HYDROGEN_CODE_STUB(ArrayNoArgumentConstructor,
2073                             ArrayConstructorStubBase);
2074 };
2075
2076
2077 class ArraySingleArgumentConstructorStub : public ArrayConstructorStubBase {
2078  public:
2079   ArraySingleArgumentConstructorStub(
2080       Isolate* isolate,
2081       ElementsKind kind,
2082       AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2083       : ArrayConstructorStubBase(isolate, kind, override_mode) {
2084   }
2085
2086  private:
2087   virtual void PrintName(OStream& os) const {  // NOLINT
2088     BasePrintName(os, "ArraySingleArgumentConstructorStub");
2089   }
2090
2091   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
2092   DEFINE_HYDROGEN_CODE_STUB(ArraySingleArgumentConstructor,
2093                             ArrayConstructorStubBase);
2094 };
2095
2096
2097 class ArrayNArgumentsConstructorStub : public ArrayConstructorStubBase {
2098  public:
2099   ArrayNArgumentsConstructorStub(
2100       Isolate* isolate,
2101       ElementsKind kind,
2102       AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2103       : ArrayConstructorStubBase(isolate, kind, override_mode) {
2104   }
2105
2106  private:
2107   virtual void PrintName(OStream& os) const {  // NOLINT
2108     BasePrintName(os, "ArrayNArgumentsConstructorStub");
2109   }
2110
2111   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
2112   DEFINE_HYDROGEN_CODE_STUB(ArrayNArgumentsConstructor,
2113                             ArrayConstructorStubBase);
2114 };
2115
2116
2117 class InternalArrayConstructorStubBase : public HydrogenCodeStub {
2118  public:
2119   InternalArrayConstructorStubBase(Isolate* isolate, ElementsKind kind)
2120       : HydrogenCodeStub(isolate) {
2121     set_sub_minor_key(ElementsKindBits::encode(kind));
2122   }
2123
2124   static void GenerateStubsAheadOfTime(Isolate* isolate);
2125
2126   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2127   static const int kConstructor = 0;
2128
2129   ElementsKind elements_kind() const {
2130     return ElementsKindBits::decode(sub_minor_key());
2131   }
2132
2133  private:
2134   class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
2135
2136   DEFINE_CODE_STUB_BASE(InternalArrayConstructorStubBase, HydrogenCodeStub);
2137 };
2138
2139
2140 class InternalArrayNoArgumentConstructorStub : public
2141     InternalArrayConstructorStubBase {
2142  public:
2143   InternalArrayNoArgumentConstructorStub(Isolate* isolate,
2144                                          ElementsKind kind)
2145       : InternalArrayConstructorStubBase(isolate, kind) { }
2146
2147   DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructorConstantArgCount);
2148   DEFINE_HYDROGEN_CODE_STUB(InternalArrayNoArgumentConstructor,
2149                             InternalArrayConstructorStubBase);
2150 };
2151
2152
2153 class InternalArraySingleArgumentConstructorStub : public
2154     InternalArrayConstructorStubBase {
2155  public:
2156   InternalArraySingleArgumentConstructorStub(Isolate* isolate,
2157                                              ElementsKind kind)
2158       : InternalArrayConstructorStubBase(isolate, kind) { }
2159
2160   DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
2161   DEFINE_HYDROGEN_CODE_STUB(InternalArraySingleArgumentConstructor,
2162                             InternalArrayConstructorStubBase);
2163 };
2164
2165
2166 class InternalArrayNArgumentsConstructorStub : public
2167     InternalArrayConstructorStubBase {
2168  public:
2169   InternalArrayNArgumentsConstructorStub(Isolate* isolate, ElementsKind kind)
2170       : InternalArrayConstructorStubBase(isolate, kind) { }
2171
2172   DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
2173   DEFINE_HYDROGEN_CODE_STUB(InternalArrayNArgumentsConstructor,
2174                             InternalArrayConstructorStubBase);
2175 };
2176
2177
2178 class StoreElementStub : public PlatformCodeStub {
2179  public:
2180   StoreElementStub(Isolate* isolate, ElementsKind elements_kind)
2181       : PlatformCodeStub(isolate) {
2182     minor_key_ = ElementsKindBits::encode(elements_kind);
2183   }
2184
2185  private:
2186   ElementsKind elements_kind() const {
2187     return ElementsKindBits::decode(minor_key_);
2188   }
2189
2190   class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
2191
2192   DEFINE_CALL_INTERFACE_DESCRIPTOR(Store);
2193   DEFINE_PLATFORM_CODE_STUB(StoreElement, PlatformCodeStub);
2194 };
2195
2196
2197 class ToBooleanStub: public HydrogenCodeStub {
2198  public:
2199   enum Type {
2200     UNDEFINED,
2201     BOOLEAN,
2202     NULL_TYPE,
2203     SMI,
2204     SPEC_OBJECT,
2205     STRING,
2206     SYMBOL,
2207     HEAP_NUMBER,
2208     NUMBER_OF_TYPES
2209   };
2210
2211   enum ResultMode {
2212     RESULT_AS_SMI,             // For Smi(1) on truthy value, Smi(0) otherwise.
2213     RESULT_AS_ODDBALL,         // For {true} on truthy value, {false} otherwise.
2214     RESULT_AS_INVERSE_ODDBALL  // For {false} on truthy value, {true} otherwise.
2215   };
2216
2217   // At most 8 different types can be distinguished, because the Code object
2218   // only has room for a single byte to hold a set of these types. :-P
2219   STATIC_ASSERT(NUMBER_OF_TYPES <= 8);
2220
2221   class Types : public EnumSet<Type, byte> {
2222    public:
2223     Types() : EnumSet<Type, byte>(0) {}
2224     explicit Types(byte bits) : EnumSet<Type, byte>(bits) {}
2225
2226     byte ToByte() const { return ToIntegral(); }
2227     bool UpdateStatus(Handle<Object> object);
2228     bool NeedsMap() const;
2229     bool CanBeUndetectable() const;
2230     bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); }
2231
2232     static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); }
2233   };
2234
2235   ToBooleanStub(Isolate* isolate, ResultMode mode, Types types = Types())
2236       : HydrogenCodeStub(isolate) {
2237     set_sub_minor_key(TypesBits::encode(types.ToByte()) |
2238                       ResultModeBits::encode(mode));
2239   }
2240
2241   ToBooleanStub(Isolate* isolate, ExtraICState state)
2242       : HydrogenCodeStub(isolate) {
2243     set_sub_minor_key(TypesBits::encode(static_cast<byte>(state)) |
2244                       ResultModeBits::encode(RESULT_AS_SMI));
2245   }
2246
2247   bool UpdateStatus(Handle<Object> object);
2248   Types types() const { return Types(TypesBits::decode(sub_minor_key())); }
2249   ResultMode mode() const { return ResultModeBits::decode(sub_minor_key()); }
2250
2251   virtual Code::Kind GetCodeKind() const { return Code::TO_BOOLEAN_IC; }
2252   virtual void PrintState(OStream& os) const OVERRIDE;  // NOLINT
2253
2254   virtual bool SometimesSetsUpAFrame() { return false; }
2255
2256   static Handle<Code> GetUninitialized(Isolate* isolate) {
2257     return ToBooleanStub(isolate, UNINITIALIZED).GetCode();
2258   }
2259
2260   virtual ExtraICState GetExtraICState() const { return types().ToIntegral(); }
2261
2262   virtual InlineCacheState GetICState() const {
2263     if (types().IsEmpty()) {
2264       return ::v8::internal::UNINITIALIZED;
2265     } else {
2266       return MONOMORPHIC;
2267     }
2268   }
2269
2270  private:
2271   ToBooleanStub(Isolate* isolate, InitializationState init_state)
2272       : HydrogenCodeStub(isolate, init_state) {
2273     set_sub_minor_key(ResultModeBits::encode(RESULT_AS_SMI));
2274   }
2275
2276   class TypesBits : public BitField<byte, 0, NUMBER_OF_TYPES> {};
2277   class ResultModeBits : public BitField<ResultMode, NUMBER_OF_TYPES, 2> {};
2278
2279   DEFINE_CALL_INTERFACE_DESCRIPTOR(ToBoolean);
2280   DEFINE_HYDROGEN_CODE_STUB(ToBoolean, HydrogenCodeStub);
2281 };
2282
2283
2284 OStream& operator<<(OStream& os, const ToBooleanStub::Types& t);
2285
2286
2287 class ElementsTransitionAndStoreStub : public HydrogenCodeStub {
2288  public:
2289   ElementsTransitionAndStoreStub(Isolate* isolate, ElementsKind from_kind,
2290                                  ElementsKind to_kind, bool is_jsarray,
2291                                  KeyedAccessStoreMode store_mode)
2292       : HydrogenCodeStub(isolate) {
2293     set_sub_minor_key(FromBits::encode(from_kind) | ToBits::encode(to_kind) |
2294                       IsJSArrayBits::encode(is_jsarray) |
2295                       StoreModeBits::encode(store_mode));
2296   }
2297
2298   ElementsKind from_kind() const { return FromBits::decode(sub_minor_key()); }
2299   ElementsKind to_kind() const { return ToBits::decode(sub_minor_key()); }
2300   bool is_jsarray() const { return IsJSArrayBits::decode(sub_minor_key()); }
2301   KeyedAccessStoreMode store_mode() const {
2302     return StoreModeBits::decode(sub_minor_key());
2303   }
2304
2305   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2306   enum ParameterIndices {
2307     kValueIndex,
2308     kMapIndex,
2309     kKeyIndex,
2310     kObjectIndex,
2311     kParameterCount
2312   };
2313
2314   static const Register ValueRegister() {
2315     return ElementTransitionAndStoreDescriptor::ValueRegister();
2316   }
2317   static const Register MapRegister() {
2318     return ElementTransitionAndStoreDescriptor::MapRegister();
2319   }
2320   static const Register KeyRegister() {
2321     return ElementTransitionAndStoreDescriptor::NameRegister();
2322   }
2323   static const Register ObjectRegister() {
2324     return ElementTransitionAndStoreDescriptor::ReceiverRegister();
2325   }
2326
2327  private:
2328   class FromBits : public BitField<ElementsKind, 0, 8> {};
2329   class ToBits : public BitField<ElementsKind, 8, 8> {};
2330   class IsJSArrayBits : public BitField<bool, 16, 1> {};
2331   class StoreModeBits : public BitField<KeyedAccessStoreMode, 17, 4> {};
2332
2333   DEFINE_CALL_INTERFACE_DESCRIPTOR(ElementTransitionAndStore);
2334   DEFINE_HYDROGEN_CODE_STUB(ElementsTransitionAndStore, HydrogenCodeStub);
2335 };
2336
2337
2338 class StoreArrayLiteralElementStub : public PlatformCodeStub {
2339  public:
2340   explicit StoreArrayLiteralElementStub(Isolate* isolate)
2341       : PlatformCodeStub(isolate) { }
2342
2343   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreArrayLiteralElement);
2344   DEFINE_PLATFORM_CODE_STUB(StoreArrayLiteralElement, PlatformCodeStub);
2345 };
2346
2347
2348 class StubFailureTrampolineStub : public PlatformCodeStub {
2349  public:
2350   StubFailureTrampolineStub(Isolate* isolate, StubFunctionMode function_mode)
2351       : PlatformCodeStub(isolate) {
2352     minor_key_ = FunctionModeField::encode(function_mode);
2353   }
2354
2355   static void GenerateAheadOfTime(Isolate* isolate);
2356
2357  private:
2358   StubFunctionMode function_mode() const {
2359     return FunctionModeField::decode(minor_key_);
2360   }
2361
2362   class FunctionModeField : public BitField<StubFunctionMode, 0, 1> {};
2363
2364   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2365   DEFINE_PLATFORM_CODE_STUB(StubFailureTrampoline, PlatformCodeStub);
2366 };
2367
2368
2369 class ProfileEntryHookStub : public PlatformCodeStub {
2370  public:
2371   explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2372
2373   // The profile entry hook function is not allowed to cause a GC.
2374   virtual bool SometimesSetsUpAFrame() { return false; }
2375
2376   // Generates a call to the entry hook if it's enabled.
2377   static void MaybeCallEntryHook(MacroAssembler* masm);
2378
2379  private:
2380   static void EntryHookTrampoline(intptr_t function,
2381                                   intptr_t stack_pointer,
2382                                   Isolate* isolate);
2383
2384   // ProfileEntryHookStub is called at the start of a function, so it has the
2385   // same register set.
2386   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction)
2387   DEFINE_PLATFORM_CODE_STUB(ProfileEntryHook, PlatformCodeStub);
2388 };
2389
2390
2391 class StoreBufferOverflowStub : public PlatformCodeStub {
2392  public:
2393   StoreBufferOverflowStub(Isolate* isolate, SaveFPRegsMode save_fp)
2394       : PlatformCodeStub(isolate) {
2395     minor_key_ = SaveDoublesBits::encode(save_fp == kSaveFPRegs);
2396   }
2397
2398   static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
2399   virtual bool SometimesSetsUpAFrame() { return false; }
2400
2401  private:
2402   bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
2403
2404   class SaveDoublesBits : public BitField<bool, 0, 1> {};
2405
2406   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2407   DEFINE_PLATFORM_CODE_STUB(StoreBufferOverflow, PlatformCodeStub);
2408 };
2409
2410
2411 class SubStringStub : public PlatformCodeStub {
2412  public:
2413   explicit SubStringStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2414
2415   DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
2416   DEFINE_PLATFORM_CODE_STUB(SubString, PlatformCodeStub);
2417 };
2418
2419
2420 class StringCompareStub : public PlatformCodeStub {
2421  public:
2422   explicit StringCompareStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2423
2424   DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
2425   DEFINE_PLATFORM_CODE_STUB(StringCompare, PlatformCodeStub);
2426 };
2427
2428
2429 #undef DEFINE_CALL_INTERFACE_DESCRIPTOR
2430 #undef DEFINE_PLATFORM_CODE_STUB
2431 #undef DEFINE_HANDLER_CODE_STUB
2432 #undef DEFINE_HYDROGEN_CODE_STUB
2433 #undef DEFINE_CODE_STUB
2434 #undef DEFINE_CODE_STUB_BASE
2435 } }  // namespace v8::internal
2436
2437 #endif  // V8_CODE_STUBS_H_