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
17namespace v8 {
18namespace 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.
136class 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
331class 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
348enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
349enum HandlerArgumentsMode { DONT_PASS_ARGUMENTS, PASS_ARGUMENTS };
350
351
352class 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
429class 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.
480class 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
516namespace v8 {
517namespace internal {
518
519
520// RuntimeCallHelper implementation used in stubs: enters/leaves a
521// newly created internal frame before/after the runtime call.
522class 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.
533class 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
543class 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
552class 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
564class 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
594class 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
616class 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
636class 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
658class 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
670class 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
714enum AllocationSiteOverrideMode {
715  DONT_OVERRIDE,
716  DISABLE_ALLOCATION_SITES,
717  LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
718};
719
720
721class 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
746class 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
758class 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
788class 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
830class 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.
847class 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.
863class 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
876class 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
895class 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
918class 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
932class 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
954class 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
966class 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
999class 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
1054class 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
1083class 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
1092class 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.
1141class 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
1184class 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
1208enum 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
1220class 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
1252class 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
1312class 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
1399OStream& operator<<(OStream& os, const CompareNilICStub::State& s);
1400
1401
1402class 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
1436class 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
1465class 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
1501class 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
1510class 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
1525class 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
1559class 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
1586enum 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.
1607class 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.
1665class 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.
1711class 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
1760class 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
1770class 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
1782class 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
1809class 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
1822class 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
1844class 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
1869class 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
1883class 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
1930class 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
1954class 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
1984class 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
2013class 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
2057class 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
2077class 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
2097class 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
2117class 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
2140class 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
2153class 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
2166class 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
2178class 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
2197class 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
2284OStream& operator<<(OStream& os, const ToBooleanStub::Types& t);
2285
2286
2287class 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
2338class 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
2348class 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
2369class 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
2391class 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
2411class 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
2420class 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_
2438