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