code-stubs.h 95.7 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4 5 6 7

#ifndef V8_CODE_STUBS_H_
#define V8_CODE_STUBS_H_

8 9 10
#include "src/allocation.h"
#include "src/assembler.h"
#include "src/codegen.h"
11
#include "src/compiler/code-stub-assembler.h"
12
#include "src/globals.h"
13
#include "src/ic/ic-state.h"
14
#include "src/interface-descriptors.h"
15
#include "src/macro-assembler.h"
16
#include "src/ostreams.h"
17

18 19
namespace v8 {
namespace internal {
20

21
// List of code stubs used on all platforms.
22
#define CODE_STUB_LIST_ALL_PLATFORMS(V)     \
23 24
  /* PlatformCodeStubs */                   \
  V(ArrayConstructor)                       \
25
  V(BinaryOpICWithAllocationSite)           \
26
  V(CallApiFunction)                        \
27
  V(CallApiAccessor)                        \
28
  V(CallApiGetter)                          \
29
  V(CallConstruct)                          \
30
  V(CallIC)                                 \
31 32 33
  V(CEntry)                                 \
  V(CompareIC)                              \
  V(DoubleToI)                              \
34
  V(FunctionPrototype)                      \
35
  V(InstanceOf)                             \
36
  V(InternalArrayConstructor)               \
37
  V(JSEntry)                                \
38 39
  V(KeyedLoadICTrampoline)                  \
  V(LoadICTrampoline)                       \
40
  V(CallICTrampoline)                       \
41
  V(LoadIndexedInterceptor)                 \
42
  V(LoadIndexedString)                      \
43 44 45 46 47 48 49 50
  V(MathPow)                                \
  V(ProfileEntryHook)                       \
  V(RecordWrite)                            \
  V(RegExpExec)                             \
  V(StoreBufferOverflow)                    \
  V(StoreElement)                           \
  V(StubFailureTrampoline)                  \
  V(SubString)                              \
51
  V(ToNumber)                               \
52
  V(ToLength)                               \
53
  V(ToString)                               \
54
  V(ToName)                                 \
55
  V(ToObject)                               \
56 57 58 59
  V(VectorStoreICTrampoline)                \
  V(VectorKeyedStoreICTrampoline)           \
  V(VectorStoreIC)                          \
  V(VectorKeyedStoreIC)                     \
60
  /* HydrogenCodeStubs */                   \
61
  V(AllocateInNewSpace)                     \
62
  V(ArrayNArgumentsConstructor)             \
63 64
  V(ArrayNoArgumentConstructor)             \
  V(ArraySingleArgumentConstructor)         \
65 66 67
  V(BinaryOpIC)                             \
  V(BinaryOpWithAllocationSite)             \
  V(CreateAllocationSite)                   \
68
  V(CreateWeakCell)                         \
69
  V(ElementsTransitionAndStore)             \
70
  V(FastCloneRegExp)                        \
71 72 73 74
  V(FastCloneShallowArray)                  \
  V(FastCloneShallowObject)                 \
  V(FastNewClosure)                         \
  V(FastNewContext)                         \
75
  V(FastNewObject)                          \
76
  V(FastNewRestParameter)                   \
77 78
  V(FastNewSloppyArguments)                 \
  V(FastNewStrictArguments)                 \
79
  V(GrowArrayElements)                      \
80
  V(InternalArrayNArgumentsConstructor)     \
81 82
  V(InternalArrayNoArgumentConstructor)     \
  V(InternalArraySingleArgumentConstructor) \
83
  V(KeyedLoadGeneric)                       \
84
  V(LoadGlobalViaContext)                   \
85
  V(LoadScriptContextField)                 \
86
  V(LoadDictionaryElement)                  \
87
  V(NameDictionaryLookup)                   \
88
  V(NumberToString)                         \
89
  V(Typeof)                                 \
90 91
  V(RegExpConstructResult)                  \
  V(StoreFastElement)                       \
92
  V(StoreGlobalViaContext)                  \
93
  V(StoreScriptContextField)                \
94
  V(StringAdd)                              \
95
  V(ToBooleanIC)                            \
96
  V(TransitionElementsKind)                 \
97 98
  V(KeyedLoadIC)                            \
  V(LoadIC)                                 \
99
  /* TurboFanCodeStubs */                   \
100 101
  V(AllocateHeapNumber)                     \
  V(AllocateMutableHeapNumber)              \
102
  V(StringLength)                           \
103 104 105 106
  V(LessThan)                               \
  V(LessThanOrEqual)                        \
  V(GreaterThan)                            \
  V(GreaterThanOrEqual)                     \
107
  V(StrictEqual)                            \
108
  V(StrictNotEqual)                         \
109 110
  V(StringEqual)                            \
  V(StringNotEqual)                         \
111 112 113 114
  V(StringLessThan)                         \
  V(StringLessThanOrEqual)                  \
  V(StringGreaterThan)                      \
  V(StringGreaterThanOrEqual)               \
115
  V(ToBoolean)                              \
116
  /* IC Handler stubs */                    \
117
  V(ArrayBufferViewLoadField)               \
118
  V(LoadConstant)                           \
119
  V(LoadFastElement)                        \
120
  V(LoadField)                              \
121
  V(KeyedLoadSloppyArguments)               \
122
  V(KeyedStoreSloppyArguments)              \
123
  V(StoreField)                             \
124
  V(StoreGlobal)                            \
125
  V(StoreTransition)
126

127 128
// List of code stubs only used on ARM 32 bits platforms.
#if V8_TARGET_ARCH_ARM
129
#define CODE_STUB_LIST_ARM(V) V(DirectCEntry)
130

131 132 133 134
#else
#define CODE_STUB_LIST_ARM(V)
#endif

135 136
// List of code stubs only used on ARM 64 bits platforms.
#if V8_TARGET_ARCH_ARM64
137 138 139 140 141
#define CODE_STUB_LIST_ARM64(V) \
  V(DirectCEntry)               \
  V(RestoreRegistersState)      \
  V(StoreRegistersState)

142 143 144 145
#else
#define CODE_STUB_LIST_ARM64(V)
#endif

146 147 148 149 150 151 152 153 154 155
// List of code stubs only used on PPC platforms.
#ifdef V8_TARGET_ARCH_PPC
#define CODE_STUB_LIST_PPC(V) \
  V(DirectCEntry)             \
  V(StoreRegistersState)      \
  V(RestoreRegistersState)
#else
#define CODE_STUB_LIST_PPC(V)
#endif

156
// List of code stubs only used on MIPS platforms.
157
#if V8_TARGET_ARCH_MIPS
158 159 160 161
#define CODE_STUB_LIST_MIPS(V) \
  V(DirectCEntry)              \
  V(RestoreRegistersState)     \
  V(StoreRegistersState)
162
#elif V8_TARGET_ARCH_MIPS64
163 164 165 166
#define CODE_STUB_LIST_MIPS(V) \
  V(DirectCEntry)              \
  V(RestoreRegistersState)     \
  V(StoreRegistersState)
167 168 169 170
#else
#define CODE_STUB_LIST_MIPS(V)
#endif

171
// Combined list of code stubs.
172 173 174 175 176
#define CODE_STUB_LIST(V)         \
  CODE_STUB_LIST_ALL_PLATFORMS(V) \
  CODE_STUB_LIST_ARM(V)           \
  CODE_STUB_LIST_ARM64(V)         \
  CODE_STUB_LIST_PPC(V)           \
177
  CODE_STUB_LIST_MIPS(V)
178

179 180
static const int kHasReturnedMinusZeroSentinel = 1;

181 182 183 184
// Stub is base classes of all stubs.
class CodeStub BASE_EMBEDDED {
 public:
  enum Major {
185 186 187
    // TODO(mvstanton): eliminate the NoCache key by getting rid
    //                  of the non-monomorphic-cache.
    NoCache = 0,  // marker for stubs that do custom caching]
188 189 190
#define DEF_ENUM(name) name,
    CODE_STUB_LIST(DEF_ENUM)
#undef DEF_ENUM
191 192 193 194
    NUMBER_OF_IDS
  };

  // Retrieve the code for the stub. Generate the code if needed.
195
  Handle<Code> GetCode();
196

197
  // Retrieve the code for the stub, make and return a copy of the code.
198
  Handle<Code> GetCodeCopy(const Code::FindAndReplacePattern& pattern);
199

200 201
  static Major MajorKeyFromKey(uint32_t key) {
    return static_cast<Major>(MajorKeyBits::decode(key));
202
  }
203
  static uint32_t MinorKeyFromKey(uint32_t key) {
204
    return MinorKeyBits::decode(key);
205
  }
206 207 208

  // Gets the major key from a code object that is a code stub or binary op IC.
  static Major GetMajorKey(Code* code_stub) {
209
    return MajorKeyFromKey(code_stub->stub_key());
210 211
  }

212 213
  static uint32_t NoCacheKey() { return MajorKeyBits::encode(NoCache); }

214
  static const char* MajorName(Major major_key);
215

216
  explicit CodeStub(Isolate* isolate) : minor_key_(0), isolate_(isolate) {}
217 218
  virtual ~CodeStub() {}

219 220
  static void GenerateStubsAheadOfTime(Isolate* isolate);
  static void GenerateFPStubs(Isolate* isolate);
221

222 223 224 225 226 227 228 229
  // Some stubs put untagged junk on the stack that cannot be scanned by the
  // GC.  This means that we must be statically sure that no GC can occur while
  // they are running.  If that is the case they should override this to return
  // true, which will cause an assertion if we try to call something that can
  // GC or if we try to put a stack frame on top of the junk, which would not
  // result in a traversable stack.
  virtual bool SometimesSetsUpAFrame() { return true; }

230
  // Lookup the code in the (possibly custom) cache.
231
  bool FindCodeInCache(Code** code_out);
232

233
  virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() const = 0;
234

235 236 237
  virtual int GetStackParameterCount() const {
    return GetCallInterfaceDescriptor().GetStackParameterCount();
  }
238

239
  virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) {}
240

241 242
  static void InitializeDescriptor(Isolate* isolate, uint32_t key,
                                   CodeStubDescriptor* desc);
243

244 245
  static MaybeHandle<Code> GetCode(Isolate* isolate, uint32_t key);

246
  // Returns information for computing the number key.
247
  virtual Major MajorKey() const = 0;
248
  uint32_t MinorKey() const { return minor_key_; }
249

250 251 252
  // BinaryOpStub needs to override this.
  virtual Code::Kind GetCodeKind() const;

253
  virtual InlineCacheState GetICState() const { return UNINITIALIZED; }
254
  virtual ExtraICState GetExtraICState() const { return kNoExtraICState; }
255
  virtual Code::StubType GetStubType() const { return Code::NORMAL; }
256

257 258
  Code::Flags GetCodeFlags() const;

259
  friend std::ostream& operator<<(std::ostream& os, const CodeStub& s) {
260 261 262
    s.PrintName(os);
    return os;
  }
263

264 265
  Isolate* isolate() const { return isolate_; }

266
 protected:
267 268
  CodeStub(uint32_t key, Isolate* isolate)
      : minor_key_(MinorKeyFromKey(key)), isolate_(isolate) {}
269

270
  // Generates the assembler code for the stub.
271
  virtual Handle<Code> GenerateCode() = 0;
272

273 274 275 276
  // Returns whether the code generated for this stub needs to be allocated as
  // a fixed (non-moveable) code object.
  virtual bool NeedsImmovableCode() { return false; }

277 278 279
  virtual void PrintName(std::ostream& os) const;        // NOLINT
  virtual void PrintBaseName(std::ostream& os) const;    // NOLINT
  virtual void PrintState(std::ostream& os) const { ; }  // NOLINT
280

281 282
  // Computes the key based on major and minor.
  uint32_t GetKey() {
283
    DCHECK(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
284 285 286
    return MinorKeyBits::encode(MinorKey()) | MajorKeyBits::encode(MajorKey());
  }

287 288
  uint32_t minor_key_;

289
 private:
290 291
  // Perform bookkeeping required after code generation when stub code is
  // initially generated.
292
  void RecordCodeGeneration(Handle<Code> code);
293

294
  // Finish the code object after it has been generated.
295
  virtual void FinishCode(Handle<Code> code) { }
296

297 298 299 300
  // Activate newly generated stub. Is called after
  // registering stub in the stub cache.
  virtual void Activate(Code* code) { }

301 302 303 304 305 306
  // Add the code to a specialized cache, specific to an individual
  // stub type. Please note, this method must add the code object to a
  // roots object, otherwise we will remove the code during GC.
  virtual void AddToSpecialCache(Handle<Code> new_object) { }

  // Find code in a specialized cache, work is delegated to the specific stub.
307
  virtual bool FindCodeInSpecialCache(Code** code_out) {
308 309
    return false;
  }
310 311 312 313

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

314 315 316 317 318 319
  // We use this dispatch to statically instantiate the correct code stub for
  // the given stub key and call the passed function with that code stub.
  typedef void (*DispatchedCall)(CodeStub* stub, void** value_out);
  static void Dispatch(Isolate* isolate, uint32_t key, void** value_out,
                       DispatchedCall call);

320 321
  static void GetCodeDispatchCall(CodeStub* stub, void** value_out);

322
  STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits));
323 324 325
  class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
  class MinorKeyBits: public BitField<uint32_t,
      kStubMajorKeyBits, kStubMinorKeyBits> {};  // NOLINT
326 327

  friend class BreakPointIterator;
328 329

  Isolate* isolate_;
330 331
};

332

333 334 335 336 337 338 339 340
#define DEFINE_CODE_STUB_BASE(NAME, SUPER)                      \
 public:                                                        \
  NAME(uint32_t key, Isolate* isolate) : SUPER(key, isolate) {} \
                                                                \
 private:                                                       \
  DISALLOW_COPY_AND_ASSIGN(NAME)


341
#define DEFINE_CODE_STUB(NAME, SUPER)                      \
342
 public:                                                   \
343
  inline Major MajorKey() const override { return NAME; }; \
344 345
                                                           \
 protected:                                                \
346 347 348
  DEFINE_CODE_STUB_BASE(NAME##Stub, SUPER)


349 350
#define DEFINE_PLATFORM_CODE_STUB(NAME, SUPER)  \
 private:                                       \
351
  void Generate(MacroAssembler* masm) override; \
352 353 354
  DEFINE_CODE_STUB(NAME, SUPER)


355 356
#define DEFINE_HYDROGEN_CODE_STUB(NAME, SUPER)                        \
 public:                                                              \
357 358
  void InitializeDescriptor(CodeStubDescriptor* descriptor) override; \
  Handle<Code> GenerateCode() override;                               \
359 360
  DEFINE_CODE_STUB(NAME, SUPER)

361 362 363 364
#define DEFINE_TURBOFAN_CODE_STUB(NAME, SUPER)                  \
 public:                                                        \
  void GenerateAssembly(compiler::CodeStubAssembler* assembler) \
      const override;                                           \
365 366
  DEFINE_CODE_STUB(NAME, SUPER)

367 368
#define DEFINE_HANDLER_CODE_STUB(NAME, SUPER) \
 public:                                      \
369
  Handle<Code> GenerateCode() override;       \
370 371
  DEFINE_CODE_STUB(NAME, SUPER)

372 373 374 375
#define DEFINE_CALL_INTERFACE_DESCRIPTOR(NAME)                          \
 public:                                                                \
  CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
    return NAME##Descriptor(isolate());                                 \
376 377
  }

