The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / code-stubs.h @ f230a1cf

History | View | Annotate | Download (69.7 KB)

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(BinaryOp)                            \
45
  V(StringAdd)                           \
46
  V(SubString)                           \
47
  V(StringCompare)                       \
48
  V(Compare)                             \
49
  V(CompareIC)                           \
50
  V(CompareNilIC)                        \
51
  V(MathPow)                             \
52
  V(StringLength)                        \
53
  V(FunctionPrototype)                   \
54
  V(StoreArrayLength)                    \
55
  V(RecordWrite)                         \
56
  V(StoreBufferOverflow)                 \
57
  V(RegExpExec)                          \
58
  V(TranscendentalCache)                 \
59
  V(Instanceof)                          \
60
  V(ConvertToDouble)                     \
61
  V(WriteInt32ToHeapNumber)              \
62
  V(StackCheck)                          \
63
  V(Interrupt)                           \
64
  V(FastNewClosure)                      \
65
  V(FastNewContext)                      \
66
  V(FastNewBlockContext)                 \
67
  V(FastCloneShallowArray)               \
68
  V(FastCloneShallowObject)              \
69
  V(CreateAllocationSite)                \
70
  V(ToBoolean)                           \
71
  V(ToNumber)                            \
72
  V(ArgumentsAccess)                     \
73
  V(RegExpConstructResult)               \
74
  V(NumberToString)                      \
75
  V(DoubleToI)                           \
76
  V(CEntry)                              \
77
  V(JSEntry)                             \
78
  V(KeyedLoadElement)                    \
79
  V(ArrayNoArgumentConstructor)          \
80
  V(ArraySingleArgumentConstructor)      \
81
  V(ArrayNArgumentsConstructor)          \
82
  V(InternalArrayNoArgumentConstructor)  \
83
  V(InternalArraySingleArgumentConstructor)      \
84
  V(InternalArrayNArgumentsConstructor)  \
85
  V(KeyedStoreElement)                   \
86
  V(DebuggerStatement)                   \
87
  V(NameDictionaryLookup)                \
88
  V(ElementsTransitionAndStore)          \
89
  V(TransitionElementsKind)              \
90
  V(StoreArrayLiteralElement)            \
91
  V(StubFailureTrampoline)               \
92
  V(ArrayConstructor)                    \
93
  V(InternalArrayConstructor)            \
94
  V(ProfileEntryHook)                    \
95
  V(StoreGlobal)                         \
96
  /* IC Handler stubs */                 \
97
  V(LoadField)                           \
98
  V(KeyedLoadField)
99

    
100
// List of code stubs only used on ARM platforms.
101
#if V8_TARGET_ARCH_ARM
102
#define CODE_STUB_LIST_ARM(V)  \
103
  V(GetProperty)               \
104
  V(SetProperty)               \
