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