378 379 380
// There are some code stubs we just can't describe right now with a
// CallInterfaceDescriptor. Isolate behavior for those cases with this macro.
// An attempt to retrieve a descriptor will fail.
381 382 383 384 385
#define DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR()                         \
 public:                                                                \
  CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
    UNREACHABLE();                                                      \
    return CallInterfaceDescriptor();                                   \
386 387
  }

388

389 390 391
class PlatformCodeStub : public CodeStub {
 public:
  // Retrieve the code for the stub. Generate the code if needed.
392
  Handle<Code> GenerateCode() override;
393 394

 protected:
395 396
  explicit PlatformCodeStub(Isolate* isolate) : CodeStub(isolate) {}

397 398
  // Generates the assembler code for the stub.
  virtual void Generate(MacroAssembler* masm) = 0;
399

400
  DEFINE_CODE_STUB_BASE(PlatformCodeStub, CodeStub);
401 402 403
};


404
enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
405

406

407
class CodeStubDescriptor {
408
 public:
409
  explicit CodeStubDescriptor(CodeStub* stub);
410

411
  CodeStubDescriptor(Isolate* isolate, uint32_t stub_key);
412

413
  void Initialize(Address deoptimization_handler = NULL,
414 415
                  int hint_stack_parameter_count = -1,
                  StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
416
  void Initialize(Register stack_parameter_count,
417 418
                  Address deoptimization_handler = NULL,
                  int hint_stack_parameter_count = -1,
419
                  StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
420

421 422 423
  void SetMissHandler(ExternalReference handler) {
    miss_handler_ = handler;
    has_miss_handler_ = true;
424 425
    // Our miss handler infrastructure doesn't currently support
    // variable stack parameter counts.
426
    DCHECK(!stack_parameter_count_.is_valid());
427 428
  }

429
  void set_call_descriptor(CallInterfaceDescriptor d) { call_descriptor_ = d; }
430
  CallInterfaceDescriptor call_descriptor() const { return call_descriptor_; }
431

432 433
  int GetRegisterParameterCount() const {
    return call_descriptor().GetRegisterParameterCount();
434 435
  }

436 437 438 439 440 441 442 443
  int GetStackParameterCount() const {
    return call_descriptor().GetStackParameterCount();
  }

  int GetParameterCount() const {
    return call_descriptor().GetParameterCount();
  }

444 445 446 447 448 449
  Register GetRegisterParameter(int index) const {
    return call_descriptor().GetRegisterParameter(index);
  }

  Type* GetParameterType(int index) const {
    return call_descriptor().GetParameterType(index);
450 451
  }

452
  ExternalReference miss_handler() const {
453
    DCHECK(has_miss_handler_);
454 455 456
    return miss_handler_;
  }

457
  bool has_miss_handler() const {
458 459 460
    return has_miss_handler_;
  }

461
  int GetHandlerParameterCount() const {
462 463
    int params = GetParameterCount();
    if (PassesArgumentsToDeoptimizationHandler()) {
464 465 466 467 468
      params += 1;
    }
    return params;
  }

469 470 471 472 473
  int hint_stack_parameter_count() const { return hint_stack_parameter_count_; }
  Register stack_parameter_count() const { return stack_parameter_count_; }
  StubFunctionMode function_mode() const { return function_mode_; }
  Address deoptimization_handler() const { return deoptimization_handler_; }

474
 private:
475 476 477 478
  bool PassesArgumentsToDeoptimizationHandler() const {
    return stack_parameter_count_.is_valid();
  }

479
  CallInterfaceDescriptor call_descriptor_;
480 481 482 483 484 485 486 487
  Register stack_parameter_count_;
  // If hint_stack_parameter_count_ > 0, the code stub can optimize the
  // return sequence. Default value is -1, which means it is ignored.
  int hint_stack_parameter_count_;
  StubFunctionMode function_mode_;

  Address deoptimization_handler_;

488 489
  ExternalReference miss_handler_;
  bool has_miss_handler_;
490 491 492 493 494
};


class HydrogenCodeStub : public CodeStub {
 public:
495
  enum InitializationState {
496 497
    UNINITIALIZED,
    INITIALIZED
498 499 500 501 502 503 504 505 506
  };

  template<class SubClass>
  static Handle<Code> GetUninitialized(Isolate* isolate) {
    SubClass::GenerateAheadOfTime(isolate);
    return SubClass().GetCode(isolate);
  }

  // Retrieve the code for the stub. Generate the code if needed.
507
  Handle<Code> GenerateCode() override = 0;
508

509 510
  bool IsUninitialized() const { return IsMissBits::decode(minor_key_); }

511
  Handle<Code> GenerateLightweightMissCode(ExternalReference miss);
512

513 514 515
  template<class StateType>
  void TraceTransition(StateType from, StateType to);

516
 protected:
517 518 519 520 521 522
  explicit HydrogenCodeStub(Isolate* isolate,
                            InitializationState state = INITIALIZED)
      : CodeStub(isolate) {
    minor_key_ = IsMissBits::encode(state == UNINITIALIZED);
  }

523 524 525 526 527 528 529 530
  void set_sub_minor_key(uint32_t key) {
    minor_key_ = SubMinorKeyBits::update(minor_key_, key);
  }

  uint32_t sub_minor_key() const { return SubMinorKeyBits::decode(minor_key_); }

  static const int kSubMinorKeyBits = kStubMinorKeyBits - 1;

531
 private:
532
  class IsMissBits : public BitField<bool, kSubMinorKeyBits, 1> {};
533
  class SubMinorKeyBits : public BitField<int, 0, kSubMinorKeyBits> {};
534

535
  void GenerateLightweightMiss(MacroAssembler* masm, ExternalReference miss);
536

537
  DEFINE_CODE_STUB_BASE(HydrogenCodeStub, CodeStub);
538 539 540
};


541 542 543 544 545
class TurboFanCodeStub : public CodeStub {
 public:
  // Retrieve the code for the stub. Generate the code if needed.
  Handle<Code> GenerateCode() override;

546
  int GetStackParameterCount() const override {
547 548 549
    return GetCallInterfaceDescriptor().GetStackParameterCount();
  }

550 551
  Code::StubType GetStubType() const override { return Code::FAST; }

552 553 554
 protected:
  explicit TurboFanCodeStub(Isolate* isolate) : CodeStub(isolate) {}

555 556
  virtual void GenerateAssembly(
      compiler::CodeStubAssembler* assembler) const = 0;
557 558

 private:
559
  DEFINE_CODE_STUB_BASE(TurboFanCodeStub, CodeStub);
560 561 562
};


563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578
// Helper interface to prepare to/restore after making runtime calls.
class RuntimeCallHelper {
 public:
  virtual ~RuntimeCallHelper() {}

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

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

 protected:
  RuntimeCallHelper() {}

 private:
  DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
};

579

580 581
}  // namespace internal
}  // namespace v8
582 583

#if V8_TARGET_ARCH_IA32
584
#include "src/ia32/code-stubs-ia32.h"
585
#elif V8_TARGET_ARCH_X64
586
#include "src/x64/code-stubs-x64.h"
587
#elif V8_TARGET_ARCH_ARM64
588
#include "src/arm64/code-stubs-arm64.h"
589
#elif V8_TARGET_ARCH_ARM
590
#include "src/arm/code-stubs-arm.h"
591 592
#elif V8_TARGET_ARCH_PPC
#include "src/ppc/code-stubs-ppc.h"
593
#elif V8_TARGET_ARCH_MIPS
594
#include "src/mips/code-stubs-mips.h"
595 596
#elif V8_TARGET_ARCH_MIPS64
#include "src/mips64/code-stubs-mips64.h"
danno@chromium.org's avatar
danno@chromium.org committed
597
#elif V8_TARGET_ARCH_X87
598
#include "src/x87/code-stubs-x87.h"
599 600 601 602 603 604 605 606
#else
#error Unsupported target architecture.
#endif

namespace v8 {
namespace internal {


607
// RuntimeCallHelper implementation used in stubs: enters/leaves a
608
// newly created internal frame before/after the runtime call.
609
class StubRuntimeCallHelper : public RuntimeCallHelper {
610
 public:
611
  StubRuntimeCallHelper() {}
612

613
  void BeforeCall(MacroAssembler* masm) const override;
614

615
  void AfterCall(MacroAssembler* masm) const override;
616 617 618 619 620 621 622 623
};


// Trivial RuntimeCallHelper implementation.
class NopRuntimeCallHelper : public RuntimeCallHelper {
 public:
  NopRuntimeCallHelper() {}

624
  void BeforeCall(MacroAssembler* masm) const override {}
625

626
  void AfterCall(MacroAssembler* masm) const override {}
627 628 629
};


630
class StringLengthStub : public TurboFanCodeStub {
631
 public:
632
  explicit StringLengthStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
633

634 635 636
  Code::Kind GetCodeKind() const override { return Code::HANDLER; }
  InlineCacheState GetICState() const override { return MONOMORPHIC; }
  ExtraICState GetExtraICState() const override { return Code::LOAD_IC; }
637 638

  DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672
  DEFINE_TURBOFAN_CODE_STUB(StringLength, TurboFanCodeStub);
};

class LessThanStub final : public TurboFanCodeStub {
 public:
  explicit LessThanStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}

  DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
  DEFINE_TURBOFAN_CODE_STUB(LessThan, TurboFanCodeStub);
};

class LessThanOrEqualStub final : public TurboFanCodeStub {
 public:
  explicit LessThanOrEqualStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}

  DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
  DEFINE_TURBOFAN_CODE_STUB(LessThanOrEqual, TurboFanCodeStub);
};

class GreaterThanStub final : public TurboFanCodeStub {
 public:
  explicit GreaterThanStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}

  DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
  DEFINE_TURBOFAN_CODE_STUB(GreaterThan, TurboFanCodeStub);
};

class GreaterThanOrEqualStub final : public TurboFanCodeStub {
 public:
  explicit GreaterThanOrEqualStub(Isolate* isolate)
      : TurboFanCodeStub(isolate) {}

  DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
  DEFINE_TURBOFAN_CODE_STUB(GreaterThanOrEqual, TurboFanCodeStub);
673 674
};

675 676 677 678 679
class StrictEqualStub final : public TurboFanCodeStub {
 public:
  explicit StrictEqualStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}

  DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
680
  DEFINE_TURBOFAN_CODE_STUB(StrictEqual, TurboFanCodeStub);
681 682
};

683 684 685 686 687
class StrictNotEqualStub final : public TurboFanCodeStub {
 public:
  explicit StrictNotEqualStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}

  DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
688
  DEFINE_TURBOFAN_CODE_STUB(StrictNotEqual, TurboFanCodeStub);
689 690
};

691 692 693 694 695
class StringEqualStub final : public TurboFanCodeStub {
 public:
  explicit StringEqualStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}

  DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
696
  DEFINE_TURBOFAN_CODE_STUB(StringEqual, TurboFanCodeStub);
697 698 699 700 701 702 703
};

class StringNotEqualStub final : public TurboFanCodeStub {
 public:
  explicit StringNotEqualStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}

  DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
704
  DEFINE_TURBOFAN_CODE_STUB(StringNotEqual, TurboFanCodeStub);
705 706
};

707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741
class StringLessThanStub final : public TurboFanCodeStub {
 public:
  explicit StringLessThanStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}

  DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
  DEFINE_TURBOFAN_CODE_STUB(StringLessThan, TurboFanCodeStub);
};

class StringLessThanOrEqualStub final : public TurboFanCodeStub {
 public:
  explicit StringLessThanOrEqualStub(Isolate* isolate)
      : TurboFanCodeStub(isolate) {}

  DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
  DEFINE_TURBOFAN_CODE_STUB(StringLessThanOrEqual, TurboFanCodeStub);
};

class StringGreaterThanStub final : public TurboFanCodeStub {
 public:
  explicit StringGreaterThanStub(Isolate* isolate)
      : TurboFanCodeStub(isolate) {}

  DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
  DEFINE_TURBOFAN_CODE_STUB(StringGreaterThan, TurboFanCodeStub);
};

class StringGreaterThanOrEqualStub final : public TurboFanCodeStub {
 public:
  explicit StringGreaterThanOrEqualStub(Isolate* isolate)
      : TurboFanCodeStub(isolate) {}

  DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
  DEFINE_TURBOFAN_CODE_STUB(StringGreaterThanOrEqual, TurboFanCodeStub);
};

742 743 744 745 746
class ToBooleanStub final : public TurboFanCodeStub {
 public:
  explicit ToBooleanStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}

  DEFINE_CALL_INTERFACE_DESCRIPTOR(ToBoolean);
747
  DEFINE_TURBOFAN_CODE_STUB(ToBoolean, TurboFanCodeStub);
748
};
749 750 751 752 753 754 755 756 757

enum StringAddFlags {
  // Omit both parameter checks.
  STRING_ADD_CHECK_NONE = 0,
  // Check left parameter.
  STRING_ADD_CHECK_LEFT = 1 << 0,
  // Check right parameter.
  STRING_ADD_CHECK_RIGHT = 1 << 1,
  // Check both parameters.
758 759 760 761 762
  STRING_ADD_CHECK_BOTH = STRING_ADD_CHECK_LEFT | STRING_ADD_CHECK_RIGHT,
  // Convert parameters when check fails (instead of throwing an exception).
  STRING_ADD_CONVERT = 1 << 2,
  STRING_ADD_CONVERT_LEFT = STRING_ADD_CHECK_LEFT | STRING_ADD_CONVERT,
  STRING_ADD_CONVERT_RIGHT = STRING_ADD_CHECK_RIGHT | STRING_ADD_CONVERT
763 764 765 766 767 768
};


std::ostream& operator<<(std::ostream& os, const StringAddFlags& flags);


769
class NumberToStringStub final : public HydrogenCodeStub {
770
 public:
771
  explicit NumberToStringStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
772 773 774 775

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

776
  DEFINE_CALL_INTERFACE_DESCRIPTOR(NumberToString);
777
  DEFINE_HYDROGEN_CODE_STUB(NumberToString, HydrogenCodeStub);
778 779 780
};