105
  V(InvokeBuiltin)             \
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.
127
enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
128

    
129
// Stub is base classes of all stubs.
130
class 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(isolate);
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(Isolate* isolate) { 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
  // Returns a name for logging/debugging purposes.
205
  SmartArrayPointer<const char> GetName();
206

    
207
 protected:
208
  static bool CanUseFPRegisters();
209

    
210
  // Generates the assembler code for the stub.
211
  virtual Handle<Code> GenerateCode(Isolate* isolate) = 0;
212

    
213
  virtual void VerifyPlatformFeatures(Isolate* isolate);
214

    
215
  // Returns whether the code generated for this stub needs to be allocated as
216
  // a fixed (non-moveable) code object.
217
  virtual bool NeedsImmovableCode() { return false; }
218

    
219
  virtual void PrintBaseName(StringStream* stream);
220
  virtual void PrintState(StringStream* stream) { }
221

    
222
 private:
223
  // Perform bookkeeping required after code generation when stub code is
224
  // initially generated.
225
  void RecordCodeGeneration(Code* code, Isolate* isolate);
226

    
227
  // Finish the code object after it has been generated.
228
  virtual void FinishCode(Handle<Code> code) { }
229

    
230
  // Activate newly generated stub. Is called after
231
  // registering stub in the stub cache.
232
  virtual void Activate(Code* code) { }
233

    
234
  // BinaryOpStub needs to override this.
235
  virtual Code::Kind GetCodeKind() const;
236

    
237
  // Add the code to a specialized cache, specific to an individual
238
  // stub type. Please note, this method must add the code object to a
239
  // roots object, otherwise we will remove the code during GC.
240
  virtual void AddToSpecialCache(Handle<Code> new_object) { }
241

    
242
  // Find code in a specialized cache, work is delegated to the specific stub.
243
  virtual bool FindCodeInSpecialCache(Code** code_out, Isolate* isolate) {
244
    return false;
245
  }
246

    
247
  // If a stub uses a special cache override this.
248
  virtual bool UseSpecialCache() { return false; }
249

    
250
  // Computes the key based on major and minor.
251
  uint32_t GetKey() {
252
    ASSERT(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
253
    return MinorKeyBits::encode(MinorKey()) |
254
           MajorKeyBits::encode(MajorKey());
255
  }
256

    
257
  class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
258
  class MinorKeyBits: public BitField<uint32_t,
259
      kStubMajorKeyBits, kStubMinorKeyBits> {};  // NOLINT
260

    
261
  friend class BreakPointIterator;
262
};
263

    
264

    
265
class PlatformCodeStub : public CodeStub {
266
 public:
267
  // Retrieve the code for the stub. Generate the code if needed.
268
  virtual Handle<Code> GenerateCode(Isolate* isolate);
269

    
270
  virtual Code::Kind GetCodeKind() const { return Code::STUB; }
271

    
272
 protected:
273
  // Generates the assembler code for the stub.
274
  virtual void Generate(MacroAssembler* masm) = 0;
275
};
276

    
277

    
278
enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
279

    
280

    
281
struct CodeStubInterfaceDescriptor {
282
  CodeStubInterfaceDescriptor();
283
  int register_param_count_;
284
  Register stack_parameter_count_;
285
  // if hint_stack_parameter_count_ > 0, the code stub can optimize the
286
  // return sequence. Default value is -1, which means it is ignored.
287
  int hint_stack_parameter_count_;
288
  StubFunctionMode function_mode_;
289
  Register* register_params_;
290
  Address deoptimization_handler_;
291

    
292
  int environment_length() const {
293
    if (stack_parameter_count_.is_valid()) {
294
      return register_param_count_ + 1;
295
    }
296
    return register_param_count_;
297
  }
298

    
299
  bool initialized() const { return register_param_count_ >= 0; }
300

    
301
  void SetMissHandler(ExternalReference handler) {
302
    miss_handler_ = handler;
303
    has_miss_handler_ = true;
304
  }
305

    
306
  ExternalReference miss_handler() {
307
    ASSERT(has_miss_handler_);
308
    return miss_handler_;
309
  }
310

    
311
  bool has_miss_handler() {
312
    return has_miss_handler_;
313
  }
314

    
315
 private:
316
  ExternalReference miss_handler_;
317
  bool has_miss_handler_;
318
};
319

    
320
// A helper to make up for the fact that type Register is not fully
321
// defined outside of the platform directories
322
#define DESCRIPTOR_GET_PARAMETER_REGISTER(descriptor, index) \
323
  ((index) == (descriptor)->register_param_count_)           \
324
      ? (descriptor)->stack_parameter_count_                 \
325
      : (descriptor)->register_params_[(index)]
326

    
327

    
328
class HydrogenCodeStub : public CodeStub {
329
 public:
330
  enum InitializationState {
331
    UNINITIALIZED,
332
    INITIALIZED
333
  };
334

    
335
  explicit HydrogenCodeStub(InitializationState state = INITIALIZED) {
336
    is_uninitialized_ = (state == UNINITIALIZED);
337
  }
338

    
339
  virtual Code::Kind GetCodeKind() const { return Code::STUB; }
340

    
341
  CodeStubInterfaceDescriptor* GetInterfaceDescriptor(Isolate* isolate) {
342
    return isolate->code_stub_interface_descriptor(MajorKey());
343
  }
344

    
345
  bool IsUninitialized() { return is_uninitialized_; }
346

    
347
  template<class SubClass>
348
  static Handle<Code> GetUninitialized(Isolate* isolate) {
349
    SubClass::GenerateAheadOfTime(isolate);
350
    return SubClass().GetCode(isolate);
351
  }
352

    
353
  virtual void InitializeInterfaceDescriptor(
354
      Isolate* isolate,
355
      CodeStubInterfaceDescriptor* descriptor) = 0;
356

    
357
  // Retrieve the code for the stub. Generate the code if needed.
358
  virtual Handle<Code> GenerateCode(Isolate* isolate) = 0;
359

    
360
  virtual int NotMissMinorKey() = 0;
361

    
362
  Handle<Code> GenerateLightweightMissCode(Isolate* isolate);
363

    
364
  template<class StateType>
365
  void TraceTransition(StateType from, StateType to);
366

    
367
 private:
368
  class MinorKeyBits: public BitField<int, 0, kStubMinorKeyBits - 1> {};
369
  class IsMissBits: public BitField<bool, kStubMinorKeyBits - 1, 1> {};
370

    
371
  void GenerateLightweightMiss(MacroAssembler* masm);
372
  virtual int MinorKey() {
373
    return IsMissBits::encode(is_uninitialized_) |
374
        MinorKeyBits::encode(NotMissMinorKey());
375
  }
376

    
377
  bool is_uninitialized_;
378
};
379

    
380

    
381
// Helper interface to prepare to/restore after making runtime calls.
382
class RuntimeCallHelper {
383
 public:
384
  virtual ~RuntimeCallHelper() {}
385

    
386
  virtual void BeforeCall(MacroAssembler* masm) const = 0;
387

    
388
  virtual void AfterCall(MacroAssembler* masm) const = 0;
389

    
390
 protected:
391
  RuntimeCallHelper() {}
392

    
393
 private:
394
  DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
395
};
396

    
397

    
398
// TODO(bmeurer): Move to the StringAddStub declaration once we're
399
// done with the translation to a hydrogen code stub.
400
enum StringAddFlags {
401
  // Omit both parameter checks.
402
  STRING_ADD_CHECK_NONE = 0,
403
  // Check left parameter.
404
  STRING_ADD_CHECK_LEFT = 1 << 0,
405
  // Check right parameter.
406
  STRING_ADD_CHECK_RIGHT = 1 << 1,
407
  // Check both parameters.
408
  STRING_ADD_CHECK_BOTH = STRING_ADD_CHECK_LEFT | STRING_ADD_CHECK_RIGHT
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

    
425
namespace v8 {
426
namespace internal {
427

    
428

    
429
// RuntimeCallHelper implementation used in stubs: enters/leaves a
430
// newly created internal frame before/after the runtime call.
431
class 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.
442
class 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

    
452
class ToNumberStub: public HydrogenCodeStub {
453
 public:
454
  ToNumberStub() { }
455

    
456
  virtual Handle<Code> GenerateCode(Isolate* isolate);
457

    
458
  virtual void InitializeInterfaceDescriptor(
459
      Isolate* isolate,
460
      CodeStubInterfaceDescriptor* descriptor);
461

    
462
 private:
463
  Major MajorKey() { return ToNumber; }
464
  int NotMissMinorKey() { return 0; }
465
};
466

    
467

    
468
class NumberToStringStub V8_FINAL : public HydrogenCodeStub {
469
 public:
470
  NumberToStringStub() {}
471

    
472
  virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE;
473

    
474
  virtual void InitializeInterfaceDescriptor(
475
      Isolate* isolate,
476
      CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
477

    
478
  static void InstallDescriptors(Isolate* isolate);
479

    
480
  // Parameters accessed via CodeStubGraphBuilder::GetParameter()
481
  static const int kNumber = 0;
482

    
483
 private:
484
  virtual Major MajorKey() V8_OVERRIDE { return NumberToString; }
485
  virtual int NotMissMinorKey() V8_OVERRIDE { return 0; }
486
};
487

    
488

    
489
class FastNewClosureStub : public HydrogenCodeStub {
490
 public:
491
  explicit FastNewClosureStub(LanguageMode language_mode, bool is_generator)
492
    : language_mode_(language_mode),
493
      is_generator_(is_generator) { }
494

    
495
  virtual Handle<Code> GenerateCode(Isolate* isolate);
496

    
497
  virtual void InitializeInterfaceDescriptor(
498
      Isolate* isolate,
499
      CodeStubInterfaceDescriptor* descriptor);
500

    
501
  static void InstallDescriptors(Isolate* isolate);
502

    
503
  LanguageMode language_mode() const { return language_mode_; }
504
  bool is_generator() const { return is_generator_; }
505

    
506
 private:
507
  class StrictModeBits: public BitField<bool, 0, 1> {};
508
  class IsGeneratorBits: public BitField<bool, 1, 1> {};
509

    
510
  Major MajorKey() { return FastNewClosure; }
511
  int NotMissMinorKey() {
512
    return StrictModeBits::encode(language_mode_ != CLASSIC_MODE) |
513
      IsGeneratorBits::encode(is_generator_);
514
  }
515

    
516
  LanguageMode language_mode_;
517
  bool is_generator_;
518
};
519

    
520

    
521
class FastNewContextStub : public PlatformCodeStub {
522
 public:
523
  static const int kMaximumSlots = 64;
524

    
525
  explicit FastNewContextStub(int slots) : slots_(slots) {
526
    ASSERT(slots_ > 0 && slots_ <= kMaximumSlots);
527
  }
528

    
529
  void Generate(MacroAssembler* masm);
530

    
531
 private:
532
  int slots_;
533

    
534
  Major MajorKey() { return FastNewContext; }
535
  int MinorKey() { return slots_; }
536
};
537

    
538

    
539
class FastNewBlockContextStub : public PlatformCodeStub {
540
 public:
541
  static const int kMaximumSlots = 64;
542

    
543
  explicit FastNewBlockContextStub(int slots) : slots_(slots) {
544
    ASSERT(slots_ > 0 && slots_ <= kMaximumSlots);
545
  }
546

    
547
  void Generate(MacroAssembler* masm);
548

    
549
 private:
550
  int slots_;
551

    
552
  Major MajorKey() { return FastNewBlockContext; }
553
  int MinorKey() { return slots_; }
554
};
555

    
556
class StoreGlobalStub : public HydrogenCodeStub {
557
 public:
558
  StoreGlobalStub(StrictModeFlag strict_mode, bool is_constant) {
559
    bit_field_ = StrictModeBits::encode(strict_mode) |
560
        IsConstantBits::encode(is_constant);
561
  }
562

    
563
  virtual Handle<Code> GenerateCode(Isolate* isolate);
564

    
565
  virtual void InitializeInterfaceDescriptor(
566
      Isolate* isolate,
567
      CodeStubInterfaceDescriptor* descriptor);
568

    
569
  virtual Code::Kind GetCodeKind() const { return Code::STORE_IC; }
570
  virtual InlineCacheState GetICState() { return MONOMORPHIC; }
571
  virtual Code::ExtraICState GetExtraICState() { return bit_field_; }
572

    
573
  bool is_constant() {
574
    return IsConstantBits::decode(bit_field_);
575
  }
576
  void set_is_constant(bool value) {
577
    bit_field_ = IsConstantBits::update(bit_field_, value);
578
  }
579

    
580
  Representation representation() {
581
    return Representation::FromKind(RepresentationBits::decode(bit_field_));
582
  }
583
  void set_representation(Representation r) {
584
    bit_field_ = RepresentationBits::update(bit_field_, r.kind());
585
  }
586

    
587
 private:
588
  virtual int NotMissMinorKey() { return GetExtraICState(); }
589
  Major MajorKey() { return StoreGlobal; }
590

    
591
  class StrictModeBits: public BitField<StrictModeFlag, 0, 1> {};
592
  class IsConstantBits: public BitField<bool, 1, 1> {};
593
  class RepresentationBits: public BitField<Representation::Kind, 2, 8> {};
594

    
595
  int bit_field_;
596

    
597
  DISALLOW_COPY_AND_ASSIGN(StoreGlobalStub);
598
};
599

    
600

    
601
class FastCloneShallowArrayStub : public HydrogenCodeStub {
602
 public:
603
  // Maximum length of copied elements array.
604
  static const int kMaximumClonedLength = 8;
605
  enum Mode {
606
    CLONE_ELEMENTS,
607
    CLONE_DOUBLE_ELEMENTS,
608
    COPY_ON_WRITE_ELEMENTS,
609
    CLONE_ANY_ELEMENTS,
610
    LAST_CLONE_MODE = CLONE_ANY_ELEMENTS
611
  };
612

    
613
  static const int kFastCloneModeCount = LAST_CLONE_MODE + 1;
614

    
615
  FastCloneShallowArrayStub(Mode mode,
616
                            AllocationSiteMode allocation_site_mode,
617
                            int length)
618
      : mode_(mode),
619
        allocation_site_mode_(allocation_site_mode),
620
        length_((mode == COPY_ON_WRITE_ELEMENTS) ? 0 : length) {
621
    ASSERT_GE(length_, 0);
622
    ASSERT_LE(length_, kMaximumClonedLength);
623
  }
624

    
625
  Mode mode() const { return mode_; }
626
  int length() const { return length_; }
627
  AllocationSiteMode allocation_site_mode() const {
628
    return allocation_site_mode_;
629
  }
630

    
631
  ElementsKind ComputeElementsKind() const {
632
    switch (mode()) {
633
      case CLONE_ELEMENTS:
634
      case COPY_ON_WRITE_ELEMENTS:
635
        return FAST_ELEMENTS;
636
      case CLONE_DOUBLE_ELEMENTS:
637
        return FAST_DOUBLE_ELEMENTS;
638
      case CLONE_ANY_ELEMENTS:
639
        /*fall-through*/;
640
    }
641
    UNREACHABLE();
642
    return LAST_ELEMENTS_KIND;
643
  }
644

    
645
  virtual Handle<Code> GenerateCode(Isolate* isolate);
646

    
647
  virtual void InitializeInterfaceDescriptor(
648
      Isolate* isolate,
649
      CodeStubInterfaceDescriptor* descriptor);
650

    
651
 private:
652
  Mode mode_;
653
  AllocationSiteMode allocation_site_mode_;
654
  int length_;
655

    
656
  class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {};
657
  class ModeBits: public BitField<Mode, 1, 4> {};
658
  class LengthBits: public BitField<int, 5, 4> {};
659
  // Ensure data fits within available bits.
660
  STATIC_ASSERT(LAST_ALLOCATION_SITE_MODE == 1);
661
  STATIC_ASSERT(kFastCloneModeCount < 16);
662
  STATIC_ASSERT(kMaximumClonedLength < 16);
663
  Major MajorKey() { return FastCloneShallowArray; }
664
  int NotMissMinorKey() {
665
    return AllocationSiteModeBits::encode(allocation_site_mode_)
666
        | ModeBits::encode(mode_)
667
        | LengthBits::encode(length_);
668
  }
669
};
670

    
671

    
672
class FastCloneShallowObjectStub : public HydrogenCodeStub {
673
 public:
674
  // Maximum number of properties in copied object.
675
  static const int kMaximumClonedProperties = 6;
676

    
677
  explicit FastCloneShallowObjectStub(int length)
678
      : length_(length) {
679
    ASSERT_GE(length_, 0);
680
    ASSERT_LE(length_, kMaximumClonedProperties);
681
  }
682

    
683
  int length() const { return length_; }
684

    
685
  virtual Handle<Code> GenerateCode(Isolate* isolate);
686

    
687
  virtual void InitializeInterfaceDescriptor(
688
      Isolate* isolate,
689
      CodeStubInterfaceDescriptor* descriptor);
690

    
691
 private:
692
  int length_;
693

    
694
  Major MajorKey() { return FastCloneShallowObject; }
695
  int NotMissMinorKey() { return length_; }
696

    
697
  DISALLOW_COPY_AND_ASSIGN(FastCloneShallowObjectStub);
698
};
699

    
700

    
701
class CreateAllocationSiteStub : public HydrogenCodeStub {
702
 public:
703
  explicit CreateAllocationSiteStub() { }
704

    
705
  virtual Handle<Code> GenerateCode(Isolate* isolate);
706

    
707
  virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE { return true; }
708

    
709
  static void GenerateAheadOfTime(Isolate* isolate);
710

    
711
  virtual void InitializeInterfaceDescriptor(
712
      Isolate* isolate,
713
      CodeStubInterfaceDescriptor* descriptor);
714

    
715
 private:
716
  Major MajorKey() { return CreateAllocationSite; }
717
  int NotMissMinorKey() { return 0; }
718

    
719
  DISALLOW_COPY_AND_ASSIGN(CreateAllocationSiteStub);
720
};
721

    
722

    
723
class InstanceofStub: public PlatformCodeStub {
724
 public:
725
  enum Flags {
726
    kNoFlags = 0,
727
    kArgsInRegisters = 1 << 0,
728
    kCallSiteInlineCheck = 1 << 1,
729
    kReturnTrueFalseObject = 1 << 2
730
  };
731

    
732
  explicit InstanceofStub(Flags flags) : flags_(flags) { }
733

    
734
  static Register left();
735
  static Register right();
736

    
737
  void Generate(MacroAssembler* masm);
738

    
739
 private:
740
  Major MajorKey() { return Instanceof; }
741
  int MinorKey() { return static_cast<int>(flags_); }
742

    
743
  bool HasArgsInRegisters() const {
744
    return (flags_ & kArgsInRegisters) != 0;
745
  }
746

    
747
  bool HasCallSiteInlineCheck() const {
748
    return (flags_ & kCallSiteInlineCheck) != 0;
749
  }
750

    
751
  bool ReturnTrueFalseObject() const {
752
    return (flags_ & kReturnTrueFalseObject) != 0;
753
  }
754

    
755
  virtual void PrintName(StringStream* stream);
756

    
757
  Flags flags_;
758
};
759

    
760

    
761
enum AllocationSiteOverrideMode {
762
  DONT_OVERRIDE,
763
  DISABLE_ALLOCATION_SITES,
764
  LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
765
};
766

    
767

    
768
class ArrayConstructorStub: public PlatformCodeStub {
769
 public:
770
  enum ArgumentCountKey { ANY, NONE, ONE, MORE_THAN_ONE };
771
  ArrayConstructorStub(Isolate* isolate, int argument_count);
772
  explicit ArrayConstructorStub(Isolate* isolate);
773

    
774
  void Generate(MacroAssembler* masm);
775

    
776
 private:
777
  void GenerateDispatchToArrayStub(MacroAssembler* masm,
778
                                   AllocationSiteOverrideMode mode);
779

    
780
  virtual CodeStub::Major MajorKey() { return ArrayConstructor; }
781
  virtual int MinorKey() { return argument_count_; }
782

    
783
  ArgumentCountKey argument_count_;
784
};
785

    
786

    
787
class InternalArrayConstructorStub: public PlatformCodeStub {
788
 public:
789
  explicit InternalArrayConstructorStub(Isolate* isolate);
790

    
791
  void Generate(MacroAssembler* masm);
792

    
793
 private:
794
  virtual CodeStub::Major MajorKey() { return InternalArrayConstructor; }
795
  virtual int MinorKey() { return 0; }
796

    
797
  void GenerateCase(MacroAssembler* masm, ElementsKind kind);
798
};
799

    
800

    
801
class MathPowStub: public PlatformCodeStub {
802
 public:
803
  enum ExponentType { INTEGER, DOUBLE, TAGGED, ON_STACK };
804

    
805
  explicit MathPowStub(ExponentType exponent_type)
806
      : exponent_type_(exponent_type) { }
807
  virtual void Generate(MacroAssembler* masm);
808

    
809
 private:
810
  virtual CodeStub::Major MajorKey() { return MathPow; }
811
  virtual int MinorKey() { return exponent_type_; }
812

    
813
  ExponentType exponent_type_;
814
};
815

    
816

    
817
class ICStub: public PlatformCodeStub {
818
 public:
819
  explicit ICStub(Code::Kind kind) : kind_(kind) { }
820
  virtual Code::Kind GetCodeKind() const { return kind_; }
821
  virtual InlineCacheState GetICState() { return MONOMORPHIC; }
822

    
823
  bool Describes(Code* code) {
824
    return GetMajorKey(code) == MajorKey() && code->stub_info() == MinorKey();
825
  }
826

    
827
 protected:
828
  class KindBits: public BitField<Code::Kind, 0, 4> {};
829
  virtual void FinishCode(Handle<Code> code) {
830
    code->set_stub_info(MinorKey());
831
  }
832
  Code::Kind kind() { return kind_; }
833

    
834
  virtual int MinorKey() {
835
    return KindBits::encode(kind_);
836
  }
837

    
838
 private:
839
  Code::Kind kind_;
840
};
841

    
842

    
843
class FunctionPrototypeStub: public ICStub {
844
 public:
845
  explicit FunctionPrototypeStub(Code::Kind kind) : ICStub(kind) { }
846
  virtual void Generate(MacroAssembler* masm);
847

    
848
 private:
849
  virtual CodeStub::Major MajorKey() { return FunctionPrototype; }
850
};
851

    
852

    
853
class StringLengthStub: public ICStub {
854
 public:
855
  explicit StringLengthStub(Code::Kind kind) : ICStub(kind) { }
856
  virtual void Generate(MacroAssembler* masm);
857

    
858
 private:
859
  STATIC_ASSERT(KindBits::kSize == 4);
860
    virtual CodeStub::Major MajorKey() { return StringLength; }
861
};
862

    
863

    
864
class StoreICStub: public ICStub {
865
 public:
866
  StoreICStub(Code::Kind kind, StrictModeFlag strict_mode)
867
      : ICStub(kind), strict_mode_(strict_mode) { }
868

    
869
 protected:
870
  virtual Code::ExtraICState GetExtraICState() {
871
    return strict_mode_;
872
  }
873

    
874
 private:
875
  STATIC_ASSERT(KindBits::kSize == 4);
876
  class StrictModeBits: public BitField<bool, 4, 1> {};
877
  virtual int MinorKey() {
878
    return KindBits::encode(kind()) | StrictModeBits::encode(strict_mode_);
879
  }
880

    
881
  StrictModeFlag strict_mode_;
882
};
883

    
884

    
885
class StoreArrayLengthStub: public StoreICStub {
886
 public:
887
  explicit StoreArrayLengthStub(Code::Kind kind, StrictModeFlag strict_mode)
888
      : StoreICStub(kind, strict_mode) { }
889
  virtual void Generate(MacroAssembler* masm);
890

    
891
 private:
892
  virtual CodeStub::Major MajorKey() { return StoreArrayLength; }
893
};
894

    
895

    
896
class HICStub: public HydrogenCodeStub {
897
 public:
898
  virtual Code::Kind GetCodeKind() const { return kind(); }
899
  virtual InlineCacheState GetICState() { return MONOMORPHIC; }
900

    
901
 protected:
902
  HICStub() { }
903
  class KindBits: public BitField<Code::Kind, 0, 4> {};
904
  virtual Code::Kind kind() const = 0;
905
};
906

    
907

    
908
class HandlerStub: public HICStub {
909
 public:
910
  virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
911
  virtual int GetStubFlags() { return kind(); }
912

    
913
 protected:
914
  HandlerStub() : HICStub() { }
915
};
916

    
917

    
918
class LoadFieldStub: public HandlerStub {
919
 public:
920
  LoadFieldStub(bool inobject, int index, Representation representation)
921
      : HandlerStub() {
922
    Initialize(Code::LOAD_IC, inobject, index, representation);
923
  }
924

    
925
  virtual Handle<Code> GenerateCode(Isolate* isolate);
926

    
927
  virtual void InitializeInterfaceDescriptor(
928
      Isolate* isolate,
929
      CodeStubInterfaceDescriptor* descriptor);
930

    
931
  Representation representation() {
932
    if (unboxed_double()) return Representation::Double();
933
    return Representation::Tagged();
934
  }
935

    
936
  virtual Code::Kind kind() const {
937
    return KindBits::decode(bit_field_);
938
  }
939

    
940
  bool is_inobject() {
941
    return InobjectBits::decode(bit_field_);
942
  }
943

    
944
  int offset() {
945
    int index = IndexBits::decode(bit_field_);
946
    int offset = index * kPointerSize;
947
    if (is_inobject()) return offset;
948
    return FixedArray::kHeaderSize + offset;
949
  }
950

    
951
  bool unboxed_double() {
952
    return UnboxedDoubleBits::decode(bit_field_);
953
  }
954

    
955
  virtual Code::StubType GetStubType() { return Code::FIELD; }
956

    
957
 protected:
958
  LoadFieldStub() : HandlerStub() { }
959

    
960
  void Initialize(Code::Kind kind,
961
                  bool inobject,
962
                  int index,
963
                  Representation representation) {
964
    bool unboxed_double = FLAG_track_double_fields && representation.IsDouble();
965
    bit_field_ = KindBits::encode(kind)
966
        | InobjectBits::encode(inobject)
967
        | IndexBits::encode(index)
968
        | UnboxedDoubleBits::encode(unboxed_double);
969
  }
970

    
971
 private:
972
  STATIC_ASSERT(KindBits::kSize == 4);
973
  class InobjectBits: public BitField<bool, 4, 1> {};
974
  class IndexBits: public BitField<int, 5, 11> {};
975
  class UnboxedDoubleBits: public BitField<bool, 16, 1> {};
976
  virtual CodeStub::Major MajorKey() { return LoadField; }
977
  virtual int NotMissMinorKey() { return bit_field_; }
978

    
979
  int bit_field_;
980
};
981

    
982

    
983
class KeyedLoadFieldStub: public LoadFieldStub {
984
 public:
985
  KeyedLoadFieldStub(bool inobject, int index, Representation representation)
986
      : LoadFieldStub() {
987
    Initialize(Code::KEYED_LOAD_IC, inobject, index, representation);
988
  }
989

    
990
  virtual void InitializeInterfaceDescriptor(
991
      Isolate* isolate,
992
      CodeStubInterfaceDescriptor* descriptor);
993

    
994
  virtual Handle<Code> GenerateCode(Isolate* isolate);
995

    
996
 private:
997
  virtual CodeStub::Major MajorKey() { return KeyedLoadField; }
998
};
999

    
1000

    
1001
class BinaryOpStub: public HydrogenCodeStub {
1002
 public:
1003
  BinaryOpStub(Token::Value op, OverwriteMode mode)
1004
      : HydrogenCodeStub(UNINITIALIZED), op_(op), mode_(mode) {
1005
    ASSERT(op <= LAST_TOKEN && op >= FIRST_TOKEN);
1006
    Initialize();
1007
  }
1008

    
1009
  explicit BinaryOpStub(Code::ExtraICState state)
1010
      : op_(decode_token(OpBits::decode(state))),
1011
        mode_(OverwriteModeField::decode(state)),
1012
        fixed_right_arg_(
1013
            Maybe<int>(HasFixedRightArgBits::decode(state),
1014
                decode_arg_value(FixedRightArgValueBits::decode(state)))),
1015
        left_state_(LeftStateField::decode(state)),
1016
        right_state_(fixed_right_arg_.has_value
1017
            ? ((fixed_right_arg_.value <= Smi::kMaxValue) ? SMI : INT32)
1018
            : RightStateField::decode(state)),
1019
        result_state_(ResultStateField::decode(state)) {
1020
    // We don't deserialize the SSE2 Field, since this is only used to be able
1021
    // to include SSE2 as well as non-SSE2 versions in the snapshot. For code
1022
    // generation we always want it to reflect the current state.
1023
    ASSERT(!fixed_right_arg_.has_value ||
1024
           can_encode_arg_value(fixed_right_arg_.value));
1025
  }
1026

    
1027
  static const int FIRST_TOKEN = Token::BIT_OR;
1028
  static const int LAST_TOKEN = Token::MOD;
1029

    
1030
  static void GenerateAheadOfTime(Isolate* isolate);
1031
  virtual void InitializeInterfaceDescriptor(
1032
      Isolate* isolate, CodeStubInterfaceDescriptor* descriptor);
1033
  static void InitializeForIsolate(Isolate* isolate) {
1034
    BinaryOpStub binopStub(UNINITIALIZED);
1035
    binopStub.InitializeInterfaceDescriptor(
1036
        isolate, isolate->code_stub_interface_descriptor(CodeStub::BinaryOp));
1037
  }
1038

    
1039
  virtual Code::Kind GetCodeKind() const { return Code::BINARY_OP_IC; }
1040
  virtual InlineCacheState GetICState() {
1041
    if (Max(left_state_, right_state_) == NONE) {
1042
      return ::v8::internal::UNINITIALIZED;
1043
    }
1044
    if (Max(left_state_, right_state_) == GENERIC) return MEGAMORPHIC;
1045
    return MONOMORPHIC;
1046
  }
1047

    
1048
  virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
1049
    ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
1050
  }
1051

    
1052
  virtual Code::ExtraICState GetExtraICState() {
1053
    bool sse_field = Max(result_state_, Max(left_state_, right_state_)) > SMI &&
1054
                     CpuFeatures::IsSafeForSnapshot(SSE2);
1055

    
1056
    return OpBits::encode(encode_token(op_))
1057
         | LeftStateField::encode(left_state_)
1058
         | RightStateField::encode(fixed_right_arg_.has_value
1059
                                       ? NONE : right_state_)
1060
         | ResultStateField::encode(result_state_)
1061
         | HasFixedRightArgBits::encode(fixed_right_arg_.has_value)
1062
         | FixedRightArgValueBits::encode(fixed_right_arg_.has_value
1063
                                              ? encode_arg_value(
1064
                                                  fixed_right_arg_.value)
1065
                                              : 0)
1066
         | SSE2Field::encode(sse_field)
1067
         | OverwriteModeField::encode(mode_);
1068
  }
1069

    
1070
  bool CanReuseDoubleBox() {
1071
    return result_state_ <= NUMBER && result_state_ > SMI &&
1072
      ((left_state_ > SMI && left_state_ <= NUMBER &&
1073
        mode_ == OVERWRITE_LEFT) ||
1074
       (right_state_ > SMI && right_state_ <= NUMBER &&
1075
        mode_ == OVERWRITE_RIGHT));
1076
  }
1077

    
1078
  bool HasSideEffects(Isolate* isolate) const {
1079
    Handle<Type> left = GetLeftType(isolate);
1080
    Handle<Type> right = GetRightType(isolate);
1081
    return left->Maybe(Type::Receiver()) || right->Maybe(Type::Receiver());
1082
  }
1083

    
1084
  virtual Handle<Code> GenerateCode(Isolate* isolate);
1085

    
1086
  Maybe<Handle<Object> > Result(Handle<Object> left,
1087
                         Handle<Object> right,
1088
                         Isolate* isolate);
1089

    
1090
  Token::Value operation() const { return op_; }
1091
  OverwriteMode mode() const { return mode_; }
1092
  Maybe<int> fixed_right_arg() const { return fixed_right_arg_; }
1093

    
1094
  Handle<Type> GetLeftType(Isolate* isolate) const;
1095
  Handle<Type> GetRightType(Isolate* isolate) const;
1096
  Handle<Type> GetResultType(Isolate* isolate) const;
1097

    
1098
  void UpdateStatus(Handle<Object> left,
1099
                    Handle<Object> right,
1100
                    Maybe<Handle<Object> > result);
1101

    
1102
  void PrintState(StringStream* stream);
1103

    
1104
 private:
1105
  explicit BinaryOpStub(InitializationState state) : HydrogenCodeStub(state),
1106
                                                     op_(Token::ADD),
1107
                                                     mode_(NO_OVERWRITE) {
1108
    Initialize();
1109
  }
1110
  void Initialize();
1111

    
1112
  enum State { NONE, SMI, INT32, NUMBER, STRING, GENERIC };
1113

    
1114
  // We truncate the last bit of the token.
1115
  STATIC_ASSERT(LAST_TOKEN - FIRST_TOKEN < (1 << 5));
1116
  class LeftStateField:         public BitField<State, 0,  3> {};
1117
  // When fixed right arg is set, we don't need to store the right state.
1118
  // Thus the two fields can overlap.
1119
  class HasFixedRightArgBits:   public BitField<bool, 4, 1> {};
1120
  class FixedRightArgValueBits: public BitField<int,  5, 4> {};
1121
  class RightStateField:        public BitField<State, 5, 3> {};
1122
  class ResultStateField:       public BitField<State, 9, 3> {};
1123
  class SSE2Field:              public BitField<bool, 12, 1> {};
1124
  class OverwriteModeField:     public BitField<OverwriteMode, 13, 2> {};
1125
  class OpBits:                 public BitField<int, 15,  5> {};
1126

    
1127
  virtual CodeStub::Major MajorKey() { return BinaryOp; }
1128
  virtual int NotMissMinorKey() { return GetExtraICState(); }
1129

    
1130
  static Handle<Type> StateToType(State state,
1131
                                  Isolate* isolate);
1132

    
1133
  static void Generate(Token::Value op,
1134
                       State left,
1135
                       int right,
1136
                       State result,
1137
                       OverwriteMode mode,
1138
                       Isolate* isolate);
1139

    
1140
  static void Generate(Token::Value op,
1141
                       State left,
1142
                       State right,
1143
                       State result,
1144
                       OverwriteMode mode,
1145
                       Isolate* isolate);
1146

    
1147
  void UpdateStatus(Handle<Object> object,
1148
                    State* state);
1149

    
1150
  bool can_encode_arg_value(int32_t value) const;
1151
  int encode_arg_value(int32_t value) const;
1152
  int32_t decode_arg_value(int value)  const;
1153
  int encode_token(Token::Value op) const;
1154
  Token::Value decode_token(int op) const;
1155

    
1156
  bool has_int_result() const {
1157
    return op_ == Token::BIT_XOR || op_ == Token::BIT_AND ||
1158
           op_ == Token::BIT_OR || op_ == Token::SAR || op_ == Token::SHL;
1159
  }
1160

    
1161
  const char* StateToName(State state);
1162

    
1163
  void PrintBaseName(StringStream* stream);
1164

    
1165
  Token::Value op_;
1166
  OverwriteMode mode_;
1167

    
1168
  Maybe<int> fixed_right_arg_;
1169
  State left_state_;
1170
  State right_state_;
1171
  State result_state_;
1172
};
1173

    
1174

    
1175
class ICCompareStub: public PlatformCodeStub {
1176
 public:
1177
  ICCompareStub(Token::Value op,
1178
                CompareIC::State left,
1179
                CompareIC::State right,
1180
                CompareIC::State handler)
1181
      : op_(op),
1182
        left_(left),
1183
        right_(right),
1184
        state_(handler) {
1185
    ASSERT(Token::IsCompareOp(op));
1186
  }
1187

    
1188
  virtual void Generate(MacroAssembler* masm);
1189

    
1190
  void set_known_map(Handle<Map> map) { known_map_ = map; }
1191

    
1192
  static void DecodeMinorKey(int minor_key,
1193
                             CompareIC::State* left_state,
1194
                             CompareIC::State* right_state,
1195
                             CompareIC::State* handler_state,
1196
                             Token::Value* op);
1197

    
1198
  static CompareIC::State CompareState(int minor_key) {
1199
    return static_cast<CompareIC::State>(HandlerStateField::decode(minor_key));
1200
  }
1201

    
1202
  virtual InlineCacheState GetICState();
1203

    
1204
 private:
1205
  class OpField: public BitField<int, 0, 3> { };
1206
  class LeftStateField: public BitField<int, 3, 4> { };
1207
  class RightStateField: public BitField<int, 7, 4> { };
1208
  class HandlerStateField: public BitField<int, 11, 4> { };
1209

    
1210
  virtual void FinishCode(Handle<Code> code) {
1211
    code->set_stub_info(MinorKey());
1212
  }
1213

    
1214
  virtual CodeStub::Major MajorKey() { return CompareIC; }
1215
  virtual int MinorKey();
1216

    
1217
  virtual Code::Kind GetCodeKind() const { return Code::COMPARE_IC; }
1218

    
1219
  void GenerateSmis(MacroAssembler* masm);
1220
  void GenerateNumbers(MacroAssembler* masm);
1221
  void GenerateInternalizedStrings(MacroAssembler* masm);
1222
  void GenerateStrings(MacroAssembler* masm);
1223
  void GenerateUniqueNames(MacroAssembler* masm);
1224
  void GenerateObjects(MacroAssembler* masm);
1225
  void GenerateMiss(MacroAssembler* masm);
1226
  void GenerateKnownObjects(MacroAssembler* masm);
1227
  void GenerateGeneric(MacroAssembler* masm);
1228

    
1229
  bool strict() const { return op_ == Token::EQ_STRICT; }
1230
  Condition GetCondition() const { return CompareIC::ComputeCondition(op_); }
1231

    
1232
  virtual void AddToSpecialCache(Handle<Code> new_object);
1233
  virtual bool FindCodeInSpecialCache(Code** code_out, Isolate* isolate);
1234
  virtual bool UseSpecialCache() { return state_ == CompareIC::KNOWN_OBJECT; }
1235

    
1236
  Token::Value op_;
1237
  CompareIC::State left_;
1238
  CompareIC::State right_;
1239
  CompareIC::State state_;
1240
  Handle<Map> known_map_;
1241
};
1242

    
1243

    
1244
class CompareNilICStub : public HydrogenCodeStub  {
1245
 public:
1246
  Handle<Type> GetType(Isolate* isolate, Handle<Map> map = Handle<Map>());
1247
  Handle<Type> GetInputType(Isolate* isolate, Handle<Map> map);
1248

    
1249
  explicit CompareNilICStub(NilValue nil) : nil_value_(nil) { }
1250

    
1251
  CompareNilICStub(Code::ExtraICState ic_state,
1252
                   InitializationState init_state = INITIALIZED)
1253
      : HydrogenCodeStub(init_state),
1254
        nil_value_(NilValueField::decode(ic_state)),
1255
        state_(State(TypesField::decode(ic_state))) {
1256
      }
1257

    
1258
  static Handle<Code> GetUninitialized(Isolate* isolate,
1259
                                       NilValue nil) {
1260
    return CompareNilICStub(nil, UNINITIALIZED).GetCode(isolate);
1261
  }
1262

    
1263
  virtual void InitializeInterfaceDescriptor(
1264
      Isolate* isolate,
1265
      CodeStubInterfaceDescriptor* descriptor);
1266

    
1267
  static void InitializeForIsolate(Isolate* isolate) {
1268
    CompareNilICStub compare_stub(kNullValue, UNINITIALIZED);
1269
    compare_stub.InitializeInterfaceDescriptor(
1270
        isolate,
1271
        isolate->code_stub_interface_descriptor(CodeStub::CompareNilIC));
1272
  }
1273

    
1274
  virtual InlineCacheState GetICState() {
1275
    if (state_.Contains(GENERIC)) {
1276
      return MEGAMORPHIC;
1277
    } else if (state_.Contains(MONOMORPHIC_MAP)) {
1278
      return MONOMORPHIC;
1279
    } else {
1280
      return PREMONOMORPHIC;
1281
    }
1282
  }
1283

    
1284
  virtual Code::Kind GetCodeKind() const { return Code::COMPARE_NIL_IC; }
1285

    
1286
  virtual Handle<Code> GenerateCode(Isolate* isolate);
1287

    
1288
  virtual Code::ExtraICState GetExtraICState() {
1289
    return NilValueField::encode(nil_value_) |
1290
           TypesField::encode(state_.ToIntegral());
1291
  }
1292

    
1293
  void UpdateStatus(Handle<Object> object);
1294

    
1295
  bool IsMonomorphic() const { return state_.Contains(MONOMORPHIC_MAP); }
1296
  NilValue GetNilValue() const { return nil_value_; }
1297
  void ClearState() { state_.RemoveAll(); }
1298

    
1299
  virtual void PrintState(StringStream* stream);
1300
  virtual void PrintBaseName(StringStream* stream);
1301

    
1302
 private:
1303
  friend class CompareNilIC;
1304

    
1305
  enum CompareNilType {
1306
    UNDEFINED,
1307
    NULL_TYPE,
1308
    MONOMORPHIC_MAP,
1309
    GENERIC,
1310
    NUMBER_OF_TYPES
1311
  };
1312

    
1313
  // At most 6 different types can be distinguished, because the Code object
1314
  // only has room for a single byte to hold a set and there are two more
1315
  // boolean flags we need to store. :-P
1316
  STATIC_ASSERT(NUMBER_OF_TYPES <= 6);
1317

    
1318
  class State : public EnumSet<CompareNilType, byte> {
1319
   public:
1320
    State() : EnumSet<CompareNilType, byte>(0) { }
1321
    explicit State(byte bits) : EnumSet<CompareNilType, byte>(bits) { }
1322

    
1323
    void Print(StringStream* stream) const;
1324
  };
1325

    
1326
  CompareNilICStub(NilValue nil, InitializationState init_state)
1327
      : HydrogenCodeStub(init_state), nil_value_(nil) { }
1328

    
1329
  class NilValueField : public BitField<NilValue, 0, 1> {};
1330
  class TypesField    : public BitField<byte,     1, NUMBER_OF_TYPES> {};
1331

    
1332
  virtual CodeStub::Major MajorKey() { return CompareNilIC; }
1333
  virtual int NotMissMinorKey() { return GetExtraICState(); }
1334

    
1335
  NilValue nil_value_;
1336
  State state_;
1337

    
1338
  DISALLOW_COPY_AND_ASSIGN(CompareNilICStub);
1339
};
1340

    
1341

    
1342
class CEntryStub : public PlatformCodeStub {
1343
 public:
1344
  explicit CEntryStub(int result_size,
1345
                      SaveFPRegsMode save_doubles = kDontSaveFPRegs)
1346
      : result_size_(result_size), save_doubles_(save_doubles) { }
1347

    
1348
  void Generate(MacroAssembler* masm);
1349

    
1350
  // The version of this stub that doesn't save doubles is generated ahead of
1351
  // time, so it's OK to call it from other stubs that can't cope with GC during
1352
  // their code generation.  On machines that always have gp registers (x64) we
1353
  // can generate both variants ahead of time.
1354
  virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE;
1355
  static void GenerateAheadOfTime(Isolate* isolate);
1356

    
1357
 protected:
1358
  virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
1359
    ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
1360
  };
1361

    
1362
 private:
1363
  void GenerateCore(MacroAssembler* masm,
1364
                    Label* throw_normal_exception,
1365
                    Label* throw_termination_exception,
1366
                    Label* throw_out_of_memory_exception,
1367
                    bool do_gc,
1368
                    bool always_allocate_scope);
1369

    
1370
  // Number of pointers/values returned.
1371
  Isolate* isolate_;
1372
  const int result_size_;
1373
  SaveFPRegsMode save_doubles_;
1374

    
1375
  Major MajorKey() { return CEntry; }
1376
  int MinorKey();
1377

    
1378
  bool NeedsImmovableCode();
1379
};
1380

    
1381

    
1382
class JSEntryStub : public PlatformCodeStub {
1383
 public:
1384
  JSEntryStub() { }
1385

    
1386
  void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
1387

    
1388
 protected:
1389
  void GenerateBody(MacroAssembler* masm, bool is_construct);
1390

    
1391
 private:
1392
  Major MajorKey() { return JSEntry; }
1393
  int MinorKey() { return 0; }
1394

    
1395
  virtual void FinishCode(Handle<Code> code);
1396

    
1397
  int handler_offset_;
1398
};
1399

    
1400

    
1401
class JSConstructEntryStub : public JSEntryStub {
1402
 public:
1403
  JSConstructEntryStub() { }
1404

    
1405
  void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
1406

    
1407
 private:
1408
  int MinorKey() { return 1; }
1409

    
1410
  virtual void PrintName(StringStream* stream) {
1411
    stream->Add("JSConstructEntryStub");
1412
  }
1413
};
1414

    
1415

    
1416
class ArgumentsAccessStub: public PlatformCodeStub {
1417
 public:
1418
  enum Type {
1419
    READ_ELEMENT,
1420
    NEW_NON_STRICT_FAST,
1421
    NEW_NON_STRICT_SLOW,
1422
    NEW_STRICT
1423
  };
1424

    
1425
  explicit ArgumentsAccessStub(Type type) : type_(type) { }
1426

    
1427
 private:
1428
  Type type_;
1429

    
1430
  Major MajorKey() { return ArgumentsAccess; }
1431
  int MinorKey() { return type_; }
1432

    
1433
  void Generate(MacroAssembler* masm);
1434
  void GenerateReadElement(MacroAssembler* masm);
1435
  void GenerateNewStrict(MacroAssembler* masm);
1436
  void GenerateNewNonStrictFast(MacroAssembler* masm);
1437
  void GenerateNewNonStrictSlow(MacroAssembler* masm);
1438

    
1439
  virtual void PrintName(StringStream* stream);
1440
};
1441

    
1442

    
1443
class RegExpExecStub: public PlatformCodeStub {
1444
 public:
1445
  RegExpExecStub() { }
1446

    
1447
 private:
1448
  Major MajorKey() { return RegExpExec; }
1449
  int MinorKey() { return 0; }
1450

    
1451
  void Generate(MacroAssembler* masm);
1452
};
1453

    
1454

    
1455
class RegExpConstructResultStub: public PlatformCodeStub {
1456
 public:
1457
  RegExpConstructResultStub() { }
1458

    
1459
 private:
1460
  Major MajorKey() { return RegExpConstructResult; }
1461
  int MinorKey() { return 0; }
1462

    
1463
  void Generate(MacroAssembler* masm);
1464
};
1465

    
1466

    
1467
class CallFunctionStub: public PlatformCodeStub {
1468
 public:
1469
  CallFunctionStub(int argc, CallFunctionFlags flags)
1470
      : argc_(argc), flags_(flags) { }
1471

    
1472
  void Generate(MacroAssembler* masm);
1473

    
1474
  virtual void FinishCode(Handle<Code> code) {
1475
    code->set_has_function_cache(RecordCallTarget());
1476
  }
1477

    
1478
  static int ExtractArgcFromMinorKey(int minor_key) {
1479
    return ArgcBits::decode(minor_key);
1480
  }
1481

    
1482
 private:
1483
  int argc_;
1484
  CallFunctionFlags flags_;
1485

    
1486
  virtual void PrintName(StringStream* stream);
1487

    
1488
  // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
1489
  class FlagBits: public BitField<CallFunctionFlags, 0, 2> {};
1490
  class ArgcBits: public BitField<unsigned, 2, 32 - 2> {};
1491

    
1492
  Major MajorKey() { return CallFunction; }
1493
  int MinorKey() {
1494
    // Encode the parameters in a unique 32 bit value.
1495
    return FlagBits::encode(flags_) | ArgcBits::encode(argc_);
1496
  }
1497

    
1498
  bool ReceiverMightBeImplicit() {
1499
    return (flags_ & RECEIVER_MIGHT_BE_IMPLICIT) != 0;
1500
  }
1501

    
1502
  bool RecordCallTarget() {
1503
    return (flags_ & RECORD_CALL_TARGET) != 0;
1504
  }
1505
};
1506

    
1507

    
1508
class CallConstructStub: public PlatformCodeStub {
1509
 public:
1510
  explicit CallConstructStub(CallFunctionFlags flags) : flags_(flags) {}
1511

    
1512
  void Generate(MacroAssembler* masm);
1513

    
1514
  virtual void FinishCode(Handle<Code> code) {
1515
    code->set_has_function_cache(RecordCallTarget());
1516
  }
1517

    
1518
 private:
1519
  CallFunctionFlags flags_;
1520

    
1521
  virtual void PrintName(StringStream* stream);
1522

    
1523
  Major MajorKey() { return CallConstruct; }
1524
  int MinorKey() { return flags_; }
1525

    
1526
  bool RecordCallTarget() {
1527
    return (flags_ & RECORD_CALL_TARGET) != 0;
1528
  }
1529
};
1530

    
1531

    
1532
enum StringIndexFlags {
1533
  // Accepts smis or heap numbers.
1534
  STRING_INDEX_IS_NUMBER,
1535

    
1536
  // Accepts smis or heap numbers that are valid array indices
1537
  // (ECMA-262 15.4). Invalid indices are reported as being out of
1538
  // range.
1539
  STRING_INDEX_IS_ARRAY_INDEX
1540
};
1541

    
1542

    
1543
// Generates code implementing String.prototype.charCodeAt.
1544
//
1545
// Only supports the case when the receiver is a string and the index
1546
// is a number (smi or heap number) that is a valid index into the
1547
// string. Additional index constraints are specified by the
1548
// flags. Otherwise, bails out to the provided labels.
1549
//
1550
// Register usage: |object| may be changed to another string in a way
1551
// that doesn't affect charCodeAt/charAt semantics, |index| is
1552
// preserved, |scratch| and |result| are clobbered.
1553
class StringCharCodeAtGenerator {
1554
 public:
1555
  StringCharCodeAtGenerator(Register object,
1556
                            Register index,
1557
                            Register result,
1558
                            Label* receiver_not_string,
1559
                            Label* index_not_number,
1560
                            Label* index_out_of_range,
1561
                            StringIndexFlags index_flags)
1562
      : object_(object),
1563
        index_(index),
1564
        result_(result),
1565
        receiver_not_string_(receiver_not_string),
1566
        index_not_number_(index_not_number),
1567
        index_out_of_range_(index_out_of_range),
1568
        index_flags_(index_flags) {
1569
    ASSERT(!result_.is(object_));
1570
    ASSERT(!result_.is(index_));
1571
  }
1572

    
1573
  // Generates the fast case code. On the fallthrough path |result|
1574
  // register contains the result.
1575
  void GenerateFast(MacroAssembler* masm);
1576

    
1577
  // Generates the slow case code. Must not be naturally
1578
  // reachable. Expected to be put after a ret instruction (e.g., in
1579
  // deferred code). Always jumps back to the fast case.
1580
  void GenerateSlow(MacroAssembler* masm,
1581
                    const RuntimeCallHelper& call_helper);
1582

    
1583
  // Skip handling slow case and directly jump to bailout.
1584
  void SkipSlow(MacroAssembler* masm, Label* bailout) {
1585
    masm->bind(&index_not_smi_);
1586
    masm->bind(&call_runtime_);
1587
    masm->jmp(bailout);
1588
  }
1589

    
1590
 private:
1591
  Register object_;
1592
  Register index_;
1593
  Register result_;
1594

    
1595
  Label* receiver_not_string_;
1596
  Label* index_not_number_;
1597
  Label* index_out_of_range_;
1598

    
1599
  StringIndexFlags index_flags_;
1600

    
1601
  Label call_runtime_;
1602
  Label index_not_smi_;
1603
  Label got_smi_index_;
1604
  Label exit_;
1605

    
1606
  DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
1607
};
1608

    
1609

    
1610
// Generates code for creating a one-char string from a char code.
1611
class StringCharFromCodeGenerator {
1612
 public:
1613
  StringCharFromCodeGenerator(Register code,
1614
                              Register result)
1615
      : code_(code),
1616
        result_(result) {
1617
    ASSERT(!code_.is(result_));
1618
  }
1619

    
1620
  // Generates the fast case code. On the fallthrough path |result|
1621
  // register contains the result.
1622
  void GenerateFast(MacroAssembler* masm);
1623

    
1624
  // Generates the slow case code. Must not be naturally
1625
  // reachable. Expected to be put after a ret instruction (e.g., in
1626
  // deferred code). Always jumps back to the fast case.
1627
  void GenerateSlow(MacroAssembler* masm,
1628
                    const RuntimeCallHelper& call_helper);
1629

    
1630
  // Skip handling slow case and directly jump to bailout.
1631
  void SkipSlow(MacroAssembler* masm, Label* bailout) {
1632
    masm->bind(&slow_case_);
1633
    masm->jmp(bailout);
1634
  }
1635

    
1636
 private:
1637
  Register code_;
1638
  Register result_;
1639

    
1640
  Label slow_case_;
1641
  Label exit_;
1642

    
1643
  DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
1644
};
1645

    
1646

    
1647
// Generates code implementing String.prototype.charAt.
1648
//
1649
// Only supports the case when the receiver is a string and the index
1650
// is a number (smi or heap number) that is a valid index into the
1651
// string. Additional index constraints are specified by the
1652
// flags. Otherwise, bails out to the provided labels.
1653
//
1654
// Register usage: |object| may be changed to another string in a way
1655
// that doesn't affect charCodeAt/charAt semantics, |index| is
1656
// preserved, |scratch1|, |scratch2|, and |result| are clobbered.
1657
class StringCharAtGenerator {
1658
 public:
1659
  StringCharAtGenerator(Register object,
1660
                        Register index,
1661
                        Register scratch,
1662
                        Register result,
1663
                        Label* receiver_not_string,
1664
                        Label* index_not_number,
1665
                        Label* index_out_of_range,
1666
                        StringIndexFlags index_flags)
1667
      : char_code_at_generator_(object,
1668
                                index,
1669
                                scratch,
1670
                                receiver_not_string,
1671
                                index_not_number,
1672
                                index_out_of_range,
1673
                                index_flags),
1674
        char_from_code_generator_(scratch, result) {}
1675

    
1676
  // Generates the fast case code. On the fallthrough path |result|
1677
  // register contains the result.
1678
  void GenerateFast(MacroAssembler* masm) {
1679
    char_code_at_generator_.GenerateFast(masm);
1680
    char_from_code_generator_.GenerateFast(masm);
1681
  }
1682

    
1683
  // Generates the slow case code. Must not be naturally
1684
  // reachable. Expected to be put after a ret instruction (e.g., in
1685
  // deferred code). Always jumps back to the fast case.
1686
  void GenerateSlow(MacroAssembler* masm,
1687
                    const RuntimeCallHelper& call_helper) {
1688
    char_code_at_generator_.GenerateSlow(masm, call_helper);
1689
    char_from_code_generator_.GenerateSlow(masm, call_helper);
1690
  }
1691

    
1692
  // Skip handling slow case and directly jump to bailout.
1693
  void SkipSlow(MacroAssembler* masm, Label* bailout) {
1694
    char_code_at_generator_.SkipSlow(masm, bailout);
1695
    char_from_code_generator_.SkipSlow(masm, bailout);
1696
  }
1697

    
1698
 private:
1699
  StringCharCodeAtGenerator char_code_at_generator_;
1700
  StringCharFromCodeGenerator char_from_code_generator_;
1701

    
1702
  DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
1703
};
1704

    
1705

    
1706
class AllowStubCallsScope {
1707
 public:
1708
  AllowStubCallsScope(MacroAssembler* masm, bool allow)
1709
       : masm_(masm), previous_allow_(masm->allow_stub_calls()) {
1710
    masm_->set_allow_stub_calls(allow);
1711
  }
1712
  ~AllowStubCallsScope() {
1713
    masm_->set_allow_stub_calls(previous_allow_);
1714
  }
1715

    
1716
 private:
1717
  MacroAssembler* masm_;
1718
  bool previous_allow_;
1719

    
1720
  DISALLOW_COPY_AND_ASSIGN(AllowStubCallsScope);
1721
};
1722

    
1723

    
1724
class KeyedLoadDictionaryElementStub : public PlatformCodeStub {
1725
 public:
1726
  KeyedLoadDictionaryElementStub() {}
1727

    
1728
  void Generate(MacroAssembler* masm);
1729

    
1730
 private:
1731
  Major MajorKey() { return KeyedLoadElement; }
1732
  int MinorKey() { return DICTIONARY_ELEMENTS; }
1733

    
1734
  DISALLOW_COPY_AND_ASSIGN(KeyedLoadDictionaryElementStub);
1735
};
1736

    
1737

    
1738
class DoubleToIStub : public PlatformCodeStub {
1739
 public:
1740
  DoubleToIStub(Register source,
1741
                Register destination,
1742
                int offset,
1743
                bool is_truncating,
1744
                bool skip_fastpath = false) : bit_field_(0) {
1745
    bit_field_ = SourceRegisterBits::encode(source.code_) |
1746
      DestinationRegisterBits::encode(destination.code_) |
1747
      OffsetBits::encode(offset) |
1748
      IsTruncatingBits::encode(is_truncating) |
1749
      SkipFastPathBits::encode(skip_fastpath) |
1750
      SSEBits::encode(CpuFeatures::IsSafeForSnapshot(SSE2) ?
1751
                          CpuFeatures::IsSafeForSnapshot(SSE3) ? 2 : 1 : 0);
1752
  }
1753

    
1754
  Register source() {
1755
    Register result = { SourceRegisterBits::decode(bit_field_) };
1756
    return result;
1757
  }
1758

    
1759
  Register destination() {
1760
    Register result = { DestinationRegisterBits::decode(bit_field_) };
1761
    return result;
1762
  }
1763

    
1764
  bool is_truncating() {
1765
    return IsTruncatingBits::decode(bit_field_);
1766
  }
1767

    
1768
  bool skip_fastpath() {
1769
    return SkipFastPathBits::decode(bit_field_);
1770
  }
1771

    
1772
  int offset() {
1773
    return OffsetBits::decode(bit_field_);
1774
  }
1775

    
1776
  void Generate(MacroAssembler* masm);
1777

    
1778
  virtual bool SometimesSetsUpAFrame() { return false; }
1779

    
1780
 protected:
1781
  virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
1782
    ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
1783
  }
1784

    
1785
 private:
1786
  static const int kBitsPerRegisterNumber = 6;
1787
  STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
1788
  class SourceRegisterBits:
1789
      public BitField<int, 0, kBitsPerRegisterNumber> {};  // NOLINT
1790
  class DestinationRegisterBits:
1791
      public BitField<int, kBitsPerRegisterNumber,
1792
        kBitsPerRegisterNumber> {};  // NOLINT
1793
  class IsTruncatingBits:
1794
      public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {};  // NOLINT
1795
  class OffsetBits:
1796
      public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {};  // NOLINT
1797
  class SkipFastPathBits:
1798
      public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {};  // NOLINT
1799
  class SSEBits:
1800
      public BitField<int, 2 * kBitsPerRegisterNumber + 5, 2> {};  // NOLINT
1801

    
1802
  Major MajorKey() { return DoubleToI; }
1803
  int MinorKey() { return bit_field_; }
1804

    
1805
  int bit_field_;
1806

    
1807
  DISALLOW_COPY_AND_ASSIGN(DoubleToIStub);
1808
};
1809

    
1810

    
1811
class KeyedLoadFastElementStub : public HydrogenCodeStub {
1812
 public:
1813
  KeyedLoadFastElementStub(bool is_js_array, ElementsKind elements_kind) {
1814
    bit_field_ = ElementsKindBits::encode(elements_kind) |
1815
        IsJSArrayBits::encode(is_js_array);
1816
  }
1817

    
1818
  bool is_js_array() const {
1819
    return IsJSArrayBits::decode(bit_field_);
1820
  }
1821

    
1822
  ElementsKind elements_kind() const {
1823
    return ElementsKindBits::decode(bit_field_);
1824
  }
1825

    
1826
  virtual Handle<Code> GenerateCode(Isolate* isolate);
1827

    
1828
  virtual void InitializeInterfaceDescriptor(
1829
      Isolate* isolate,
1830
      CodeStubInterfaceDescriptor* descriptor);
1831

    
1832
 private:
1833
  class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
1834
  class IsJSArrayBits: public BitField<bool, 8, 1> {};
1835
  uint32_t bit_field_;
1836

    
1837
  Major MajorKey() { return KeyedLoadElement; }
1838
  int NotMissMinorKey() { return bit_field_; }
1839

    
1840
  DISALLOW_COPY_AND_ASSIGN(KeyedLoadFastElementStub);
1841
};
1842

    
1843

    
1844
class KeyedStoreFastElementStub : public HydrogenCodeStub {
1845
 public:
1846
  KeyedStoreFastElementStub(bool is_js_array,
1847
                            ElementsKind elements_kind,
1848
                            KeyedAccessStoreMode mode) {
1849
    bit_field_ = ElementsKindBits::encode(elements_kind) |
1850
        IsJSArrayBits::encode(is_js_array) |
1851
        StoreModeBits::encode(mode);
1852
  }
1853

    
1854
  bool is_js_array() const {
1855
    return IsJSArrayBits::decode(bit_field_);
1856
  }
1857

    
1858
  ElementsKind elements_kind() const {
1859
    return ElementsKindBits::decode(bit_field_);
1860
  }
1861

    
1862
  KeyedAccessStoreMode store_mode() const {
1863
    return StoreModeBits::decode(bit_field_);
1864
  }
1865

    
1866
  virtual Handle<Code> GenerateCode(Isolate* isolate);
1867

    
1868
  virtual void InitializeInterfaceDescriptor(
1869
      Isolate* isolate,
1870
      CodeStubInterfaceDescriptor* descriptor);
1871

    
1872
 private:
1873
  class ElementsKindBits: public BitField<ElementsKind,      0, 8> {};
1874
  class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
1875
  class IsJSArrayBits: public BitField<bool,                12, 1> {};
1876
  uint32_t bit_field_;
1877

    
1878
  Major MajorKey() { return KeyedStoreElement; }
1879
  int NotMissMinorKey() { return bit_field_; }
1880

    
1881
  DISALLOW_COPY_AND_ASSIGN(KeyedStoreFastElementStub);
1882
};
1883

    
1884

    
1885
class TransitionElementsKindStub : public HydrogenCodeStub {
1886
 public:
1887
  TransitionElementsKindStub(ElementsKind from_kind,
1888
                             ElementsKind to_kind) {
1889
    bit_field_ = FromKindBits::encode(from_kind) |
1890
        ToKindBits::encode(to_kind);
1891
  }
1892

    
1893
  ElementsKind from_kind() const {
1894
    return FromKindBits::decode(bit_field_);
1895
  }
1896

    
1897
  ElementsKind to_kind() const {
1898
    return ToKindBits::decode(bit_field_);
1899
  }
1900

    
1901
  virtual Handle<Code> GenerateCode(Isolate* isolate);
1902

    
1903
  virtual void InitializeInterfaceDescriptor(
1904
      Isolate* isolate,
1905
      CodeStubInterfaceDescriptor* descriptor);
1906

    
1907
 private:
1908
  class FromKindBits: public BitField<ElementsKind, 8, 8> {};
1909
  class ToKindBits: public BitField<ElementsKind, 0, 8> {};
1910
  uint32_t bit_field_;
1911

    
1912
  Major MajorKey() { return TransitionElementsKind; }
1913
  int NotMissMinorKey() { return bit_field_; }
1914

    
1915
  DISALLOW_COPY_AND_ASSIGN(TransitionElementsKindStub);
1916
};
1917

    
1918

    
1919
enum ContextCheckMode {
1920
  CONTEXT_CHECK_REQUIRED,
1921
  CONTEXT_CHECK_NOT_REQUIRED,
1922
  LAST_CONTEXT_CHECK_MODE = CONTEXT_CHECK_NOT_REQUIRED
1923
};
1924

    
1925

    
1926
class ArrayConstructorStubBase : public HydrogenCodeStub {
1927
 public:
1928
  ArrayConstructorStubBase(ElementsKind kind, ContextCheckMode context_mode,
1929
                           AllocationSiteOverrideMode override_mode) {
1930
    // It only makes sense to override local allocation site behavior
1931
    // if there is a difference between the global allocation site policy
1932
    // for an ElementsKind and the desired usage of the stub.
1933
    ASSERT(!(FLAG_track_allocation_sites &&
1934
             override_mode == DISABLE_ALLOCATION_SITES) ||
1935
           AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE);
1936
    bit_field_ = ElementsKindBits::encode(kind) |
1937
        AllocationSiteOverrideModeBits::encode(override_mode) |
1938
        ContextCheckModeBits::encode(context_mode);
1939
  }
1940

    
1941
  ElementsKind elements_kind() const {
1942
    return ElementsKindBits::decode(bit_field_);
1943
  }
1944

    
1945
  AllocationSiteOverrideMode override_mode() const {
1946
    return AllocationSiteOverrideModeBits::decode(bit_field_);
1947
  }
1948

    
1949
  ContextCheckMode context_mode() const {
1950
    return ContextCheckModeBits::decode(bit_field_);
1951
  }
1952

    
1953
  virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE {
1954
    // We only pre-generate stubs that verify correct context
1955
    return context_mode() == CONTEXT_CHECK_REQUIRED;
1956
  }
1957

    
1958
  static void GenerateStubsAheadOfTime(Isolate* isolate);
1959
  static void InstallDescriptors(Isolate* isolate);
1960

    
1961
  // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1962
  static const int kConstructor = 0;
1963
  static const int kPropertyCell = 1;
1964

    
1965
 private:
1966
  int NotMissMinorKey() { return bit_field_; }
1967

    
1968
  // Ensure data fits within available bits.
1969
  STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
1970
  STATIC_ASSERT(LAST_CONTEXT_CHECK_MODE == 1);
1971

    
1972
  class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
1973
  class AllocationSiteOverrideModeBits: public
1974
      BitField<AllocationSiteOverrideMode, 8, 1> {};  // NOLINT
1975
  class ContextCheckModeBits: public BitField<ContextCheckMode, 9, 1> {};
1976
  uint32_t bit_field_;
1977

    
1978
  DISALLOW_COPY_AND_ASSIGN(ArrayConstructorStubBase);
1979
};
1980

    
1981

    
1982
class ArrayNoArgumentConstructorStub : public ArrayConstructorStubBase {
1983
 public:
1984
  ArrayNoArgumentConstructorStub(
1985
      ElementsKind kind,
1986
      ContextCheckMode context_mode = CONTEXT_CHECK_REQUIRED,
1987
      AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
1988
      : ArrayConstructorStubBase(kind, context_mode, override_mode) {
1989
  }
1990

    
1991
  virtual Handle<Code> GenerateCode(Isolate* isolate);
1992

    
1993
  virtual void InitializeInterfaceDescriptor(
1994
      Isolate* isolate,
1995
      CodeStubInterfaceDescriptor* descriptor);
1996

    
1997
 private:
1998
  Major MajorKey() { return ArrayNoArgumentConstructor; }
1999

    
2000
  DISALLOW_COPY_AND_ASSIGN(ArrayNoArgumentConstructorStub);
2001
};
2002

    
2003

    
2004
class ArraySingleArgumentConstructorStub : public ArrayConstructorStubBase {
2005
 public:
2006
  ArraySingleArgumentConstructorStub(
2007
      ElementsKind kind,
2008
      ContextCheckMode context_mode = CONTEXT_CHECK_REQUIRED,
2009
      AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2010
      : ArrayConstructorStubBase(kind, context_mode, override_mode) {
2011
  }
2012

    
2013
  virtual Handle<Code> GenerateCode(Isolate* isolate);
2014

    
2015
  virtual void InitializeInterfaceDescriptor(
2016
      Isolate* isolate,
2017
      CodeStubInterfaceDescriptor* descriptor);
2018

    
2019
 private:
2020
  Major MajorKey() { return ArraySingleArgumentConstructor; }
2021

    
2022
  DISALLOW_COPY_AND_ASSIGN(ArraySingleArgumentConstructorStub);
2023
};
2024

    
2025

    
2026
class ArrayNArgumentsConstructorStub : public ArrayConstructorStubBase {
2027
 public:
2028
  ArrayNArgumentsConstructorStub(
2029
      ElementsKind kind,
2030
      ContextCheckMode context_mode = CONTEXT_CHECK_REQUIRED,
2031
      AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2032
      : ArrayConstructorStubBase(kind, context_mode, override_mode) {
2033
  }
2034

    
2035
  virtual Handle<Code> GenerateCode(Isolate* isolate);
2036

    
2037
  virtual void InitializeInterfaceDescriptor(
2038
      Isolate* isolate,
2039
      CodeStubInterfaceDescriptor* descriptor);
2040

    
2041
 private:
2042
  Major MajorKey() { return ArrayNArgumentsConstructor; }
2043

    
2044
  DISALLOW_COPY_AND_ASSIGN(ArrayNArgumentsConstructorStub);
2045
};
2046

    
2047

    
2048
class InternalArrayConstructorStubBase : public HydrogenCodeStub {
2049
 public:
2050
  explicit InternalArrayConstructorStubBase(ElementsKind kind) {
2051
    kind_ = kind;
2052
  }
2053

    
2054
  virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE { return true; }
2055
  static void GenerateStubsAheadOfTime(Isolate* isolate);
2056
  static void InstallDescriptors(Isolate* isolate);
2057

    
2058
  // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2059
  static const int kConstructor = 0;
2060

    
2061
  ElementsKind elements_kind() const { return kind_; }
2062

    
2063
 private:
2064
  int NotMissMinorKey() { return kind_; }
2065

    
2066
  ElementsKind kind_;
2067

    
2068
  DISALLOW_COPY_AND_ASSIGN(InternalArrayConstructorStubBase);
2069
};
2070

    
2071

    
2072
class InternalArrayNoArgumentConstructorStub : public
2073
    InternalArrayConstructorStubBase {
2074
 public:
2075
  explicit InternalArrayNoArgumentConstructorStub(ElementsKind kind)
2076
      : InternalArrayConstructorStubBase(kind) { }
2077

    
2078
  virtual Handle<Code> GenerateCode(Isolate* isolate);
2079

    
2080
  virtual void InitializeInterfaceDescriptor(
2081
      Isolate* isolate,
2082
      CodeStubInterfaceDescriptor* descriptor);
2083

    
2084
 private:
2085
  Major MajorKey() { return InternalArrayNoArgumentConstructor; }
2086

    
2087
  DISALLOW_COPY_AND_ASSIGN(InternalArrayNoArgumentConstructorStub);
2088
};
2089

    
2090

    
2091
class InternalArraySingleArgumentConstructorStub : public
2092
    InternalArrayConstructorStubBase {
2093
 public:
2094
  explicit InternalArraySingleArgumentConstructorStub(ElementsKind kind)
2095
      : InternalArrayConstructorStubBase(kind) { }
2096

    
2097
  virtual Handle<Code> GenerateCode(Isolate* isolate);
2098

    
2099
  virtual void InitializeInterfaceDescriptor(
2100
      Isolate* isolate,
2101
      CodeStubInterfaceDescriptor* descriptor);
2102

    
2103
 private:
2104
  Major MajorKey() { return InternalArraySingleArgumentConstructor; }
2105

    
2106
  DISALLOW_COPY_AND_ASSIGN(InternalArraySingleArgumentConstructorStub);
2107
};
2108

    
2109

    
2110
class InternalArrayNArgumentsConstructorStub : public
2111
    InternalArrayConstructorStubBase {
2112
 public:
2113
  explicit InternalArrayNArgumentsConstructorStub(ElementsKind kind)
2114
      : InternalArrayConstructorStubBase(kind) { }
2115

    
2116
  virtual Handle<Code> GenerateCode(Isolate* isolate);
2117

    
2118
  virtual void InitializeInterfaceDescriptor(
2119
      Isolate* isolate,
2120
      CodeStubInterfaceDescriptor* descriptor);
2121

    
2122
 private:
2123
  Major MajorKey() { return InternalArrayNArgumentsConstructor; }
2124

    
2125
  DISALLOW_COPY_AND_ASSIGN(InternalArrayNArgumentsConstructorStub);
2126
};
2127

    
2128

    
2129
class KeyedStoreElementStub : public PlatformCodeStub {
2130
 public:
2131
  KeyedStoreElementStub(bool is_js_array,
2132
                        ElementsKind elements_kind,
2133
                        KeyedAccessStoreMode store_mode)
2134
      : is_js_array_(is_js_array),
2135
        elements_kind_(elements_kind),
2136
        store_mode_(store_mode),
2137
        fp_registers_(CanUseFPRegisters()) { }
2138

    
2139
  Major MajorKey() { return KeyedStoreElement; }
2140
  int MinorKey() {
2141
    return ElementsKindBits::encode(elements_kind_) |
2142
        IsJSArrayBits::encode(is_js_array_) |
2143
        StoreModeBits::encode(store_mode_) |
2144
        FPRegisters::encode(fp_registers_);
2145
  }
2146

    
2147
  void Generate(MacroAssembler* masm);
2148

    
2149
 private:
2150
  class ElementsKindBits: public BitField<ElementsKind,      0, 8> {};
2151
  class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
2152
  class IsJSArrayBits: public BitField<bool,                12, 1> {};
2153
  class FPRegisters: public BitField<bool,                  13, 1> {};
2154

    
2155
  bool is_js_array_;
2156
  ElementsKind elements_kind_;
2157
  KeyedAccessStoreMode store_mode_;
2158
  bool fp_registers_;
2159

    
2160
  DISALLOW_COPY_AND_ASSIGN(KeyedStoreElementStub);
2161
};
2162

    
2163

    
2164
class ToBooleanStub: public HydrogenCodeStub {
2165
 public:
2166
  enum Type {
2167
    UNDEFINED,
2168
    BOOLEAN,
2169
    NULL_TYPE,
2170
    SMI,
2171
    SPEC_OBJECT,
2172
    STRING,
2173
    SYMBOL,
2174
    HEAP_NUMBER,
2175
    NUMBER_OF_TYPES
2176
  };
2177

    
2178
  // At most 8 different types can be distinguished, because the Code object
2179
  // only has room for a single byte to hold a set of these types. :-P
2180
  STATIC_ASSERT(NUMBER_OF_TYPES <= 8);
2181

    
2182
  class Types : public EnumSet<Type, byte> {
2183
   public:
2184
    Types() : EnumSet<Type, byte>(0) {}
2185
    explicit Types(byte bits) : EnumSet<Type, byte>(bits) {}
2186

    
2187
    byte ToByte() const { return ToIntegral(); }
2188
    void Print(StringStream* stream) const;
2189
    bool UpdateStatus(Handle<Object> object);
2190
    bool NeedsMap() const;
2191
    bool CanBeUndetectable() const;
2192
    bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); }
2193

    
2194
    static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); }
2195
  };
2196

    
2197
  explicit ToBooleanStub(Types types = Types())
2198
      : types_(types) { }
2199
  explicit ToBooleanStub(Code::ExtraICState state)
2200
      : types_(static_cast<byte>(state)) { }
2201

    
2202
  bool UpdateStatus(Handle<Object> object);
2203
  Types GetTypes() { return types_; }
2204

    
2205
  virtual Handle<Code> GenerateCode(Isolate* isolate);
2206
  virtual void InitializeInterfaceDescriptor(
2207
      Isolate* isolate,
2208
      CodeStubInterfaceDescriptor* descriptor);
2209

    
2210
  virtual Code::Kind GetCodeKind() const { return Code::TO_BOOLEAN_IC; }
2211
  virtual void PrintState(StringStream* stream);
2212

    
2213
  virtual bool SometimesSetsUpAFrame() { return false; }
2214

    
2215
  static void InitializeForIsolate(Isolate* isolate) {
2216
    ToBooleanStub stub;
2217
    stub.InitializeInterfaceDescriptor(
2218
        isolate,
2219
        isolate->code_stub_interface_descriptor(CodeStub::ToBoolean));
2220
  }
2221

    
2222
  static Handle<Code> GetUninitialized(Isolate* isolate) {
2223
    return ToBooleanStub(UNINITIALIZED).GetCode(isolate);
2224
  }
2225

    
2226
  virtual Code::ExtraICState GetExtraICState() {
2227
    return types_.ToIntegral();
2228
  }
2229

    
2230
  virtual InlineCacheState GetICState() {
2231
    if (types_.IsEmpty()) {
2232
      return ::v8::internal::UNINITIALIZED;
2233
    } else {
2234
      return MONOMORPHIC;
2235
    }
2236
  }
2237

    
2238
 private:
2239
  Major MajorKey() { return ToBoolean; }
2240
  int NotMissMinorKey() { return GetExtraICState(); }
2241

    
2242
  explicit ToBooleanStub(InitializationState init_state) :
2243
    HydrogenCodeStub(init_state) {}
2244

    
2245
  Types types_;
2246
};
2247

    
2248

    
2249
class ElementsTransitionAndStoreStub : public HydrogenCodeStub {
2250
 public:
2251
  ElementsTransitionAndStoreStub(ElementsKind from_kind,
2252
                                 ElementsKind to_kind,
2253
                                 bool is_jsarray,
2254
                                 KeyedAccessStoreMode store_mode)
2255
      : from_kind_(from_kind),
2256
        to_kind_(to_kind),
2257
        is_jsarray_(is_jsarray),
2258
        store_mode_(store_mode) {}
2259

    
2260
  ElementsKind from_kind() const { return from_kind_; }
2261
  ElementsKind to_kind() const { return to_kind_; }
2262
  bool is_jsarray() const { return is_jsarray_; }
2263
  KeyedAccessStoreMode store_mode() const { return store_mode_; }
2264

    
2265
  virtual Handle<Code> GenerateCode(Isolate* isolate);
2266

    
2267
  void InitializeInterfaceDescriptor(
2268
      Isolate* isolate,
2269
      CodeStubInterfaceDescriptor* descriptor);
2270

    
2271
 private:
2272
  class FromBits:      public BitField<ElementsKind,          0, 8> {};
2273
  class ToBits:        public BitField<ElementsKind,          8, 8> {};
2274
  class IsJSArrayBits: public BitField<bool,                 16, 1> {};
2275
  class StoreModeBits: public BitField<KeyedAccessStoreMode, 17, 4> {};
2276

    
2277
  Major MajorKey() { return ElementsTransitionAndStore; }
2278
  int NotMissMinorKey() {
2279
    return FromBits::encode(from_kind_) |
2280
        ToBits::encode(to_kind_) |
2281
        IsJSArrayBits::encode(is_jsarray_) |
2282
        StoreModeBits::encode(store_mode_);
2283
  }
2284

    
2285
  ElementsKind from_kind_;
2286
  ElementsKind to_kind_;
2287
  bool is_jsarray_;
2288
  KeyedAccessStoreMode store_mode_;
2289

    
2290
  DISALLOW_COPY_AND_ASSIGN(ElementsTransitionAndStoreStub);
2291
};
2292

    
2293

    
2294
class StoreArrayLiteralElementStub : public PlatformCodeStub {
2295
 public:
2296
  StoreArrayLiteralElementStub()
2297
        : fp_registers_(CanUseFPRegisters()) { }
2298

    
2299
 private:
2300
  class FPRegisters: public BitField<bool,                0, 1> {};
2301

    
2302
  Major MajorKey() { return StoreArrayLiteralElement; }
2303
  int MinorKey() { return FPRegisters::encode(fp_registers_); }
2304

    
2305
  void Generate(MacroAssembler* masm);
2306

    
2307
  bool fp_registers_;
2308

    
2309
  DISALLOW_COPY_AND_ASSIGN(StoreArrayLiteralElementStub);
2310
};
2311

    
2312

    
2313
class StubFailureTrampolineStub : public PlatformCodeStub {
2314
 public:
2315
  explicit StubFailureTrampolineStub(StubFunctionMode function_mode)
2316
      : fp_registers_(CanUseFPRegisters()), function_mode_(function_mode) {}
2317

    
2318
  virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE { return true; }
2319

    
2320
  static void GenerateAheadOfTime(Isolate* isolate);
2321

    
2322
 private:
2323
  class FPRegisters:       public BitField<bool,                0, 1> {};
2324
  class FunctionModeField: public BitField<StubFunctionMode,    1, 1> {};
2325

    
2326
  Major MajorKey() { return StubFailureTrampoline; }
2327
  int MinorKey() {
2328
    return FPRegisters::encode(fp_registers_) |
2329
        FunctionModeField::encode(function_mode_);
2330
  }
2331

    
2332
  void Generate(MacroAssembler* masm);
2333

    
2334
  bool fp_registers_;
2335
  StubFunctionMode function_mode_;
2336

    
2337
  DISALLOW_COPY_AND_ASSIGN(StubFailureTrampolineStub);
2338
};
2339

    
2340

    
2341
class ProfileEntryHookStub : public PlatformCodeStub {
2342
 public:
2343
  explicit ProfileEntryHookStub() {}
2344

    
2345
  // The profile entry hook function is not allowed to cause a GC.
2346
  virtual bool SometimesSetsUpAFrame() { return false; }
2347

    
2348
  // Generates a call to the entry hook if it's enabled.
2349
  static void MaybeCallEntryHook(MacroAssembler* masm);
2350

    
2351
 private:
2352
  static void EntryHookTrampoline(intptr_t function,
2353
                                  intptr_t stack_pointer,
2354
                                  Isolate* isolate);
2355

    
2356
  Major MajorKey() { return ProfileEntryHook; }
2357
  int MinorKey() { return 0; }
2358

    
2359
  void Generate(MacroAssembler* masm);
2360

    
2361
  DISALLOW_COPY_AND_ASSIGN(ProfileEntryHookStub);
2362
};
2363

    
2364
} }  // namespace v8::internal
2365

    
2366
#endif  // V8_CODE_STUBS_H_