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