781 782 783 784 785 786 787 788 789 790 791 792 793 794
class TypeofStub final : public HydrogenCodeStub {
 public:
  explicit TypeofStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}

  // Parameters accessed via CodeStubGraphBuilder::GetParameter()
  static const int kObject = 0;

  static void GenerateAheadOfTime(Isolate* isolate);

  DEFINE_CALL_INTERFACE_DESCRIPTOR(Typeof);
  DEFINE_HYDROGEN_CODE_STUB(Typeof, HydrogenCodeStub);
};


795
class FastNewClosureStub : public HydrogenCodeStub {
796
 public:
797
  FastNewClosureStub(Isolate* isolate, LanguageMode language_mode,
798
                     FunctionKind kind)
799
      : HydrogenCodeStub(isolate) {
800
    DCHECK(IsValidFunctionKind(kind));
801
    set_sub_minor_key(LanguageModeBits::encode(language_mode) |
802
                      FunctionKindBits::encode(kind));
803
  }
804

805 806
  LanguageMode language_mode() const {
    return LanguageModeBits::decode(sub_minor_key());
807 808
  }

809 810 811
  FunctionKind kind() const {
    return FunctionKindBits::decode(sub_minor_key());
  }
812 813

 private:
marja's avatar
marja committed
814 815
  STATIC_ASSERT(LANGUAGE_END == 3);
  class LanguageModeBits : public BitField<LanguageMode, 0, 2> {};
816
  class FunctionKindBits : public BitField<FunctionKind, 2, 8> {};
817

818
  DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewClosure);
819
  DEFINE_HYDROGEN_CODE_STUB(FastNewClosure, HydrogenCodeStub);
820 821 822
};


823
class FastNewContextStub final : public HydrogenCodeStub {
824
 public:
825
  static const int kMaximumSlots = 64;
826

827
  FastNewContextStub(Isolate* isolate, int slots) : HydrogenCodeStub(isolate) {
828
    DCHECK(slots >= 0 && slots <= kMaximumSlots);
829
    set_sub_minor_key(SlotsBits::encode(slots));
830 831
  }

832
  int slots() const { return SlotsBits::decode(sub_minor_key()); }
833 834 835

  // Parameters accessed via CodeStubGraphBuilder::GetParameter()
  static const int kFunction = 0;
836 837

 private:
838 839
  class SlotsBits : public BitField<int, 0, 8> {};

840
  DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewContext);
841
  DEFINE_HYDROGEN_CODE_STUB(FastNewContext, HydrogenCodeStub);
842 843 844
};


845 846 847 848 849 850 851 852 853
class FastNewObjectStub final : public PlatformCodeStub {
 public:
  explicit FastNewObjectStub(Isolate* isolate) : PlatformCodeStub(isolate) {}

  DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewObject);
  DEFINE_PLATFORM_CODE_STUB(FastNewObject, PlatformCodeStub);
};


854 855 856 857 858 859 860 861 862 863 864 865 866 867
// TODO(turbofan): This stub should be possible to write in TurboFan
// using the CodeStubAssembler very soon in a way that is as efficient
// and easy as the current handwritten version, which is partly a copy
// of the strict arguments object materialization code.
class FastNewRestParameterStub final : public PlatformCodeStub {
 public:
  explicit FastNewRestParameterStub(Isolate* isolate)
      : PlatformCodeStub(isolate) {}

  DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewRestParameter);
  DEFINE_PLATFORM_CODE_STUB(FastNewRestParameter, PlatformCodeStub);
};


868 869
// TODO(turbofan): This stub should be possible to write in TurboFan
// using the CodeStubAssembler very soon in a way that is as efficient
870 871 872 873 874 875 876 877 878 879 880 881 882 883
// and easy as the current handwritten version.
class FastNewSloppyArgumentsStub final : public PlatformCodeStub {
 public:
  explicit FastNewSloppyArgumentsStub(Isolate* isolate)
      : PlatformCodeStub(isolate) {}

  DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewSloppyArguments);
  DEFINE_PLATFORM_CODE_STUB(FastNewSloppyArguments, PlatformCodeStub);
};


// TODO(turbofan): This stub should be possible to write in TurboFan
// using the CodeStubAssembler very soon in a way that is as efficient
// and easy as the current handwritten version.
884 885 886 887 888 889 890 891 892 893
class FastNewStrictArgumentsStub final : public PlatformCodeStub {
 public:
  explicit FastNewStrictArgumentsStub(Isolate* isolate)
      : PlatformCodeStub(isolate) {}

  DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewStrictArguments);
  DEFINE_PLATFORM_CODE_STUB(FastNewStrictArguments, PlatformCodeStub);
};


894 895 896 897 898 899 900 901 902 903
class FastCloneRegExpStub final : public HydrogenCodeStub {
 public:
  explicit FastCloneRegExpStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}

 private:
  DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneRegExp);
  DEFINE_HYDROGEN_CODE_STUB(FastCloneRegExp, HydrogenCodeStub);
};


904
class FastCloneShallowArrayStub : public HydrogenCodeStub {
905
 public:
906
  FastCloneShallowArrayStub(Isolate* isolate,
907
                            AllocationSiteMode allocation_site_mode)
908 909 910
      : HydrogenCodeStub(isolate) {
    set_sub_minor_key(AllocationSiteModeBits::encode(allocation_site_mode));
  }
911

912
  AllocationSiteMode allocation_site_mode() const {
913
    return AllocationSiteModeBits::decode(sub_minor_key());
914 915
  }

916
 private:
917
  class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {};
918

919
  DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowArray);
920
  DEFINE_HYDROGEN_CODE_STUB(FastCloneShallowArray, HydrogenCodeStub);
921 922 923
};


924
class FastCloneShallowObjectStub : public HydrogenCodeStub {
925 926 927 928
 public:
  // Maximum number of properties in copied object.
  static const int kMaximumClonedProperties = 6;

929
  FastCloneShallowObjectStub(Isolate* isolate, int length)
930 931 932 933
      : HydrogenCodeStub(isolate) {
    DCHECK_GE(length, 0);
    DCHECK_LE(length, kMaximumClonedProperties);
    set_sub_minor_key(LengthBits::encode(length));
934 935
  }

936
  int length() const { return LengthBits::decode(sub_minor_key()); }
937

938
 private:
939
  class LengthBits : public BitField<int, 0, 4> {};
940

941
  DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowObject);
942
  DEFINE_HYDROGEN_CODE_STUB(FastCloneShallowObject, HydrogenCodeStub);
943 944 945
};


946 947
class CreateAllocationSiteStub : public HydrogenCodeStub {
 public:
948 949
  explicit CreateAllocationSiteStub(Isolate* isolate)
      : HydrogenCodeStub(isolate) { }
950 951 952

  static void GenerateAheadOfTime(Isolate* isolate);

953
  DEFINE_CALL_INTERFACE_DESCRIPTOR(CreateAllocationSite);
954
  DEFINE_HYDROGEN_CODE_STUB(CreateAllocationSite, HydrogenCodeStub);
955 956 957
};


958 959 960 961 962 963 964 965 966 967 968
class CreateWeakCellStub : public HydrogenCodeStub {
 public:
  explicit CreateWeakCellStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}

  static void GenerateAheadOfTime(Isolate* isolate);

  DEFINE_CALL_INTERFACE_DESCRIPTOR(CreateWeakCell);
  DEFINE_HYDROGEN_CODE_STUB(CreateWeakCell, HydrogenCodeStub);
};


969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990
class GrowArrayElementsStub : public HydrogenCodeStub {
 public:
  GrowArrayElementsStub(Isolate* isolate, bool is_js_array, ElementsKind kind)
      : HydrogenCodeStub(isolate) {
    set_sub_minor_key(ElementsKindBits::encode(kind) |
                      IsJsArrayBits::encode(is_js_array));
  }

  ElementsKind elements_kind() const {
    return ElementsKindBits::decode(sub_minor_key());
  }

  bool is_js_array() const { return IsJsArrayBits::decode(sub_minor_key()); }

 private:
  class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
  class IsJsArrayBits : public BitField<bool, ElementsKindBits::kNext, 1> {};

  DEFINE_CALL_INTERFACE_DESCRIPTOR(GrowArrayElements);
  DEFINE_HYDROGEN_CODE_STUB(GrowArrayElements, HydrogenCodeStub);
};

991

992 993 994
class InstanceOfStub final : public PlatformCodeStub {
 public:
  explicit InstanceOfStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
995

996
 private:
997 998
  DEFINE_CALL_INTERFACE_DESCRIPTOR(InstanceOf);
  DEFINE_PLATFORM_CODE_STUB(InstanceOf, PlatformCodeStub);
999 1000 1001
};


1002 1003 1004 1005 1006 1007 1008
enum AllocationSiteOverrideMode {
  DONT_OVERRIDE,
  DISABLE_ALLOCATION_SITES,
  LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
};


1009 1010 1011
class ArrayConstructorStub: public PlatformCodeStub {
 public:
  enum ArgumentCountKey { ANY, NONE, ONE, MORE_THAN_ONE };
1012

1013
  ArrayConstructorStub(Isolate* isolate, int argument_count);
1014

1015 1016 1017
  explicit ArrayConstructorStub(Isolate* isolate);

 private:
1018 1019 1020 1021
  ArgumentCountKey argument_count() const {
    return ArgumentCountBits::decode(minor_key_);
  }

1022 1023
  void GenerateDispatchToArrayStub(MacroAssembler* masm,
                                   AllocationSiteOverrideMode mode);
1024

1025
  void PrintName(std::ostream& os) const override;  // NOLINT
1026

1027
  class ArgumentCountBits : public BitField<ArgumentCountKey, 0, 2> {};
1028

1029
  DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
1030
  DEFINE_PLATFORM_CODE_STUB(ArrayConstructor, PlatformCodeStub);
1031 1032 1033
};


1034 1035 1036 1037 1038 1039
class InternalArrayConstructorStub: public PlatformCodeStub {
 public:
  explicit InternalArrayConstructorStub(Isolate* isolate);

 private:
  void GenerateCase(MacroAssembler* masm, ElementsKind kind);
1040

1041
  DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
1042
  DEFINE_PLATFORM_CODE_STUB(InternalArrayConstructor, PlatformCodeStub);
1043 1044 1045
};


1046
class MathPowStub: public PlatformCodeStub {
1047
 public:
1048
  enum ExponentType { INTEGER, DOUBLE, TAGGED, ON_STACK };
1049

1050
  MathPowStub(Isolate* isolate, ExponentType exponent_type)
1051 1052 1053 1054
      : PlatformCodeStub(isolate) {
    minor_key_ = ExponentTypeBits::encode(exponent_type);
  }

1055
  CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
1056 1057 1058 1059 1060 1061 1062 1063 1064
    if (exponent_type() == TAGGED) {
      return MathPowTaggedDescriptor(isolate());
    } else if (exponent_type() == INTEGER) {
      return MathPowIntegerDescriptor(isolate());
    }
    // A CallInterfaceDescriptor doesn't specify double registers (yet).
    return ContextOnlyDescriptor(isolate());
  }

1065
 private:
1066 1067 1068 1069 1070 1071
  ExponentType exponent_type() const {
    return ExponentTypeBits::decode(minor_key_);
  }

  class ExponentTypeBits : public BitField<ExponentType, 0, 2> {};

1072
  DEFINE_PLATFORM_CODE_STUB(MathPow, PlatformCodeStub);
1073 1074 1075
};


1076 1077
class CallICStub: public PlatformCodeStub {
 public:
1078
  CallICStub(Isolate* isolate, const CallICState& state)
1079 1080 1081
      : PlatformCodeStub(isolate) {
    minor_key_ = state.GetExtraICState();
  }
1082

1083
  Code::Kind GetCodeKind() const override { return Code::CALL_IC; }
1084

1085
  InlineCacheState GetICState() const override { return GENERIC; }
1086

1087
  ExtraICState GetExtraICState() const final {
1088
    return static_cast<ExtraICState>(minor_key_);
1089 1090 1091
  }

 protected:
1092
  int arg_count() const { return state().argc(); }
1093
  ConvertReceiverMode convert_mode() const { return state().convert_mode(); }
ishell's avatar
ishell committed
1094
  TailCallMode tail_call_mode() const { return state().tail_call_mode(); }
1095

1096 1097
  CallICState state() const {
    return CallICState(static_cast<ExtraICState>(minor_key_));
1098
  }
1099 1100

  // Code generation helpers.
1101
  void GenerateMiss(MacroAssembler* masm);
1102
  void HandleArrayCase(MacroAssembler* masm, Label* miss);
1103

1104
 private:
1105
  void PrintState(std::ostream& os) const override;  // NOLINT
1106

1107
  DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunctionWithFeedbackAndVector);
1108
  DEFINE_PLATFORM_CODE_STUB(CallIC, PlatformCodeStub);
1109 1110 1111
};


1112 1113
// TODO(verwaest): Translate to hydrogen code stub.
class FunctionPrototypeStub : public PlatformCodeStub {
1114
 public:
1115 1116
  explicit FunctionPrototypeStub(Isolate* isolate)
      : PlatformCodeStub(isolate) {}
1117

1118
  Code::Kind GetCodeKind() const override { return Code::HANDLER; }
1119

1120 1121 1122
  // TODO(mvstanton): only the receiver register is accessed. When this is
  // translated to a hydrogen code stub, a new CallInterfaceDescriptor
  // should be created that just uses that register for more efficient code.
1123
  CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
1124
    return LoadWithVectorDescriptor(isolate());
1125 1126
  }

1127
  DEFINE_PLATFORM_CODE_STUB(FunctionPrototype, PlatformCodeStub);
1128 1129 1130
};


1131 1132 1133 1134 1135 1136
// TODO(mvstanton): Translate to hydrogen code stub.
class LoadIndexedInterceptorStub : public PlatformCodeStub {
 public:
  explicit LoadIndexedInterceptorStub(Isolate* isolate)
      : PlatformCodeStub(isolate) {}

1137 1138
  Code::Kind GetCodeKind() const override { return Code::HANDLER; }
  Code::StubType GetStubType() const override { return Code::FAST; }
1139 1140 1141 1142 1143 1144

  DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
  DEFINE_PLATFORM_CODE_STUB(LoadIndexedInterceptor, PlatformCodeStub);
};


1145 1146 1147 1148 1149
class LoadIndexedStringStub : public PlatformCodeStub {
 public:
  explicit LoadIndexedStringStub(Isolate* isolate)
      : PlatformCodeStub(isolate) {}

1150 1151
  Code::Kind GetCodeKind() const override { return Code::HANDLER; }
  Code::StubType GetStubType() const override { return Code::FAST; }
1152 1153 1154 1155 1156 1157

  DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
  DEFINE_PLATFORM_CODE_STUB(LoadIndexedString, PlatformCodeStub);
};


1158
class HandlerStub : public HydrogenCodeStub {
1159
 public:
1160 1161 1162
  Code::Kind GetCodeKind() const override { return Code::HANDLER; }
  ExtraICState GetExtraICState() const override { return kind(); }
  InlineCacheState GetICState() const override { return MONOMORPHIC; }
1163

1164
  void InitializeDescriptor(CodeStubDescriptor* descriptor) override;
1165

1166
  CallInterfaceDescriptor GetCallInterfaceDescriptor() const override;
1167

1168
 protected:
1169
  explicit HandlerStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
1170

1171
  virtual Code::Kind kind() const = 0;
1172

1173
  DEFINE_CODE_STUB_BASE(HandlerStub, HydrogenCodeStub);
1174 1175 1176 1177 1178
};


class LoadFieldStub: public HandlerStub {
 public:
1179 1180 1181
  LoadFieldStub(Isolate* isolate, FieldIndex index) : HandlerStub(isolate) {
    int property_index_key = index.GetFieldAccessStubKey();
    set_sub_minor_key(LoadFieldByIndexBits::encode(property_index_key));
1182 1183
  }

1184 1185 1186 1187
  FieldIndex index() const {
    int property_index_key = LoadFieldByIndexBits::decode(sub_minor_key());
    return FieldIndex::FromFieldAccessStubKey(property_index_key);
  }
1188

1189
 protected:
1190 1191
  Code::Kind kind() const override { return Code::LOAD_IC; }
  Code::StubType GetStubType() const override { return Code::FAST; }
1192

1193
 private:
1194 1195
  class LoadFieldByIndexBits : public BitField<int, 0, 13> {};

1196
  DEFINE_HANDLER_CODE_STUB(LoadField, HandlerStub);
1197 1198 1199
};


1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225
class ArrayBufferViewLoadFieldStub : public HandlerStub {
 public:
  ArrayBufferViewLoadFieldStub(Isolate* isolate, FieldIndex index)
      : HandlerStub(isolate) {
    int property_index_key = index.GetFieldAccessStubKey();
    set_sub_minor_key(
        ArrayBufferViewLoadFieldByIndexBits::encode(property_index_key));
  }

  FieldIndex index() const {
    int property_index_key =
        ArrayBufferViewLoadFieldByIndexBits::decode(sub_minor_key());
    return FieldIndex::FromFieldAccessStubKey(property_index_key);
  }

 protected:
  Code::Kind kind() const override { return Code::LOAD_IC; }
  Code::StubType GetStubType() const override { return Code::FAST; }

 private:
  class ArrayBufferViewLoadFieldByIndexBits : public BitField<int, 0, 13> {};

  DEFINE_HANDLER_CODE_STUB(ArrayBufferViewLoadField, HandlerStub);
};


1226 1227 1228 1229 1230 1231
class KeyedLoadSloppyArgumentsStub : public HandlerStub {
 public:
  explicit KeyedLoadSloppyArgumentsStub(Isolate* isolate)
      : HandlerStub(isolate) {}

 protected:
1232 1233
  Code::Kind kind() const override { return Code::KEYED_LOAD_IC; }
  Code::StubType GetStubType() const override { return Code::FAST; }
1234 1235 1236 1237 1238 1239

 private:
  DEFINE_HANDLER_CODE_STUB(KeyedLoadSloppyArguments, HandlerStub);
};


1240 1241
class CommonStoreModeBits : public BitField<KeyedAccessStoreMode, 0, 3> {};

1242 1243
class KeyedStoreSloppyArgumentsStub : public HandlerStub {
 public:
1244 1245 1246 1247 1248
  explicit KeyedStoreSloppyArgumentsStub(Isolate* isolate,
                                         KeyedAccessStoreMode mode)
      : HandlerStub(isolate) {
    set_sub_minor_key(CommonStoreModeBits::encode(mode));
  }
1249 1250 1251 1252 1253 1254 1255 1256 1257 1258

 protected:
  Code::Kind kind() const override { return Code::KEYED_STORE_IC; }
  Code::StubType GetStubType() const override { return Code::FAST; }

 private:
  DEFINE_HANDLER_CODE_STUB(KeyedStoreSloppyArguments, HandlerStub);
};


1259 1260
class LoadConstantStub : public HandlerStub {
 public:
1261 1262 1263
  LoadConstantStub(Isolate* isolate, int constant_index)
      : HandlerStub(isolate) {
    set_sub_minor_key(ConstantIndexBits::encode(constant_index));
1264 1265
  }

1266 1267 1268
  int constant_index() const {
    return ConstantIndexBits::decode(sub_minor_key());
  }
1269 1270

 protected:
1271 1272
  Code::Kind kind() const override { return Code::LOAD_IC; }
  Code::StubType GetStubType() const override { return Code::FAST; }
1273 1274

 private:
1275 1276
  class ConstantIndexBits : public BitField<int, 0, kSubMinorKeyBits> {};

1277
  DEFINE_HANDLER_CODE_STUB(LoadConstant, HandlerStub);
1278 1279 1280
};


1281 1282 1283 1284
class StoreFieldStub : public HandlerStub {
 public:
  StoreFieldStub(Isolate* isolate, FieldIndex index,
                 Representation representation)
1285 1286 1287 1288 1289
      : HandlerStub(isolate) {
    int property_index_key = index.GetFieldAccessStubKey();
    uint8_t repr = PropertyDetails::EncodeRepresentation(representation);
    set_sub_minor_key(StoreFieldByIndexBits::encode(property_index_key) |
                      RepresentationBits::encode(repr));
1290 1291
  }

1292 1293 1294 1295 1296 1297 1298 1299 1300 1301
  FieldIndex index() const {
    int property_index_key = StoreFieldByIndexBits::decode(sub_minor_key());
    return FieldIndex::FromFieldAccessStubKey(property_index_key);
  }

  Representation representation() {
    uint8_t repr = RepresentationBits::decode(sub_minor_key());
    return PropertyDetails::DecodeRepresentation(repr);
  }

1302
 protected:
1303 1304
  Code::Kind kind() const override { return Code::STORE_IC; }
  Code::StubType GetStubType() const override { return Code::FAST; }
1305 1306

 private:
1307 1308 1309
  class StoreFieldByIndexBits : public BitField<int, 0, 13> {};
  class RepresentationBits : public BitField<uint8_t, 13, 4> {};

1310
  DEFINE_HANDLER_CODE_STUB(StoreField, HandlerStub);
1311 1312 1313
};


1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339
// Register and parameter access methods are specified here instead of in
// the CallInterfaceDescriptor because the stub uses a different descriptor
// if FLAG_vector_stores is on.
class StoreTransitionHelper {
 public:
  static Register ReceiverRegister() {
    return StoreTransitionDescriptor::ReceiverRegister();
  }

  static Register NameRegister() {
    return StoreTransitionDescriptor::NameRegister();
  }

  static Register ValueRegister() {
    return StoreTransitionDescriptor::ValueRegister();
  }

  static Register SlotRegister() {
    return VectorStoreTransitionDescriptor::SlotRegister();
  }

  static Register VectorRegister() {
    return VectorStoreTransitionDescriptor::VectorRegister();
  }

  static Register MapRegister() {
1340
    return VectorStoreTransitionDescriptor::MapRegister();
1341 1342 1343 1344 1345 1346 1347 1348 1349 1350
  }

  static int ReceiverIndex() {
    return StoreTransitionDescriptor::kReceiverIndex;
  }

  static int NameIndex() { return StoreTransitionDescriptor::kReceiverIndex; }

  static int ValueIndex() { return StoreTransitionDescriptor::kValueIndex; }

1351 1352 1353 1354
  static int MapIndex() {
    DCHECK(static_cast<int>(VectorStoreTransitionDescriptor::kMapIndex) ==
           static_cast<int>(StoreTransitionDescriptor::kMapIndex));
    return StoreTransitionDescriptor::kMapIndex;
1355 1356 1357
  }

  static int VectorIndex() {
1358 1359 1360
    if (HasVirtualSlotArg()) {
      return VectorStoreTransitionDescriptor::kVirtualSlotVectorIndex;
    }
1361 1362 1363
    return VectorStoreTransitionDescriptor::kVectorIndex;
  }

1364 1365 1366
  // Some platforms don't have a slot arg.
  static bool HasVirtualSlotArg() {
    return SlotRegister().is(no_reg);
1367 1368 1369 1370
  }
};


1371
class StoreTransitionStub : public HandlerStub {
1372
 public:
1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384
  enum StoreMode {
    StoreMapOnly,
    StoreMapAndValue,
    ExtendStorageAndStoreMapAndValue
  };

  explicit StoreTransitionStub(Isolate* isolate) : HandlerStub(isolate) {
    set_sub_minor_key(StoreModeBits::encode(StoreMapOnly));
  }

  StoreTransitionStub(Isolate* isolate, FieldIndex index,
                      Representation representation, StoreMode store_mode)
1385
      : HandlerStub(isolate) {
1386
    DCHECK(store_mode != StoreMapOnly);
1387 1388 1389
    int property_index_key = index.GetFieldAccessStubKey();
    uint8_t repr = PropertyDetails::EncodeRepresentation(representation);
    set_sub_minor_key(StoreFieldByIndexBits::encode(property_index_key) |
1390 1391
                      RepresentationBits::encode(repr) |
                      StoreModeBits::encode(store_mode));
1392 1393 1394
  }

  FieldIndex index() const {
1395
    DCHECK(store_mode() != StoreMapOnly);
1396 1397 1398 1399 1400
    int property_index_key = StoreFieldByIndexBits::decode(sub_minor_key());
    return FieldIndex::FromFieldAccessStubKey(property_index_key);
  }

  Representation representation() {
1401
    DCHECK(store_mode() != StoreMapOnly);
1402 1403 1404 1405
    uint8_t repr = RepresentationBits::decode(sub_minor_key());
    return PropertyDetails::DecodeRepresentation(repr);
  }

1406 1407 1408 1409
  StoreMode store_mode() const {
    return StoreModeBits::decode(sub_minor_key());
  }

1410
  CallInterfaceDescriptor GetCallInterfaceDescriptor() const override;
1411 1412

 protected:
1413 1414
  Code::Kind kind() const override { return Code::STORE_IC; }
  Code::StubType GetStubType() const override { return Code::FAST; }
1415 1416 1417 1418

 private:
  class StoreFieldByIndexBits : public BitField<int, 0, 13> {};
  class RepresentationBits : public BitField<uint8_t, 13, 4> {};
1419
  class StoreModeBits : public BitField<StoreMode, 17, 2> {};
1420

1421
  DEFINE_HANDLER_CODE_STUB(StoreTransition, HandlerStub);
1422 1423 1424
};


1425 1426
class StoreGlobalStub : public HandlerStub {
 public:
1427 1428 1429
  StoreGlobalStub(Isolate* isolate, PropertyCellType type,
                  Maybe<PropertyCellConstantType> constant_type,
                  bool check_global)
1430
      : HandlerStub(isolate) {
1431 1432 1433 1434
    PropertyCellConstantType encoded_constant_type =
        constant_type.FromMaybe(PropertyCellConstantType::kSmi);
    set_sub_minor_key(CellTypeBits::encode(type) |
                      ConstantTypeBits::encode(encoded_constant_type) |
1435
                      CheckGlobalBits::encode(check_global));
1436 1437
  }

1438
  static Handle<HeapObject> property_cell_placeholder(Isolate* isolate) {
1439
    return isolate->factory()->uninitialized_value();
1440 1441
  }

1442 1443 1444 1445
  static Handle<HeapObject> global_map_placeholder(Isolate* isolate) {
    return isolate->factory()->termination_exception();
  }

1446
  Handle<Code> GetCodeCopyFromTemplate(Handle<JSGlobalObject> global,
1447
                                       Handle<PropertyCell> cell) {
1448
    Code::FindAndReplacePattern pattern;
1449
    if (check_global()) {
1450
      pattern.Add(handle(global_map_placeholder(isolate())->map()),
1451
                  Map::WeakCellForMap(Handle<Map>(global->map())));
1452
    }
1453 1454 1455
    pattern.Add(handle(property_cell_placeholder(isolate())->map()),
                isolate()->factory()->NewWeakCell(cell));
    return CodeStub::GetCodeCopy(pattern);
1456 1457
  }

1458
  Code::Kind kind() const override { return Code::STORE_IC; }
1459

1460 1461 1462
  PropertyCellType cell_type() const {
    return CellTypeBits::decode(sub_minor_key());
  }
1463

1464 1465 1466
  PropertyCellConstantType constant_type() const {
    DCHECK(PropertyCellType::kConstantType == cell_type());
    return ConstantTypeBits::decode(sub_minor_key());
1467 1468
  }

1469 1470
  bool check_global() const { return CheckGlobalBits::decode(sub_minor_key()); }

1471
  Representation representation() {
1472 1473
    return Representation::FromKind(
        RepresentationBits::decode(sub_minor_key()));
1474
  }
1475

1476
  void set_representation(Representation r) {
1477
    set_sub_minor_key(RepresentationBits::update(sub_minor_key(), r.kind()));
1478 1479 1480
  }

 private:
1481 1482 1483 1484
  class CellTypeBits : public BitField<PropertyCellType, 0, 2> {};
  class ConstantTypeBits : public BitField<PropertyCellConstantType, 2, 2> {};
  class RepresentationBits : public BitField<Representation::Kind, 4, 8> {};
  class CheckGlobalBits : public BitField<bool, 12, 1> {};
1485

1486
  DEFINE_HANDLER_CODE_STUB(StoreGlobal, HandlerStub);
1487 1488 1489
};


1490
class LoadGlobalViaContextStub final : public PlatformCodeStub {
1491
 public:
1492
  static const int kMaximumDepth = 15;
1493 1494

  LoadGlobalViaContextStub(Isolate* isolate, int depth)
1495 1496
      : PlatformCodeStub(isolate) {
    minor_key_ = DepthBits::encode(depth);
1497 1498
  }

1499
  int depth() const { return DepthBits::decode(minor_key_); }
1500 1501

 private:
1502 1503
  class DepthBits : public BitField<int, 0, 4> {};
  STATIC_ASSERT(DepthBits::kMax == kMaximumDepth);
1504 1505

  DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadGlobalViaContext);
1506
  DEFINE_PLATFORM_CODE_STUB(LoadGlobalViaContext, PlatformCodeStub);
1507 1508 1509
};


1510
class StoreGlobalViaContextStub final : public PlatformCodeStub {
1511
 public:
1512
  static const int kMaximumDepth = 15;
1513 1514 1515

  StoreGlobalViaContextStub(Isolate* isolate, int depth,
                            LanguageMode language_mode)
1516 1517 1518
      : PlatformCodeStub(isolate) {
    minor_key_ =
        DepthBits::encode(depth) | LanguageModeBits::encode(language_mode);
1519 1520
  }

1521
  int depth() const { return DepthBits::decode(minor_key_); }
1522
  LanguageMode language_mode() const {
1523
    return LanguageModeBits::decode(minor_key_);
1524 1525 1526
  }

 private:
1527 1528
  class DepthBits : public BitField<int, 0, 4> {};
  STATIC_ASSERT(DepthBits::kMax == kMaximumDepth);
1529 1530 1531 1532
  class LanguageModeBits : public BitField<LanguageMode, 4, 2> {};
  STATIC_ASSERT(LANGUAGE_END == 3);

  DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreGlobalViaContext);
1533
  DEFINE_PLATFORM_CODE_STUB(StoreGlobalViaContext, PlatformCodeStub);
1534 1535 1536
};


1537 1538
class CallApiFunctionStub : public PlatformCodeStub {
 public:
1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557
  explicit CallApiFunctionStub(Isolate* isolate, bool call_data_undefined)
      : PlatformCodeStub(isolate) {
    minor_key_ = CallDataUndefinedBits::encode(call_data_undefined);
  }

 private:
  bool call_data_undefined() const {
    return CallDataUndefinedBits::decode(minor_key_);
  }

  class CallDataUndefinedBits : public BitField<bool, 0, 1> {};

  DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiFunction);
  DEFINE_PLATFORM_CODE_STUB(CallApiFunction, PlatformCodeStub);
};


class CallApiAccessorStub : public PlatformCodeStub {
 public:
1558 1559
  CallApiAccessorStub(Isolate* isolate, bool is_store, bool call_data_undefined,
                      bool is_lazy)
1560
      : PlatformCodeStub(isolate) {
1561
    minor_key_ = IsStoreBits::encode(is_store) |
1562
                 CallDataUndefinedBits::encode(call_data_undefined) |
1563 1564
                 ArgumentBits::encode(is_store ? 1 : 0) |
                 IsLazyAccessorBits::encode(is_lazy);
1565 1566 1567 1568 1569 1570 1571 1572 1573 1574
  }

 protected:
  // For CallApiFunctionWithFixedArgsStub, see below.
  static const int kArgBits = 3;
  CallApiAccessorStub(Isolate* isolate, int argc, bool call_data_undefined)
      : PlatformCodeStub(isolate) {
    minor_key_ = IsStoreBits::encode(false) |
                 CallDataUndefinedBits::encode(call_data_undefined) |
                 ArgumentBits::encode(argc);
1575 1576 1577
  }

 private:
1578
  bool is_store() const { return IsStoreBits::decode(minor_key_); }
1579
  bool is_lazy() const { return IsLazyAccessorBits::decode(minor_key_); }
1580 1581 1582
  bool call_data_undefined() const {
    return CallDataUndefinedBits::decode(minor_key_);
  }
1583
  int argc() const { return ArgumentBits::decode(minor_key_); }
1584

1585
  class IsStoreBits: public BitField<bool, 0, 1> {};
1586
  class CallDataUndefinedBits: public BitField<bool, 1, 1> {};
1587
  class ArgumentBits : public BitField<int, 2, kArgBits> {};
1588
  class IsLazyAccessorBits : public BitField<bool, 3 + kArgBits, 1> {};
1589

1590 1591
  DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiAccessor);
  DEFINE_PLATFORM_CODE_STUB(CallApiAccessor, PlatformCodeStub);
1592 1593 1594
};


1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612
// TODO(dcarney): see if it's possible to remove this later without performance
// degradation.
// This is not a real stub, but a way of generating the CallApiAccessorStub
// (which has the same abi) which makes it clear that it is not an accessor.
class CallApiFunctionWithFixedArgsStub : public CallApiAccessorStub {
 public:
  static const int kMaxFixedArgs = (1 << kArgBits) - 1;
  CallApiFunctionWithFixedArgsStub(Isolate* isolate, int argc,
                                   bool call_data_undefined)
      : CallApiAccessorStub(isolate, argc, call_data_undefined) {
    DCHECK(0 <= argc && argc <= kMaxFixedArgs);
  }
};


typedef ApiAccessorDescriptor ApiFunctionWithFixedArgsDescriptor;


dcarney@chromium.org's avatar
dcarney@chromium.org committed
1613 1614
class CallApiGetterStub : public PlatformCodeStub {
 public:
1615
  explicit CallApiGetterStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
dcarney@chromium.org's avatar
dcarney@chromium.org committed
1616

1617
  DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiGetter);
1618
  DEFINE_PLATFORM_CODE_STUB(CallApiGetter, PlatformCodeStub);
dcarney@chromium.org's avatar
dcarney@chromium.org committed
1619
};
1620 1621


1622
class BinaryOpICStub : public HydrogenCodeStub {
1623
 public:
1624
  BinaryOpICStub(Isolate* isolate, Token::Value op)
1625
      : HydrogenCodeStub(isolate, UNINITIALIZED) {
1626
    BinaryOpICState state(isolate, op);
1627 1628
    set_sub_minor_key(state.GetExtraICState());
  }
1629

1630
  BinaryOpICStub(Isolate* isolate, const BinaryOpICState& state)
1631 1632 1633
      : HydrogenCodeStub(isolate) {
    set_sub_minor_key(state.GetExtraICState());
  }
1634

1635
  static void GenerateAheadOfTime(Isolate* isolate);
1636

1637
  Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; }
1638

1639
  InlineCacheState GetICState() const final { return state().GetICState(); }
1640

1641
  ExtraICState GetExtraICState() const final {
1642
    return static_cast<ExtraICState>(sub_minor_key());
1643
  }
1644

1645 1646
  BinaryOpICState state() const {
    return BinaryOpICState(isolate(), GetExtraICState());
1647
  }
1648

1649
  void PrintState(std::ostream& os) const final;  // NOLINT
1650

1651 1652 1653
  // Parameters accessed via CodeStubGraphBuilder::GetParameter()
  static const int kLeft = 0;
  static const int kRight = 1;
1654 1655

 private:
1656
  static void GenerateAheadOfTime(Isolate* isolate,
1657
                                  const BinaryOpICState& state);
1658

1659
  DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1660
  DEFINE_HYDROGEN_CODE_STUB(BinaryOpIC, HydrogenCodeStub);
1661 1662 1663
};


1664 1665
// TODO(bmeurer): Merge this into the BinaryOpICStub once we have proper tail
// call support for stubs in Hydrogen.
1666
class BinaryOpICWithAllocationSiteStub final : public PlatformCodeStub {
1667
 public:
1668
  BinaryOpICWithAllocationSiteStub(Isolate* isolate,
1669
                                   const BinaryOpICState& state)
1670
      : PlatformCodeStub(isolate) {
1671 1672
    minor_key_ = state.GetExtraICState();
  }
1673 1674 1675

  static void GenerateAheadOfTime(Isolate* isolate);

1676
  Handle<Code> GetCodeCopyFromTemplate(Handle<AllocationSite> allocation_site) {
1677
    Code::FindAndReplacePattern pattern;
1678 1679
    pattern.Add(isolate()->factory()->undefined_map(), allocation_site);
    return CodeStub::GetCodeCopy(pattern);
1680 1681
  }

1682
  Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; }
1683

1684
  InlineCacheState GetICState() const override { return state().GetICState(); }
1685

1686
  ExtraICState GetExtraICState() const override {
1687
    return static_cast<ExtraICState>(minor_key_);
1688 1689
  }

1690
  void PrintState(std::ostream& os) const override;  // NOLINT
1691 1692

 private:
1693 1694
  BinaryOpICState state() const {
    return BinaryOpICState(isolate(), static_cast<ExtraICState>(minor_key_));
1695 1696
  }

1697
  static void GenerateAheadOfTime(Isolate* isolate,
1698
                                  const BinaryOpICState& state);
1699

1700
  DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1701
  DEFINE_PLATFORM_CODE_STUB(BinaryOpICWithAllocationSite, PlatformCodeStub);
1702 1703 1704
};


1705
class BinaryOpWithAllocationSiteStub final : public BinaryOpICStub {
1706
 public:
1707 1708
  BinaryOpWithAllocationSiteStub(Isolate* isolate, Token::Value op)
      : BinaryOpICStub(isolate, op) {}
1709

1710
  BinaryOpWithAllocationSiteStub(Isolate* isolate, const BinaryOpICState& state)
1711
      : BinaryOpICStub(isolate, state) {}
1712

1713
  Code::Kind GetCodeKind() const final { return Code::STUB; }
1714 1715 1716 1717 1718

  // Parameters accessed via CodeStubGraphBuilder::GetParameter()
  static const int kAllocationSite = 0;
  static const int kLeft = 1;
  static const int kRight = 2;
1719

1720
  DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1721
  DEFINE_HYDROGEN_CODE_STUB(BinaryOpWithAllocationSite, BinaryOpICStub);
1722 1723 1724
};


1725
class StringAddStub final : public HydrogenCodeStub {
1726
 public:
1727
  StringAddStub(Isolate* isolate, StringAddFlags flags,
1728
                PretenureFlag pretenure_flag)
1729 1730 1731 1732
      : HydrogenCodeStub(isolate) {
    set_sub_minor_key(StringAddFlagsBits::encode(flags) |
                      PretenureFlagBits::encode(pretenure_flag));
  }
1733 1734

  StringAddFlags flags() const {
1735
    return StringAddFlagsBits::decode(sub_minor_key());
1736 1737 1738
  }

  PretenureFlag pretenure_flag() const {
1739
    return PretenureFlagBits::decode(sub_minor_key());
1740 1741 1742 1743 1744 1745 1746
  }

  // Parameters accessed via CodeStubGraphBuilder::GetParameter()
  static const int kLeft = 0;
  static const int kRight = 1;

 private:
1747 1748
  class StringAddFlagsBits : public BitField<StringAddFlags, 0, 3> {};
  class PretenureFlagBits : public BitField<PretenureFlag, 3, 1> {};
1749

1750
  void PrintBaseName(std::ostream& os) const override;  // NOLINT
1751

1752
  DEFINE_CALL_INTERFACE_DESCRIPTOR(StringAdd);
1753
  DEFINE_HYDROGEN_CODE_STUB(StringAdd, HydrogenCodeStub);
1754 1755 1756
};


1757
class CompareICStub : public PlatformCodeStub {
1758
 public:
1759 1760
  CompareICStub(Isolate* isolate, Token::Value op, CompareICState::State left,
                CompareICState::State right, CompareICState::State state)
1761
      : PlatformCodeStub(isolate) {
1762
    DCHECK(Token::IsCompareOp(op));
1763
    minor_key_ = OpBits::encode(op - Token::EQ) |
1764 1765
                 LeftStateBits::encode(left) | RightStateBits::encode(right) |
                 StateBits::encode(state);
1766 1767
  }

1768 1769
  void set_known_map(Handle<Map> map) { known_map_ = map; }

1770
  InlineCacheState GetICState() const override;
1771

1772 1773 1774 1775
  Token::Value op() const {
    return static_cast<Token::Value>(Token::EQ + OpBits::decode(minor_key_));
  }

1776 1777 1778 1779 1780 1781 1782
  CompareICState::State left() const {
    return LeftStateBits::decode(minor_key_);
  }
  CompareICState::State right() const {
    return RightStateBits::decode(minor_key_);
  }
  CompareICState::State state() const { return StateBits::decode(minor_key_); }
1783

1784
 private:
1785
  Code::Kind GetCodeKind() const override { return Code::COMPARE_IC; }
1786

1787
  void GenerateBooleans(MacroAssembler* masm);
1788
  void GenerateSmis(MacroAssembler* masm);
1789
  void GenerateNumbers(MacroAssembler* masm);
1790
  void GenerateInternalizedStrings(MacroAssembler* masm);
1791
  void GenerateStrings(MacroAssembler* masm);
1792
  void GenerateUniqueNames(MacroAssembler* masm);
1793
  void GenerateReceivers(MacroAssembler* masm);
1794
  void GenerateMiss(MacroAssembler* masm);
1795
  void GenerateKnownReceivers(MacroAssembler* masm);
1796
  void GenerateGeneric(MacroAssembler* masm);
1797

1798
  bool strict() const { return op() == Token::EQ_STRICT; }
1799
  Condition GetCondition() const;
1800

1801 1802 1803
  void AddToSpecialCache(Handle<Code> new_object) override;
  bool FindCodeInSpecialCache(Code** code_out) override;
  bool UseSpecialCache() override {
1804
    return state() == CompareICState::KNOWN_RECEIVER;
1805
  }
1806 1807

  class OpBits : public BitField<int, 0, 3> {};
1808 1809 1810
  class LeftStateBits : public BitField<CompareICState::State, 3, 4> {};
  class RightStateBits : public BitField<CompareICState::State, 7, 4> {};
  class StateBits : public BitField<CompareICState::State, 11, 4> {};
1811 1812

  Handle<Map> known_map_;
1813

1814
  DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1815
  DEFINE_PLATFORM_CODE_STUB(CompareIC, PlatformCodeStub);
1816 1817 1818
};


1819
class CEntryStub : public PlatformCodeStub {
1820
 public:
1821
  CEntryStub(Isolate* isolate, int result_size,
1822 1823
             SaveFPRegsMode save_doubles = kDontSaveFPRegs,
             ArgvMode argv_mode = kArgvOnStack)
1824
      : PlatformCodeStub(isolate) {
1825 1826
    minor_key_ = SaveDoublesBits::encode(save_doubles == kSaveFPRegs) |
                 ArgvMode::encode(argv_mode == kArgvInRegister);
1827
    DCHECK(result_size == 1 || result_size == 2 || result_size == 3);
1828 1829
    minor_key_ = ResultSizeBits::update(minor_key_, result_size);
  }
1830

1831 1832
  // The version of this stub that doesn't save doubles is generated ahead of
  // time, so it's OK to call it from other stubs that can't cope with GC during
1833 1834
  // their code generation.  On machines that always have gp registers (x64) we
  // can generate both variants ahead of time.
1835
  static void GenerateAheadOfTime(Isolate* isolate);
1836

1837
 private:
1838
  bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
1839
  bool argv_in_register() const { return ArgvMode::decode(minor_key_); }
1840
  int result_size() const { return ResultSizeBits::decode(minor_key_); }
1841

1842
  bool NeedsImmovableCode() override;
1843 1844

  class SaveDoublesBits : public BitField<bool, 0, 1> {};
1845 1846
  class ArgvMode : public BitField<bool, 1, 1> {};
  class ResultSizeBits : public BitField<int, 2, 3> {};
1847

1848
  DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1849
  DEFINE_PLATFORM_CODE_STUB(CEntry, PlatformCodeStub);
1850 1851 1852
};


1853
class JSEntryStub : public PlatformCodeStub {
1854
 public:
1855 1856 1857 1858 1859
  JSEntryStub(Isolate* isolate, StackFrame::Type type)
      : PlatformCodeStub(isolate) {
    DCHECK(type == StackFrame::ENTRY || type == StackFrame::ENTRY_CONSTRUCT);
    minor_key_ = StackFrameTypeBits::encode(type);
  }
1860 1861

 private:
1862
  void FinishCode(Handle<Code> code) override;
1863

1864
  void PrintName(std::ostream& os) const override {  // NOLINT
1865 1866 1867
    os << (type() == StackFrame::ENTRY ? "JSEntryStub"
                                       : "JSConstructEntryStub");
  }
1868

1869 1870 1871
  StackFrame::Type type() const {
    return StackFrameTypeBits::decode(minor_key_);
  }
1872

1873
  class StackFrameTypeBits : public BitField<StackFrame::Type, 0, 5> {};
1874

1875
  int handler_offset_;
1876

1877
  DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1878
  DEFINE_PLATFORM_CODE_STUB(JSEntry, PlatformCodeStub);
1879 1880 1881
};


1882
class RegExpExecStub: public PlatformCodeStub {
1883
 public:
1884
  explicit RegExpExecStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
1885

1886
  DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
1887
  DEFINE_PLATFORM_CODE_STUB(RegExpExec, PlatformCodeStub);
1888 1889 1890
};


1891
class RegExpConstructResultStub final : public HydrogenCodeStub {
1892
 public:
1893 1894
  explicit RegExpConstructResultStub(Isolate* isolate)
      : HydrogenCodeStub(isolate) { }
1895

1896 1897 1898 1899 1900
  // Parameters accessed via CodeStubGraphBuilder::GetParameter()
  static const int kLength = 0;
  static const int kIndex = 1;
  static const int kInput = 2;

1901
  DEFINE_CALL_INTERFACE_DESCRIPTOR(RegExpConstructResult);
1902
  DEFINE_HYDROGEN_CODE_STUB(RegExpConstructResult, HydrogenCodeStub);
1903 1904 1905
};


1906 1907
// TODO(bmeurer/mvstanton): Turn CallConstructStub into ConstructICStub.
class CallConstructStub final : public PlatformCodeStub {
1908
 public:
1909
  explicit CallConstructStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
1910

1911 1912
  DEFINE_CALL_INTERFACE_DESCRIPTOR(CallConstruct);
  DEFINE_PLATFORM_CODE_STUB(CallConstruct, PlatformCodeStub);
1913 1914 1915
};


1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926
enum StringIndexFlags {
  // Accepts smis or heap numbers.
  STRING_INDEX_IS_NUMBER,

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


1927 1928 1929 1930 1931 1932 1933 1934 1935
enum ReceiverCheckMode {
  // We don't know anything about the receiver.
  RECEIVER_IS_UNKNOWN,

  // We know the receiver is a string.
  RECEIVER_IS_STRING
};


1936 1937 1938 1939 1940 1941 1942 1943 1944
enum EmbedMode {
  // The code being generated is part of an IC handler, which may MISS
  // to an IC in failure cases.
  PART_OF_IC_HANDLER,

  NOT_PART_OF_IC_HANDLER
};


1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956
// Generates code implementing String.prototype.charCodeAt.
//
// Only supports the case when the receiver is a string and the index
// is a number (smi or heap number) that is a valid index into the
// string. Additional index constraints are specified by the
// flags. Otherwise, bails out to the provided labels.
//
// Register usage: |object| may be changed to another string in a way
// that doesn't affect charCodeAt/charAt semantics, |index| is
// preserved, |scratch| and |result| are clobbered.
class StringCharCodeAtGenerator {
 public:
1957 1958
  StringCharCodeAtGenerator(Register object, Register index, Register result,
                            Label* receiver_not_string, Label* index_not_number,
1959
                            Label* index_out_of_range,
1960 1961
                            StringIndexFlags index_flags,
                            ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN)
1962 1963 1964 1965 1966 1967
      : object_(object),
        index_(index),
        result_(result),
        receiver_not_string_(receiver_not_string),
        index_not_number_(index_not_number),
        index_out_of_range_(index_out_of_range),
1968 1969
        index_flags_(index_flags),
        check_mode_(check_mode) {
1970 1971
    DCHECK(!result_.is(object_));
    DCHECK(!result_.is(index_));
1972 1973 1974 1975 1976 1977 1978 1979 1980
  }

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

  // Generates the slow case code. Must not be naturally
  // reachable. Expected to be put after a ret instruction (e.g., in
  // deferred code). Always jumps back to the fast case.
1981
  void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode,
1982 1983
                    const RuntimeCallHelper& call_helper);

1984 1985 1986 1987 1988 1989 1990
  // Skip handling slow case and directly jump to bailout.
  void SkipSlow(MacroAssembler* masm, Label* bailout) {
    masm->bind(&index_not_smi_);
    masm->bind(&call_runtime_);
    masm->jmp(bailout);
  }

1991 1992 1993 1994 1995 1996 1997 1998 1999 2000
 private:
  Register object_;
  Register index_;
  Register result_;

  Label* receiver_not_string_;
  Label* index_not_number_;
  Label* index_out_of_range_;

  StringIndexFlags index_flags_;
2001
  ReceiverCheckMode check_mode_;
2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018

  Label call_runtime_;
  Label index_not_smi_;
  Label got_smi_index_;
  Label exit_;

  DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
};


// Generates code for creating a one-char string from a char code.
class StringCharFromCodeGenerator {
 public:
  StringCharFromCodeGenerator(Register code,
                              Register result)
      : code_(code),
        result_(result) {
2019
    DCHECK(!code_.is(result_));
2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031
  }

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

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

2032 2033 2034 2035 2036 2037
  // Skip handling slow case and directly jump to bailout.
  void SkipSlow(MacroAssembler* masm, Label* bailout) {
    masm->bind(&slow_case_);
    masm->jmp(bailout);
  }

2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060
 private:
  Register code_;
  Register result_;

  Label slow_case_;
  Label exit_;

  DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
};


// Generates code implementing String.prototype.charAt.
//
// Only supports the case when the receiver is a string and the index
// is a number (smi or heap number) that is a valid index into the
// string. Additional index constraints are specified by the
// flags. Otherwise, bails out to the provided labels.
//
// Register usage: |object| may be changed to another string in a way
// that doesn't affect charCodeAt/charAt semantics, |index| is
// preserved, |scratch1|, |scratch2|, and |result| are clobbered.
class StringCharAtGenerator {
 public:
2061 2062 2063 2064 2065 2066 2067
  StringCharAtGenerator(Register object, Register index, Register scratch,
                        Register result, Label* receiver_not_string,
                        Label* index_not_number, Label* index_out_of_range,
                        StringIndexFlags index_flags,
                        ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN)
      : char_code_at_generator_(object, index, scratch, receiver_not_string,
                                index_not_number, index_out_of_range,
2068
                                index_flags, check_mode),
2069
        char_from_code_generator_(scratch, result) {}
2070 2071 2072

  // Generates the fast case code. On the fallthrough path |result|
  // register contains the result.
2073 2074 2075 2076
  void GenerateFast(MacroAssembler* masm) {
    char_code_at_generator_.GenerateFast(masm);
    char_from_code_generator_.GenerateFast(masm);
  }
2077 2078 2079 2080

  // Generates the slow case code. Must not be naturally
  // reachable. Expected to be put after a ret instruction (e.g., in
  // deferred code). Always jumps back to the fast case.
2081
  void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode,
2082
                    const RuntimeCallHelper& call_helper) {
2083
    char_code_at_generator_.GenerateSlow(masm, embed_mode, call_helper);
2084 2085 2086 2087 2088 2089 2090 2091
    char_from_code_generator_.GenerateSlow(masm, call_helper);
  }

  // Skip handling slow case and directly jump to bailout.
  void SkipSlow(MacroAssembler* masm, Label* bailout) {
    char_code_at_generator_.SkipSlow(masm, bailout);
    char_from_code_generator_.SkipSlow(masm, bailout);
  }
2092 2093 2094 2095 2096 2097 2098 2099

 private:
  StringCharCodeAtGenerator char_code_at_generator_;
  StringCharFromCodeGenerator char_from_code_generator_;

  DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
};

2100

2101
class LoadDictionaryElementStub : public HydrogenCodeStub {
danno@chromium.org's avatar
danno@chromium.org committed
2102
 public:
2103 2104 2105 2106
  explicit LoadDictionaryElementStub(Isolate* isolate, const LoadICState& state)
      : HydrogenCodeStub(isolate) {
    minor_key_ = state.GetExtraICState();
  }
danno@chromium.org's avatar
danno@chromium.org committed
2107

2108
  CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
2109
    return LoadWithVectorDescriptor(isolate());
2110 2111
  }

2112
  DEFINE_HYDROGEN_CODE_STUB(LoadDictionaryElement, HydrogenCodeStub);
2113 2114 2115
};


2116
class KeyedLoadGenericStub : public HydrogenCodeStub {
2117
 public:
2118 2119 2120 2121
  explicit KeyedLoadGenericStub(Isolate* isolate, const LoadICState& state)
      : HydrogenCodeStub(isolate) {
    minor_key_ = state.GetExtraICState();
  }
2122

2123 2124
  Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
  InlineCacheState GetICState() const override { return GENERIC; }
2125

2126
  DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
2127

2128
  DEFINE_HYDROGEN_CODE_STUB(KeyedLoadGeneric, HydrogenCodeStub);
2129 2130 2131
};


2132 2133
class LoadICTrampolineStub : public PlatformCodeStub {
 public:
2134
  LoadICTrampolineStub(Isolate* isolate, const LoadICState& state)
2135 2136 2137
      : PlatformCodeStub(isolate) {
    minor_key_ = state.GetExtraICState();
  }
2138

2139
  Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
2140

2141
  InlineCacheState GetICState() const final { return GENERIC; }
2142

2143
  ExtraICState GetExtraICState() const final {
2144
    return static_cast<ExtraICState>(minor_key_);
2145 2146
  }

2147
 protected:
2148 2149
  LoadICState state() const {
    return LoadICState(static_cast<ExtraICState>(minor_key_));
2150
  }
2151

2152
  DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
2153
  DEFINE_PLATFORM_CODE_STUB(LoadICTrampoline, PlatformCodeStub);
2154 2155 2156 2157 2158
};


class KeyedLoadICTrampolineStub : public LoadICTrampolineStub {
 public:
2159 2160
  explicit KeyedLoadICTrampolineStub(Isolate* isolate, const LoadICState& state)
      : LoadICTrampolineStub(isolate, state) {}
2161

2162
  Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
2163

2164
  DEFINE_PLATFORM_CODE_STUB(KeyedLoadICTrampoline, LoadICTrampolineStub);
2165 2166 2167
};


2168 2169 2170 2171 2172 2173 2174 2175 2176
class VectorStoreICTrampolineStub : public PlatformCodeStub {
 public:
  VectorStoreICTrampolineStub(Isolate* isolate, const StoreICState& state)
      : PlatformCodeStub(isolate) {
    minor_key_ = state.GetExtraICState();
  }

  Code::Kind GetCodeKind() const override { return Code::STORE_IC; }

2177
  InlineCacheState GetICState() const final { return GENERIC; }
2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205

  ExtraICState GetExtraICState() const final {
    return static_cast<ExtraICState>(minor_key_);
  }

 protected:
  StoreICState state() const {
    return StoreICState(static_cast<ExtraICState>(minor_key_));
  }

 private:
  DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorStoreICTrampoline);
  DEFINE_PLATFORM_CODE_STUB(VectorStoreICTrampoline, PlatformCodeStub);
};


class VectorKeyedStoreICTrampolineStub : public VectorStoreICTrampolineStub {
 public:
  VectorKeyedStoreICTrampolineStub(Isolate* isolate, const StoreICState& state)
      : VectorStoreICTrampolineStub(isolate, state) {}

  Code::Kind GetCodeKind() const override { return Code::KEYED_STORE_IC; }

  DEFINE_PLATFORM_CODE_STUB(VectorKeyedStoreICTrampoline,
                            VectorStoreICTrampolineStub);
};


2206 2207 2208 2209 2210 2211 2212
class CallICTrampolineStub : public PlatformCodeStub {
 public:
  CallICTrampolineStub(Isolate* isolate, const CallICState& state)
      : PlatformCodeStub(isolate) {
    minor_key_ = state.GetExtraICState();
  }

2213
  Code::Kind GetCodeKind() const override { return Code::CALL_IC; }
2214

2215
  InlineCacheState GetICState() const final { return GENERIC; }
2216

2217
  ExtraICState GetExtraICState() const final {
2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230
    return static_cast<ExtraICState>(minor_key_);
  }

 protected:
  CallICState state() const {
    return CallICState(static_cast<ExtraICState>(minor_key_));
  }

  DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunctionWithFeedback);
  DEFINE_PLATFORM_CODE_STUB(CallICTrampoline, PlatformCodeStub);
};


2231
class LoadICStub : public PlatformCodeStub {
2232
 public:
2233
  explicit LoadICStub(Isolate* isolate, const LoadICState& state)
2234 2235
      : PlatformCodeStub(isolate) {
    minor_key_ = state.GetExtraICState();
2236
  }
2237

2238
  void GenerateForTrampoline(MacroAssembler* masm);
2239

2240
  Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
2241
  InlineCacheState GetICState() const final { return GENERIC; }
2242
  ExtraICState GetExtraICState() const final {
2243 2244
    return static_cast<ExtraICState>(minor_key_);
  }
2245

2246 2247
  DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
  DEFINE_PLATFORM_CODE_STUB(LoadIC, PlatformCodeStub);
2248 2249 2250

 protected:
  void GenerateImpl(MacroAssembler* masm, bool in_frame);
2251 2252 2253
};


2254
class KeyedLoadICStub : public PlatformCodeStub {
2255
 public:
2256 2257 2258 2259
  explicit KeyedLoadICStub(Isolate* isolate, const LoadICState& state)
      : PlatformCodeStub(isolate) {
    minor_key_ = state.GetExtraICState();
  }
2260

2261 2262
  void GenerateForTrampoline(MacroAssembler* masm);

2263
  Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
2264
  InlineCacheState GetICState() const final { return GENERIC; }
2265 2266 2267
  ExtraICState GetExtraICState() const final {
    return static_cast<ExtraICState>(minor_key_);
  }
2268

2269 2270
  DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
  DEFINE_PLATFORM_CODE_STUB(KeyedLoadIC, PlatformCodeStub);
2271 2272 2273

 protected:
  void GenerateImpl(MacroAssembler* masm, bool in_frame);
2274 2275 2276
};


2277 2278 2279 2280 2281 2282 2283 2284 2285 2286
class VectorStoreICStub : public PlatformCodeStub {
 public:
  VectorStoreICStub(Isolate* isolate, const StoreICState& state)
      : PlatformCodeStub(isolate) {
    minor_key_ = state.GetExtraICState();
  }

  void GenerateForTrampoline(MacroAssembler* masm);

  Code::Kind GetCodeKind() const final { return Code::STORE_IC; }
2287
  InlineCacheState GetICState() const final { return GENERIC; }
2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309
  ExtraICState GetExtraICState() const final {
    return static_cast<ExtraICState>(minor_key_);
  }

  DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorStoreIC);
  DEFINE_PLATFORM_CODE_STUB(VectorStoreIC, PlatformCodeStub);

 protected:
  void GenerateImpl(MacroAssembler* masm, bool in_frame);
};


class VectorKeyedStoreICStub : public PlatformCodeStub {
 public:
  VectorKeyedStoreICStub(Isolate* isolate, const StoreICState& state)
      : PlatformCodeStub(isolate) {
    minor_key_ = state.GetExtraICState();
  }

  void GenerateForTrampoline(MacroAssembler* masm);

  Code::Kind GetCodeKind() const final { return Code::KEYED_STORE_IC; }
2310
  InlineCacheState GetICState() const final { return GENERIC; }
2311
  ExtraICState GetExtraICState() const final {
2312 2313
    return static_cast<ExtraICState>(minor_key_);
  }
2314 2315 2316 2317 2318 2319 2320 2321 2322

  DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorStoreIC);
  DEFINE_PLATFORM_CODE_STUB(VectorKeyedStoreIC, PlatformCodeStub);

 protected:
  void GenerateImpl(MacroAssembler* masm, bool in_frame);
};


2323 2324
class DoubleToIStub : public PlatformCodeStub {
 public:
2325 2326 2327 2328 2329 2330 2331 2332 2333
  DoubleToIStub(Isolate* isolate, Register source, Register destination,
                int offset, bool is_truncating, bool skip_fastpath = false)
      : PlatformCodeStub(isolate) {
    minor_key_ = SourceRegisterBits::encode(source.code()) |
                 DestinationRegisterBits::encode(destination.code()) |
                 OffsetBits::encode(offset) |
                 IsTruncatingBits::encode(is_truncating) |
                 SkipFastPathBits::encode(skip_fastpath) |
                 SSE3Bits::encode(CpuFeatures::IsSupported(SSE3) ? 1 : 0);
2334 2335
  }

2336
  bool SometimesSetsUpAFrame() override { return false; }
2337

2338 2339 2340
 private:
  Register source() const {
    return Register::from_code(SourceRegisterBits::decode(minor_key_));
2341
  }
2342 2343
  Register destination() const {
    return Register::from_code(DestinationRegisterBits::decode(minor_key_));
2344
  }
2345 2346 2347
  bool is_truncating() const { return IsTruncatingBits::decode(minor_key_); }
  bool skip_fastpath() const { return SkipFastPathBits::decode(minor_key_); }
  int offset() const { return OffsetBits::decode(minor_key_); }
2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359

  static const int kBitsPerRegisterNumber = 6;
  STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
  class SourceRegisterBits:
      public BitField<int, 0, kBitsPerRegisterNumber> {};  // NOLINT
  class DestinationRegisterBits:
      public BitField<int, kBitsPerRegisterNumber,
        kBitsPerRegisterNumber> {};  // NOLINT
  class IsTruncatingBits:
      public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {};  // NOLINT
  class OffsetBits:
      public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {};  // NOLINT
2360 2361
  class SkipFastPathBits:
      public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {};  // NOLINT
2362 2363
  class SSE3Bits:
      public BitField<int, 2 * kBitsPerRegisterNumber + 5, 1> {};  // NOLINT
2364

2365
  DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2366
  DEFINE_PLATFORM_CODE_STUB(DoubleToI, PlatformCodeStub);
2367 2368 2369
};


2370
class ScriptContextFieldStub : public HandlerStub {
2371
 public:
2372 2373
  ScriptContextFieldStub(Isolate* isolate,
                         const ScriptContextTable::LookupResult* lookup_result)
2374 2375
      : HandlerStub(isolate) {
    DCHECK(Accepted(lookup_result));
2376
    STATIC_ASSERT(kContextIndexBits + kSlotIndexBits <= kSubMinorKeyBits);
2377 2378 2379 2380 2381 2382 2383 2384 2385 2386
    set_sub_minor_key(ContextIndexBits::encode(lookup_result->context_index) |
                      SlotIndexBits::encode(lookup_result->slot_index));
  }

  int context_index() const {
    return ContextIndexBits::decode(sub_minor_key());
  }

  int slot_index() const { return SlotIndexBits::decode(sub_minor_key()); }

2387
  static bool Accepted(const ScriptContextTable::LookupResult* lookup_result) {
2388 2389 2390 2391 2392
    return ContextIndexBits::is_valid(lookup_result->context_index) &&
           SlotIndexBits::is_valid(lookup_result->slot_index);
  }

 private:
2393
  static const int kContextIndexBits = 9;
2394 2395 2396 2397 2398
  static const int kSlotIndexBits = 13;
  class ContextIndexBits : public BitField<int, 0, kContextIndexBits> {};
  class SlotIndexBits
      : public BitField<int, kContextIndexBits, kSlotIndexBits> {};

2399
  Code::StubType GetStubType() const override { return Code::FAST; }
2400

2401
  DEFINE_CODE_STUB_BASE(ScriptContextFieldStub, HandlerStub);
2402
};
2403 2404


2405
class LoadScriptContextFieldStub : public ScriptContextFieldStub {
2406
 public:
2407 2408 2409
  LoadScriptContextFieldStub(
      Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
      : ScriptContextFieldStub(isolate, lookup_result) {}
2410 2411

 private:
2412
  Code::Kind kind() const override { return Code::LOAD_IC; }
2413

2414
  DEFINE_HANDLER_CODE_STUB(LoadScriptContextField, ScriptContextFieldStub);
2415 2416 2417
};


2418
class StoreScriptContextFieldStub : public ScriptContextFieldStub {
2419
 public:
2420 2421 2422
  StoreScriptContextFieldStub(
      Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
      : ScriptContextFieldStub(isolate, lookup_result) {}
2423 2424

 private:
2425
  Code::Kind kind() const override { return Code::STORE_IC; }
2426

2427
  DEFINE_HANDLER_CODE_STUB(StoreScriptContextField, ScriptContextFieldStub);
2428 2429 2430
};


2431
class LoadFastElementStub : public HandlerStub {
2432
 public:
2433
  LoadFastElementStub(Isolate* isolate, bool is_js_array,
2434 2435
                      ElementsKind elements_kind,
                      bool convert_hole_to_undefined = false)
2436
      : HandlerStub(isolate) {
2437 2438 2439 2440
    set_sub_minor_key(
        ElementsKindBits::encode(elements_kind) |
        IsJSArrayBits::encode(is_js_array) |
        CanConvertHoleToUndefined::encode(convert_hole_to_undefined));
2441 2442
  }

2443 2444
  Code::Kind kind() const override { return Code::KEYED_LOAD_IC; }

2445
  bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2446 2447 2448
  bool convert_hole_to_undefined() const {
    return CanConvertHoleToUndefined::decode(sub_minor_key());
  }
2449 2450

  ElementsKind elements_kind() const {
2451
    return ElementsKindBits::decode(sub_minor_key());
2452 2453 2454 2455
  }

 private:
  class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2456
  class IsJSArrayBits: public BitField<bool, 8, 1> {};
2457
  class CanConvertHoleToUndefined : public BitField<bool, 9, 1> {};
2458

2459
  DEFINE_HANDLER_CODE_STUB(LoadFastElement, HandlerStub);
danno@chromium.org's avatar
danno@chromium.org committed
2460 2461 2462
};


2463
class StoreFastElementStub : public HydrogenCodeStub {
2464
 public:
2465 2466
  StoreFastElementStub(Isolate* isolate, bool is_js_array,
                       ElementsKind elements_kind, KeyedAccessStoreMode mode)
2467
      : HydrogenCodeStub(isolate) {
2468 2469 2470
    set_sub_minor_key(CommonStoreModeBits::encode(mode) |
                      ElementsKindBits::encode(elements_kind) |
                      IsJSArrayBits::encode(is_js_array));
2471 2472
  }

2473 2474
  static void GenerateAheadOfTime(Isolate* isolate);

2475
  bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2476 2477

  ElementsKind elements_kind() const {
2478
    return ElementsKindBits::decode(sub_minor_key());
2479 2480 2481
  }

  KeyedAccessStoreMode store_mode() const {
2482
    return CommonStoreModeBits::decode(sub_minor_key());
2483 2484
  }

2485
  CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
2486
    return VectorStoreICDescriptor(isolate());
2487 2488
  }

2489 2490
  Code::Kind GetCodeKind() const override { return Code::HANDLER; }

2491
 private:
2492 2493
  class ElementsKindBits : public BitField<ElementsKind, 3, 8> {};
  class IsJSArrayBits : public BitField<bool, 11, 1> {};
2494

2495
  DEFINE_HYDROGEN_CODE_STUB(StoreFastElement, HydrogenCodeStub);
2496 2497 2498
};


2499 2500
class TransitionElementsKindStub : public HydrogenCodeStub {
 public:
2501 2502
  TransitionElementsKindStub(Isolate* isolate,
                             ElementsKind from_kind,
2503
                             ElementsKind to_kind,
2504
                             bool is_js_array) : HydrogenCodeStub(isolate) {
2505 2506 2507
    set_sub_minor_key(FromKindBits::encode(from_kind) |
                      ToKindBits::encode(to_kind) |
                      IsJSArrayBits::encode(is_js_array));
2508 2509 2510
  }

  ElementsKind from_kind() const {
2511
    return FromKindBits::decode(sub_minor_key());
2512 2513
  }

2514
  ElementsKind to_kind() const { return ToKindBits::decode(sub_minor_key()); }
2515

2516
  bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2517

2518 2519 2520
 private:
  class FromKindBits: public BitField<ElementsKind, 8, 8> {};
  class ToKindBits: public BitField<ElementsKind, 0, 8> {};
2521
  class IsJSArrayBits: public BitField<bool, 16, 1> {};
2522

2523
  DEFINE_CALL_INTERFACE_DESCRIPTOR(TransitionElementsKind);
2524
  DEFINE_HYDROGEN_CODE_STUB(TransitionElementsKind, HydrogenCodeStub);
2525 2526
};

2527
class AllocateHeapNumberStub : public TurboFanCodeStub {
2528 2529
 public:
  explicit AllocateHeapNumberStub(Isolate* isolate)
2530 2531 2532 2533
      : TurboFanCodeStub(isolate) {}

  void InitializeDescriptor(CodeStubDescriptor* descriptor) override;
  void GenerateAssembly(compiler::CodeStubAssembler* assembler) const override;
2534 2535

  DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateHeapNumber);
2536
  DEFINE_CODE_STUB(AllocateHeapNumber, TurboFanCodeStub);
2537 2538
};

2539
class AllocateMutableHeapNumberStub : public TurboFanCodeStub {
2540 2541
 public:
  explicit AllocateMutableHeapNumberStub(Isolate* isolate)
2542 2543 2544 2545
      : TurboFanCodeStub(isolate) {}

  void InitializeDescriptor(CodeStubDescriptor* descriptor) override;
  void GenerateAssembly(compiler::CodeStubAssembler* assembler) const override;
2546 2547

  DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateMutableHeapNumber);
2548
  DEFINE_CODE_STUB(AllocateMutableHeapNumber, TurboFanCodeStub);
2549 2550 2551
};


2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562
class AllocateInNewSpaceStub final : public HydrogenCodeStub {
 public:
  explicit AllocateInNewSpaceStub(Isolate* isolate)
      : HydrogenCodeStub(isolate) {}

 private:
  DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateInNewSpace);
  DEFINE_HYDROGEN_CODE_STUB(AllocateInNewSpace, HydrogenCodeStub);
};


2563
class ArrayConstructorStubBase : public HydrogenCodeStub {
2564
 public:
2565 2566 2567 2568
  ArrayConstructorStubBase(Isolate* isolate,
                           ElementsKind kind,
                           AllocationSiteOverrideMode override_mode)
      : HydrogenCodeStub(isolate) {
2569 2570 2571
    // It only makes sense to override local allocation site behavior
    // if there is a difference between the global allocation site policy
    // for an ElementsKind and the desired usage of the stub.
2572
    DCHECK(override_mode != DISABLE_ALLOCATION_SITES ||
2573
           AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE);
2574 2575
    set_sub_minor_key(ElementsKindBits::encode(kind) |
                      AllocationSiteOverrideModeBits::encode(override_mode));
2576 2577 2578
  }

  ElementsKind elements_kind() const {
2579
    return ElementsKindBits::decode(sub_minor_key());
2580 2581
  }

2582
  AllocationSiteOverrideMode override_mode() const {
2583
    return AllocationSiteOverrideModeBits::decode(sub_minor_key());
2584 2585
  }

2586 2587 2588
  static void GenerateStubsAheadOfTime(Isolate* isolate);

  // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2589
  static const int kConstructor = 0;
2590
  static const int kAllocationSite = 1;
2591

2592
 protected:
2593 2594
  std::ostream& BasePrintName(std::ostream& os,
                              const char* name) const;  // NOLINT
2595

2596
 private:
2597 2598 2599
  // Ensure data fits within available bits.
  STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);

2600
  class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2601 2602
  class AllocationSiteOverrideModeBits: public
      BitField<AllocationSiteOverrideMode, 8, 1> {};  // NOLINT
2603

2604
  DEFINE_CODE_STUB_BASE(ArrayConstructorStubBase, HydrogenCodeStub);
2605 2606 2607 2608 2609 2610
};


class ArrayNoArgumentConstructorStub : public ArrayConstructorStubBase {
 public:
  ArrayNoArgumentConstructorStub(
2611
      Isolate* isolate,
2612
      ElementsKind kind,
2613
      AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2614
      : ArrayConstructorStubBase(isolate, kind, override_mode) {
2615 2616 2617
  }

 private:
2618
  void PrintName(std::ostream& os) const override {  // NOLINT
2619
    BasePrintName(os, "ArrayNoArgumentConstructorStub");
2620 2621
  }

2622
  DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructorConstantArgCount);
2623 2624
  DEFINE_HYDROGEN_CODE_STUB(ArrayNoArgumentConstructor,
                            ArrayConstructorStubBase);
2625 2626 2627
};


2628
class ArraySingleArgumentConstructorStub : public ArrayConstructorStubBase {
2629
 public:
2630
  ArraySingleArgumentConstructorStub(
2631
      Isolate* isolate,
2632
      ElementsKind kind,
2633
      AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2634
      : ArrayConstructorStubBase(isolate, kind, override_mode) {
2635
  }
2636 2637

 private:
2638
  void PrintName(std::ostream& os) const override {  // NOLINT
2639
    BasePrintName(os, "ArraySingleArgumentConstructorStub");
2640 2641
  }

2642
  DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
2643 2644
  DEFINE_HYDROGEN_CODE_STUB(ArraySingleArgumentConstructor,
                            ArrayConstructorStubBase);
2645 2646 2647
};


2648
class ArrayNArgumentsConstructorStub : public ArrayConstructorStubBase {
2649
 public:
2650
  ArrayNArgumentsConstructorStub(
2651
      Isolate* isolate,
2652
      ElementsKind kind,
2653
      AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2654
      : ArrayConstructorStubBase(isolate, kind, override_mode) {
2655
  }
2656 2657

 private:
2658
  void PrintName(std::ostream& os) const override {  // NOLINT
2659
    BasePrintName(os, "ArrayNArgumentsConstructorStub");
2660 2661
  }

2662
  DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
2663 2664
  DEFINE_HYDROGEN_CODE_STUB(ArrayNArgumentsConstructor,
                            ArrayConstructorStubBase);
2665 2666 2667
};


2668 2669
class InternalArrayConstructorStubBase : public HydrogenCodeStub {
 public:
2670 2671
  InternalArrayConstructorStubBase(Isolate* isolate, ElementsKind kind)
      : HydrogenCodeStub(isolate) {
2672
    set_sub_minor_key(ElementsKindBits::encode(kind));
2673 2674 2675 2676 2677 2678 2679
  }

  static void GenerateStubsAheadOfTime(Isolate* isolate);

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

2680 2681 2682
  ElementsKind elements_kind() const {
    return ElementsKindBits::decode(sub_minor_key());
  }
2683 2684

 private:
2685
  class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
2686

2687
  DEFINE_CODE_STUB_BASE(InternalArrayConstructorStubBase, HydrogenCodeStub);
2688 2689 2690 2691 2692 2693
};


class InternalArrayNoArgumentConstructorStub : public
    InternalArrayConstructorStubBase {
 public:
2694 2695 2696
  InternalArrayNoArgumentConstructorStub(Isolate* isolate,
                                         ElementsKind kind)
      : InternalArrayConstructorStubBase(isolate, kind) { }
2697

2698
  DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructorConstantArgCount);
2699 2700
  DEFINE_HYDROGEN_CODE_STUB(InternalArrayNoArgumentConstructor,
                            InternalArrayConstructorStubBase);
2701 2702 2703 2704 2705 2706
};


class InternalArraySingleArgumentConstructorStub : public
    InternalArrayConstructorStubBase {
 public:
2707 2708 2709
  InternalArraySingleArgumentConstructorStub(Isolate* isolate,
                                             ElementsKind kind)
      : InternalArrayConstructorStubBase(isolate, kind) { }
2710

2711
  DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
2712 2713
  DEFINE_HYDROGEN_CODE_STUB(InternalArraySingleArgumentConstructor,
                            InternalArrayConstructorStubBase);
2714 2715 2716 2717 2718 2719
};


class InternalArrayNArgumentsConstructorStub : public
    InternalArrayConstructorStubBase {
 public:
2720 2721
  InternalArrayNArgumentsConstructorStub(Isolate* isolate, ElementsKind kind)
      : InternalArrayConstructorStubBase(isolate, kind) { }
2722

2723
  DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
2724 2725
  DEFINE_HYDROGEN_CODE_STUB(InternalArrayNArgumentsConstructor,
                            InternalArrayConstructorStubBase);
2726 2727 2728
};


2729
class StoreElementStub : public PlatformCodeStub {
danno@chromium.org's avatar
danno@chromium.org committed
2730
 public:
2731 2732
  StoreElementStub(Isolate* isolate, ElementsKind elements_kind,
                   KeyedAccessStoreMode mode)
2733
      : PlatformCodeStub(isolate) {
2734 2735 2736
    // TODO(jkummerow): Rename this stub to StoreSlowElementStub,
    // drop elements_kind parameter.
    DCHECK_EQ(DICTIONARY_ELEMENTS, elements_kind);
2737 2738
    minor_key_ = ElementsKindBits::encode(elements_kind) |
                 CommonStoreModeBits::encode(mode);
2739
  }
danno@chromium.org's avatar
danno@chromium.org committed
2740

2741
  CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
2742
    return VectorStoreICDescriptor(isolate());
2743 2744
  }

2745 2746
  Code::Kind GetCodeKind() const override { return Code::HANDLER; }

2747
 private:
2748 2749 2750 2751
  ElementsKind elements_kind() const {
    return ElementsKindBits::decode(minor_key_);
  }

2752
  class ElementsKindBits : public BitField<ElementsKind, 3, 8> {};
2753

2754
  DEFINE_PLATFORM_CODE_STUB(StoreElement, PlatformCodeStub);
danno@chromium.org's avatar
danno@chromium.org committed
2755 2756
};

2757
class ToBooleanICStub : public HydrogenCodeStub {
2758
 public:
2759 2760 2761 2762 2763 2764 2765
  enum Type {
    UNDEFINED,
    BOOLEAN,
    NULL_TYPE,
    SMI,
    SPEC_OBJECT,
    STRING,
2766
    SYMBOL,
2767
    HEAP_NUMBER,
2768
    SIMD_VALUE,
2769 2770 2771
    NUMBER_OF_TYPES
  };

2772 2773 2774
  // At most 16 different types can be distinguished, because the Code object
  // only has room for two bytes to hold a set of these types. :-P
  STATIC_ASSERT(NUMBER_OF_TYPES <= 16);
2775

2776
  class Types : public EnumSet<Type, uint16_t> {
2777
   public:
2778 2779
    Types() : EnumSet<Type, uint16_t>(0) {}
    explicit Types(uint16_t bits) : EnumSet<Type, uint16_t>(bits) {}
2780

2781
    bool UpdateStatus(Handle<Object> object);
2782
    bool NeedsMap() const;
2783
    bool CanBeUndetectable() const {
2784
      return Contains(ToBooleanICStub::SPEC_OBJECT);
2785
    }
2786
    bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); }
2787

2788 2789
    static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); }
  };
2790

2791
  ToBooleanICStub(Isolate* isolate, ExtraICState state)
2792
      : HydrogenCodeStub(isolate) {
2793
    set_sub_minor_key(TypesBits::encode(static_cast<uint16_t>(state)));
2794
  }
2795

2796
  bool UpdateStatus(Handle<Object> object);
2797
  Types types() const { return Types(TypesBits::decode(sub_minor_key())); }
2798

2799 2800
  Code::Kind GetCodeKind() const override { return Code::TO_BOOLEAN_IC; }
  void PrintState(std::ostream& os) const override;  // NOLINT
2801

2802
  bool SometimesSetsUpAFrame() override { return false; }
2803

2804
  static Handle<Code> GetUninitialized(Isolate* isolate) {
2805
    return ToBooleanICStub(isolate, UNINITIALIZED).GetCode();
2806
  }
2807

2808
  ExtraICState GetExtraICState() const override { return types().ToIntegral(); }
2809

2810
  InlineCacheState GetICState() const override {
2811
    if (types().IsEmpty()) {
2812 2813 2814 2815 2816
      return ::v8::internal::UNINITIALIZED;
    } else {
      return MONOMORPHIC;
    }
  }
2817 2818

 private:
2819 2820
  ToBooleanICStub(Isolate* isolate, InitializationState init_state)
      : HydrogenCodeStub(isolate, init_state) {}
2821

2822
  class TypesBits : public BitField<uint16_t, 0, NUMBER_OF_TYPES> {};
2823

2824
  DEFINE_CALL_INTERFACE_DESCRIPTOR(ToBoolean);
2825
  DEFINE_HYDROGEN_CODE_STUB(ToBooleanIC, HydrogenCodeStub);
2826 2827
};

2828
std::ostream& operator<<(std::ostream& os, const ToBooleanICStub::Types& t);
2829

2830
class ElementsTransitionAndStoreStub : public HydrogenCodeStub {
2831
 public:
2832 2833
  ElementsTransitionAndStoreStub(Isolate* isolate, ElementsKind from_kind,
                                 ElementsKind to_kind, bool is_jsarray,
2834
                                 KeyedAccessStoreMode store_mode)
2835
      : HydrogenCodeStub(isolate) {
2836 2837 2838
    set_sub_minor_key(CommonStoreModeBits::encode(store_mode) |
                      FromBits::encode(from_kind) | ToBits::encode(to_kind) |
                      IsJSArrayBits::encode(is_jsarray));
2839
  }
2840

2841 2842 2843 2844
  ElementsKind from_kind() const { return FromBits::decode(sub_minor_key()); }
  ElementsKind to_kind() const { return ToBits::decode(sub_minor_key()); }
  bool is_jsarray() const { return IsJSArrayBits::decode(sub_minor_key()); }
  KeyedAccessStoreMode store_mode() const {
2845
    return CommonStoreModeBits::decode(sub_minor_key());
2846
  }
2847

2848
  CallInterfaceDescriptor GetCallInterfaceDescriptor() const override;
2849
  Code::Kind GetCodeKind() const override { return Code::HANDLER; }
2850

2851
 private:
2852 2853 2854
  class FromBits : public BitField<ElementsKind, 3, 8> {};
  class ToBits : public BitField<ElementsKind, 11, 8> {};
  class IsJSArrayBits : public BitField<bool, 19, 1> {};
2855

2856
  DEFINE_HYDROGEN_CODE_STUB(ElementsTransitionAndStore, HydrogenCodeStub);
2857 2858 2859
};


2860 2861
class StubFailureTrampolineStub : public PlatformCodeStub {
 public:
2862
  StubFailureTrampolineStub(Isolate* isolate, StubFunctionMode function_mode)
2863 2864 2865
      : PlatformCodeStub(isolate) {
    minor_key_ = FunctionModeField::encode(function_mode);
  }
2866

2867
  static void GenerateAheadOfTime(Isolate* isolate);
2868 2869

 private:
2870 2871
  StubFunctionMode function_mode() const {
    return FunctionModeField::decode(minor_key_);
2872
  }
2873

2874
  class FunctionModeField : public BitField<StubFunctionMode, 0, 1> {};
2875

2876
  DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2877
  DEFINE_PLATFORM_CODE_STUB(StubFailureTrampoline, PlatformCodeStub);
2878 2879 2880
};


2881
class ProfileEntryHookStub : public PlatformCodeStub {
2882
 public:
2883
  explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2884 2885

  // The profile entry hook function is not allowed to cause a GC.
2886
  bool SometimesSetsUpAFrame() override { return false; }
2887 2888 2889 2890 2891 2892

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

 private:
  static void EntryHookTrampoline(intptr_t function,
2893 2894
                                  intptr_t stack_pointer,
                                  Isolate* isolate);
2895

2896 2897 2898
  // ProfileEntryHookStub is called at the start of a function, so it has the
  // same register set.
  DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction)
2899
  DEFINE_PLATFORM_CODE_STUB(ProfileEntryHook, PlatformCodeStub);
2900 2901
};

2902

2903 2904 2905 2906 2907 2908 2909 2910
class StoreBufferOverflowStub : public PlatformCodeStub {
 public:
  StoreBufferOverflowStub(Isolate* isolate, SaveFPRegsMode save_fp)
      : PlatformCodeStub(isolate) {
    minor_key_ = SaveDoublesBits::encode(save_fp == kSaveFPRegs);
  }

  static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
2911
  bool SometimesSetsUpAFrame() override { return false; }
2912 2913 2914 2915 2916 2917

 private:
  bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }

  class SaveDoublesBits : public BitField<bool, 0, 1> {};

2918
  DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2919
  DEFINE_PLATFORM_CODE_STUB(StoreBufferOverflow, PlatformCodeStub);
2920 2921 2922 2923 2924 2925 2926
};


class SubStringStub : public PlatformCodeStub {
 public:
  explicit SubStringStub(Isolate* isolate) : PlatformCodeStub(isolate) {}

2927
  DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
2928
  DEFINE_PLATFORM_CODE_STUB(SubString, PlatformCodeStub);
2929 2930 2931
};


2932
class ToNumberStub final : public PlatformCodeStub {
2933 2934 2935 2936 2937 2938 2939 2940
 public:
  explicit ToNumberStub(Isolate* isolate) : PlatformCodeStub(isolate) {}

  DEFINE_CALL_INTERFACE_DESCRIPTOR(ToNumber);
  DEFINE_PLATFORM_CODE_STUB(ToNumber, PlatformCodeStub);
};


2941 2942 2943 2944 2945 2946 2947 2948 2949
class ToLengthStub final : public PlatformCodeStub {
 public:
  explicit ToLengthStub(Isolate* isolate) : PlatformCodeStub(isolate) {}

  DEFINE_CALL_INTERFACE_DESCRIPTOR(ToLength);
  DEFINE_PLATFORM_CODE_STUB(ToLength, PlatformCodeStub);
};


2950 2951 2952 2953 2954 2955 2956 2957 2958
class ToStringStub final : public PlatformCodeStub {
 public:
  explicit ToStringStub(Isolate* isolate) : PlatformCodeStub(isolate) {}

  DEFINE_CALL_INTERFACE_DESCRIPTOR(ToString);
  DEFINE_PLATFORM_CODE_STUB(ToString, PlatformCodeStub);
};


2959 2960 2961 2962 2963 2964 2965 2966 2967
class ToNameStub final : public PlatformCodeStub {
 public:
  explicit ToNameStub(Isolate* isolate) : PlatformCodeStub(isolate) {}

  DEFINE_CALL_INTERFACE_DESCRIPTOR(ToName);
  DEFINE_PLATFORM_CODE_STUB(ToName, PlatformCodeStub);
};


2968 2969 2970 2971 2972 2973 2974 2975
class ToObjectStub final : public HydrogenCodeStub {
 public:
  explicit ToObjectStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}

  DEFINE_CALL_INTERFACE_DESCRIPTOR(ToObject);
  DEFINE_HYDROGEN_CODE_STUB(ToObject, HydrogenCodeStub);
};

2976
#undef DEFINE_CALL_INTERFACE_DESCRIPTOR
2977 2978 2979
#undef DEFINE_PLATFORM_CODE_STUB
#undef DEFINE_HANDLER_CODE_STUB
#undef DEFINE_HYDROGEN_CODE_STUB
2980 2981
#undef DEFINE_CODE_STUB
#undef DEFINE_CODE_STUB_BASE
2982 2983

extern Representation RepresentationFromType(Type* type);
2984 2985 2986

}  // namespace internal
}  // namespace v8
2987 2988

#endif  // V8_CODE_STUBS_H_