code-stubs.h 40.5 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/factory.h"
12
#include "src/globals.h"
13
#include "src/interface-descriptors.h"
14
#include "src/macro-assembler.h"
15
#include "src/ostreams.h"
16
#include "src/type-hints.h"
17

18 19
namespace v8 {
namespace internal {
20

21 22 23 24 25 26 27
// Forward declarations.
class CodeStubAssembler;
namespace compiler {
class CodeAssemblerLabel;
class CodeAssemblerState;
class Node;
}
28

29
// List of code stubs used on all platforms.
30 31 32 33 34 35 36 37 38 39 40 41 42
#define CODE_STUB_LIST_ALL_PLATFORMS(V)       \
  /* --- PlatformCodeStubs --- */             \
  V(ArrayConstructor)                         \
  V(CallApiCallback)                          \
  V(CallApiGetter)                            \
  V(CEntry)                                   \
  V(DoubleToI)                                \
  V(InternalArrayConstructor)                 \
  V(JSEntry)                                  \
  V(MathPow)                                  \
  V(ProfileEntryHook)                         \
  V(RecordWrite)                              \
  V(StoreBufferOverflow)                      \
43
  V(StoreSlowElement)                         \
44 45 46 47 48 49 50 51 52 53
  V(SubString)                                \
  V(NameDictionaryLookup)                     \
  /* --- TurboFanCodeStubs --- */             \
  V(AllocateHeapNumber)                       \
  V(ArrayNoArgumentConstructor)               \
  V(ArraySingleArgumentConstructor)           \
  V(ArrayNArgumentsConstructor)               \
  V(StringLength)                             \
  V(InternalArrayNoArgumentConstructor)       \
  V(InternalArraySingleArgumentConstructor)   \
54
  V(ElementsTransitionAndStore)               \
55 56
  V(KeyedLoadSloppyArguments)                 \
  V(KeyedStoreSloppyArguments)                \
57 58
  V(LoadScriptContextField)                   \
  V(StoreScriptContextField)                  \
59
  V(NumberToString)                           \
60
  V(StringAdd)                                \
61
  V(GetProperty)                              \
62
  V(StoreFastElement)                         \
63
  V(StoreInterceptor)                         \
64
  V(TransitionElementsKind)                   \
65
  V(LoadIndexedInterceptor)                   \
66
  V(GrowArrayElements)
67

68 69
// List of code stubs only used on ARM 32 bits platforms.
#if V8_TARGET_ARCH_ARM
70
#define CODE_STUB_LIST_ARM(V) V(DirectCEntry)
71

72 73 74 75
#else
#define CODE_STUB_LIST_ARM(V)
#endif

76 77
// List of code stubs only used on ARM 64 bits platforms.
#if V8_TARGET_ARCH_ARM64
78
#define CODE_STUB_LIST_ARM64(V) V(DirectCEntry)
79

80 81 82 83
#else
#define CODE_STUB_LIST_ARM64(V)
#endif

84 85 86 87 88 89 90 91 92 93
// 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

94
// List of code stubs only used on MIPS platforms.
95
#if V8_TARGET_ARCH_MIPS
96 97 98 99
#define CODE_STUB_LIST_MIPS(V) \
  V(DirectCEntry)              \
  V(RestoreRegistersState)     \
  V(StoreRegistersState)
100
#elif V8_TARGET_ARCH_MIPS64
101 102 103 104
#define CODE_STUB_LIST_MIPS(V) \
  V(DirectCEntry)              \
  V(RestoreRegistersState)     \
  V(StoreRegistersState)
105 106 107 108
#else
#define CODE_STUB_LIST_MIPS(V)
#endif

109 110 111 112 113 114 115 116 117 118
// List of code stubs only used on S390 platforms.
#ifdef V8_TARGET_ARCH_S390
#define CODE_STUB_LIST_S390(V) \
  V(DirectCEntry)              \
  V(StoreRegistersState)       \
  V(RestoreRegistersState)
#else
#define CODE_STUB_LIST_S390(V)
#endif

119
// Combined list of code stubs.
120 121 122 123 124
#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)           \
125 126
  CODE_STUB_LIST_MIPS(V)          \
  CODE_STUB_LIST_S390(V)
127

128 129
static const int kHasReturnedMinusZeroSentinel = 1;

130
class CodeStub : public ZoneObject {
131 132
 public:
  enum Major {
133 134 135
    // TODO(mvstanton): eliminate the NoCache key by getting rid
    //                  of the non-monomorphic-cache.
    NoCache = 0,  // marker for stubs that do custom caching]
136 137 138
#define DEF_ENUM(name) name,
    CODE_STUB_LIST(DEF_ENUM)
#undef DEF_ENUM
139 140 141 142
    NUMBER_OF_IDS
  };

  // Retrieve the code for the stub. Generate the code if needed.
143
  Handle<Code> GetCode();
144 145 146

  static Major MajorKeyFromKey(uint32_t key) {
    return static_cast<Major>(MajorKeyBits::decode(key));
147
  }
148
  static uint32_t MinorKeyFromKey(uint32_t key) {
149
    return MinorKeyBits::decode(key);
150
  }
151 152 153

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

157 158
  static uint32_t NoCacheKey() { return MajorKeyBits::encode(NoCache); }

159
  static const char* MajorName(Major major_key);
160

161
  explicit CodeStub(Isolate* isolate) : minor_key_(0), isolate_(isolate) {}
162 163
  virtual ~CodeStub() {}

164 165
  static void GenerateStubsAheadOfTime(Isolate* isolate);
  static void GenerateFPStubs(Isolate* isolate);
166

167 168 169 170 171 172 173 174
  // 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; }

175
  // Lookup the code in the (possibly custom) cache.
176
  bool FindCodeInCache(Code** code_out);
177

178
  virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() const = 0;
179

180 181 182
  virtual int GetStackParameterCount() const {
    return GetCallInterfaceDescriptor().GetStackParameterCount();
  }
183

184
  virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) {}
185

186 187
  static void InitializeDescriptor(Isolate* isolate, uint32_t key,
                                   CodeStubDescriptor* desc);
188

189 190
  static MaybeHandle<Code> GetCode(Isolate* isolate, uint32_t key);

191
  // Returns information for computing the number key.
192
  virtual Major MajorKey() const = 0;
193
  uint32_t MinorKey() const { return minor_key_; }
194

195 196 197
  // BinaryOpStub needs to override this.
  virtual Code::Kind GetCodeKind() const;

198
  virtual ExtraICState GetExtraICState() const { return kNoExtraICState; }
199

200 201
  Code::Flags GetCodeFlags() const;

202
  friend std::ostream& operator<<(std::ostream& os, const CodeStub& s) {
203 204 205
    s.PrintName(os);
    return os;
  }
206

207
  Isolate* isolate() const { return isolate_; }
208 209 210 211 212
  void set_isolate(Isolate* isolate) {
    DCHECK_NOT_NULL(isolate);
    DCHECK(isolate_ == nullptr || isolate_ == isolate);
    isolate_ = isolate;
  }
213

214 215
  void DeleteStubFromCacheForTesting();

216
 protected:
217 218
  CodeStub(uint32_t key, Isolate* isolate)
      : minor_key_(MinorKeyFromKey(key)), isolate_(isolate) {}
219

220
  // Generates the assembler code for the stub.
221
  virtual Handle<Code> GenerateCode() = 0;
222

223 224 225 226
  // Returns whether the code generated for this stub needs to be allocated as
  // a fixed (non-moveable) code object.
  virtual bool NeedsImmovableCode() { return false; }

227 228 229
  virtual void PrintName(std::ostream& os) const;        // NOLINT
  virtual void PrintBaseName(std::ostream& os) const;    // NOLINT
  virtual void PrintState(std::ostream& os) const { ; }  // NOLINT
230

231 232
  // Computes the key based on major and minor.
  uint32_t GetKey() {
233
    DCHECK(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
234 235 236
    return MinorKeyBits::encode(MinorKey()) | MajorKeyBits::encode(MajorKey());
  }

237 238
  uint32_t minor_key_;

239
 private:
240 241
  // Perform bookkeeping required after code generation when stub code is
  // initially generated.
242
  void RecordCodeGeneration(Handle<Code> code);
243

244
  // Finish the code object after it has been generated.
245
  virtual void FinishCode(Handle<Code> code) { }
246

247 248 249 250
  // Activate newly generated stub. Is called after
  // registering stub in the stub cache.
  virtual void Activate(Code* code) { }

251 252 253 254 255 256
  // 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.
257
  virtual bool FindCodeInSpecialCache(Code** code_out) {
258 259
    return false;
  }
260 261 262 263

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

264 265 266 267 268 269
  // 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);

270 271
  static void GetCodeDispatchCall(CodeStub* stub, void** value_out);

272
  STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits));
273 274 275
  class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
  class MinorKeyBits: public BitField<uint32_t,
      kStubMajorKeyBits, kStubMinorKeyBits> {};  // NOLINT
276 277

  friend class BreakPointIterator;
278 279

  Isolate* isolate_;
280 281
};

282

283 284 285 286 287 288 289 290
#define DEFINE_CODE_STUB_BASE(NAME, SUPER)                      \
 public:                                                        \
  NAME(uint32_t key, Isolate* isolate) : SUPER(key, isolate) {} \
                                                                \
 private:                                                       \
  DISALLOW_COPY_AND_ASSIGN(NAME)


291
#define DEFINE_CODE_STUB(NAME, SUPER)                      \
292
 public:                                                   \
293
  inline Major MajorKey() const override { return NAME; }; \
294
                                                           \
295 296 297
  DEFINE_CODE_STUB_BASE(NAME##Stub, SUPER)


298 299
#define DEFINE_PLATFORM_CODE_STUB(NAME, SUPER)  \
 private:                                       \
300
  void Generate(MacroAssembler* masm) override; \
301 302 303
  DEFINE_CODE_STUB(NAME, SUPER)


304 305 306
#define DEFINE_TURBOFAN_CODE_STUB(NAME, SUPER)                               \
 public:                                                                     \
  void GenerateAssembly(compiler::CodeAssemblerState* state) const override; \
307 308
  DEFINE_CODE_STUB(NAME, SUPER)

309 310
#define DEFINE_HANDLER_CODE_STUB(NAME, SUPER) \
 public:                                      \
311
  Handle<Code> GenerateCode() override;       \
312 313
  DEFINE_CODE_STUB(NAME, SUPER)

314 315
#define DEFINE_CALL_INTERFACE_DESCRIPTOR(NAME)                          \
 public:                                                                \
316
  typedef NAME##Descriptor Descriptor;                                  \
317
  CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
318
    return Descriptor(isolate());                                       \
319 320
  }

321 322 323
// 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.
324 325 326 327 328
#define DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR()                         \
 public:                                                                \
  CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
    UNREACHABLE();                                                      \
    return CallInterfaceDescriptor();                                   \
329 330
  }

331

332 333 334
class PlatformCodeStub : public CodeStub {
 public:
  // Retrieve the code for the stub. Generate the code if needed.
335
  Handle<Code> GenerateCode() override;
336 337

 protected:
338 339
  explicit PlatformCodeStub(Isolate* isolate) : CodeStub(isolate) {}

340 341
  // Generates the assembler code for the stub.
  virtual void Generate(MacroAssembler* masm) = 0;
342

343
  DEFINE_CODE_STUB_BASE(PlatformCodeStub, CodeStub);
344 345 346
};


347
enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
348

349

350
class CodeStubDescriptor {
351
 public:
352
  explicit CodeStubDescriptor(CodeStub* stub);
353

354
  CodeStubDescriptor(Isolate* isolate, uint32_t stub_key);
355

356
  void Initialize(Address deoptimization_handler = NULL,
357 358
                  int hint_stack_parameter_count = -1,
                  StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
359
  void Initialize(Register stack_parameter_count,
360 361
                  Address deoptimization_handler = NULL,
                  int hint_stack_parameter_count = -1,
362
                  StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
363

364 365 366
  void SetMissHandler(Runtime::FunctionId id) {
    miss_handler_id_ = id;
    miss_handler_ = ExternalReference(Runtime::FunctionForId(id), isolate_);
367
    has_miss_handler_ = true;
368 369
    // Our miss handler infrastructure doesn't currently support
    // variable stack parameter counts.
370
    DCHECK(!stack_parameter_count_.is_valid());
371 372
  }

373
  void set_call_descriptor(CallInterfaceDescriptor d) { call_descriptor_ = d; }
374
  CallInterfaceDescriptor call_descriptor() const { return call_descriptor_; }
375

376 377
  int GetRegisterParameterCount() const {
    return call_descriptor().GetRegisterParameterCount();
378 379
  }

380 381 382 383 384 385 386 387
  int GetStackParameterCount() const {
    return call_descriptor().GetStackParameterCount();
  }

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

388 389 390 391
  Register GetRegisterParameter(int index) const {
    return call_descriptor().GetRegisterParameter(index);
  }

392
  MachineType GetParameterType(int index) const {
393
    return call_descriptor().GetParameterType(index);
394 395
  }

396
  ExternalReference miss_handler() const {
397
    DCHECK(has_miss_handler_);
398 399 400
    return miss_handler_;
  }

401 402 403 404 405
  Runtime::FunctionId miss_handler_id() const {
    DCHECK(has_miss_handler_);
    return miss_handler_id_;
  }

406
  bool has_miss_handler() const {
407 408 409
    return has_miss_handler_;
  }

410
  int GetHandlerParameterCount() const {
411 412
    int params = GetParameterCount();
    if (PassesArgumentsToDeoptimizationHandler()) {
413 414 415 416 417
      params += 1;
    }
    return params;
  }

418 419 420 421 422
  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_; }

423
 private:
424 425 426 427
  bool PassesArgumentsToDeoptimizationHandler() const {
    return stack_parameter_count_.is_valid();
  }

428
  Isolate* isolate_;
429
  CallInterfaceDescriptor call_descriptor_;
430 431 432 433 434 435 436 437
  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_;

438
  ExternalReference miss_handler_;
439
  Runtime::FunctionId miss_handler_id_;
440
  bool has_miss_handler_;
441 442 443
};


444 445 446 447 448
class TurboFanCodeStub : public CodeStub {
 public:
  // Retrieve the code for the stub. Generate the code if needed.
  Handle<Code> GenerateCode() override;

449
  int GetStackParameterCount() const override {
450 451 452
    return GetCallInterfaceDescriptor().GetStackParameterCount();
  }

453 454 455
 protected:
  explicit TurboFanCodeStub(Isolate* isolate) : CodeStub(isolate) {}

456
  virtual void GenerateAssembly(compiler::CodeAssemblerState* state) const = 0;
457 458

 private:
459
  DEFINE_CODE_STUB_BASE(TurboFanCodeStub, CodeStub);
460 461
};

462 463
}  // namespace internal
}  // namespace v8
464 465

#if V8_TARGET_ARCH_IA32
466
#include "src/ia32/code-stubs-ia32.h"
467
#elif V8_TARGET_ARCH_X64
468
#include "src/x64/code-stubs-x64.h"
469
#elif V8_TARGET_ARCH_ARM64
470
#include "src/arm64/code-stubs-arm64.h"
471
#elif V8_TARGET_ARCH_ARM
472
#include "src/arm/code-stubs-arm.h"
473 474
#elif V8_TARGET_ARCH_PPC
#include "src/ppc/code-stubs-ppc.h"
475
#elif V8_TARGET_ARCH_MIPS
476
#include "src/mips/code-stubs-mips.h"
477 478
#elif V8_TARGET_ARCH_MIPS64
#include "src/mips64/code-stubs-mips64.h"
479 480
#elif V8_TARGET_ARCH_S390
#include "src/s390/code-stubs-s390.h"
481 482 483 484 485 486 487
#else
#error Unsupported target architecture.
#endif

namespace v8 {
namespace internal {

488
class StringLengthStub : public TurboFanCodeStub {
489
 public:
490
  explicit StringLengthStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
491

492 493
  Code::Kind GetCodeKind() const override { return Code::HANDLER; }
  ExtraICState GetExtraICState() const override { return Code::LOAD_IC; }
494 495

  DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
496 497 498
  DEFINE_TURBOFAN_CODE_STUB(StringLength, TurboFanCodeStub);
};

499 500 501 502 503
class StoreInterceptorStub : public TurboFanCodeStub {
 public:
  explicit StoreInterceptorStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}

  Code::Kind GetCodeKind() const override { return Code::HANDLER; }
504
  ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
505

506
  DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
507
  DEFINE_TURBOFAN_CODE_STUB(StoreInterceptor, TurboFanCodeStub);
508 509
};

510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540
class TransitionElementsKindStub : public TurboFanCodeStub {
 public:
  TransitionElementsKindStub(Isolate* isolate, ElementsKind from_kind,
                             ElementsKind to_kind, bool is_jsarray)
      : TurboFanCodeStub(isolate) {
    set_sub_minor_key(FromKindBits::encode(from_kind) |
                      ToKindBits::encode(to_kind) |
                      IsJSArrayBits::encode(is_jsarray));
  }

  void set_sub_minor_key(uint32_t key) { minor_key_ = key; }

  uint32_t sub_minor_key() const { return minor_key_; }

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

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

  bool is_jsarray() const { return IsJSArrayBits::decode(sub_minor_key()); }

 private:
  class ToKindBits : public BitField<ElementsKind, 0, 8> {};
  class FromKindBits : public BitField<ElementsKind, ToKindBits::kNext, 8> {};
  class IsJSArrayBits : public BitField<bool, FromKindBits::kNext, 1> {};

  DEFINE_CALL_INTERFACE_DESCRIPTOR(TransitionElementsKind);
  DEFINE_TURBOFAN_CODE_STUB(TransitionElementsKind, TurboFanCodeStub);
};

541 542 543 544 545 546
class LoadIndexedInterceptorStub : public TurboFanCodeStub {
 public:
  explicit LoadIndexedInterceptorStub(Isolate* isolate)
      : TurboFanCodeStub(isolate) {}

  Code::Kind GetCodeKind() const override { return Code::HANDLER; }
547
  ExtraICState GetExtraICState() const override { return Code::KEYED_LOAD_IC; }
548 549 550 551 552

  DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
  DEFINE_TURBOFAN_CODE_STUB(LoadIndexedInterceptor, TurboFanCodeStub);
};

553 554 555 556 557 558 559 560 561
// ES6 [[Get]] operation.
class GetPropertyStub : public TurboFanCodeStub {
 public:
  explicit GetPropertyStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}

  DEFINE_CALL_INTERFACE_DESCRIPTOR(GetProperty);
  DEFINE_TURBOFAN_CODE_STUB(GetProperty, TurboFanCodeStub);
};

562
class NumberToStringStub final : public TurboFanCodeStub {
563
 public:
564
  explicit NumberToStringStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
565

566
  DEFINE_CALL_INTERFACE_DESCRIPTOR(TypeConversion);
567
  DEFINE_TURBOFAN_CODE_STUB(NumberToString, TurboFanCodeStub);
568 569
};

570
class GrowArrayElementsStub : public TurboFanCodeStub {
571
 public:
572 573 574
  GrowArrayElementsStub(Isolate* isolate, ElementsKind kind)
      : TurboFanCodeStub(isolate) {
    minor_key_ = ElementsKindBits::encode(GetHoleyElementsKind(kind));
575 576 577
  }

  ElementsKind elements_kind() const {
578
    return ElementsKindBits::decode(minor_key_);
579 580 581 582 583 584
  }

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

  DEFINE_CALL_INTERFACE_DESCRIPTOR(GrowArrayElements);
585
  DEFINE_TURBOFAN_CODE_STUB(GrowArrayElements, TurboFanCodeStub);
586 587
};

588 589 590 591 592 593 594
enum AllocationSiteOverrideMode {
  DONT_OVERRIDE,
  DISABLE_ALLOCATION_SITES,
  LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
};


595 596 597 598 599
class ArrayConstructorStub: public PlatformCodeStub {
 public:
  explicit ArrayConstructorStub(Isolate* isolate);

 private:
600 601
  void GenerateDispatchToArrayStub(MacroAssembler* masm,
                                   AllocationSiteOverrideMode mode);
602

603
  DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
604
  DEFINE_PLATFORM_CODE_STUB(ArrayConstructor, PlatformCodeStub);
605 606 607
};


608 609 610 611 612 613
class InternalArrayConstructorStub: public PlatformCodeStub {
 public:
  explicit InternalArrayConstructorStub(Isolate* isolate);

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

615
  DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNArgumentsConstructor);
616
  DEFINE_PLATFORM_CODE_STUB(InternalArrayConstructor, PlatformCodeStub);
617 618 619
};


620
class MathPowStub: public PlatformCodeStub {
621
 public:
622
  enum ExponentType { INTEGER, DOUBLE, TAGGED };
623

624
  MathPowStub(Isolate* isolate, ExponentType exponent_type)
625 626 627 628
      : PlatformCodeStub(isolate) {
    minor_key_ = ExponentTypeBits::encode(exponent_type);
  }

629
  CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
630
    if (exponent_type() == TAGGED) {
631 632 633
      return MathPowTaggedDescriptor(isolate());
    } else if (exponent_type() == INTEGER) {
      return MathPowIntegerDescriptor(isolate());
634 635 636 637
    } else {
      // A CallInterfaceDescriptor doesn't specify double registers (yet).
      DCHECK_EQ(DOUBLE, exponent_type());
      return ContextOnlyDescriptor(isolate());
638 639 640
    }
  }

641
 private:
642 643 644 645 646 647
  ExponentType exponent_type() const {
    return ExponentTypeBits::decode(minor_key_);
  }

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

648
  DEFINE_PLATFORM_CODE_STUB(MathPow, PlatformCodeStub);
649 650
};

651
class KeyedLoadSloppyArgumentsStub : public TurboFanCodeStub {
652 653
 public:
  explicit KeyedLoadSloppyArgumentsStub(Isolate* isolate)
654
      : TurboFanCodeStub(isolate) {}
655

656 657
  Code::Kind GetCodeKind() const override { return Code::HANDLER; }
  ExtraICState GetExtraICState() const override { return Code::LOAD_IC; }
658

659
 protected:
660
  DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
661
  DEFINE_TURBOFAN_CODE_STUB(KeyedLoadSloppyArguments, TurboFanCodeStub);
662 663 664
};


665 666
class CommonStoreModeBits : public BitField<KeyedAccessStoreMode, 0, 3> {};

667
class KeyedStoreSloppyArgumentsStub : public TurboFanCodeStub {
668
 public:
669 670
  explicit KeyedStoreSloppyArgumentsStub(Isolate* isolate,
                                         KeyedAccessStoreMode mode)
671 672
      : TurboFanCodeStub(isolate) {
    minor_key_ = CommonStoreModeBits::encode(mode);
673
  }
674

675 676
  Code::Kind GetCodeKind() const override { return Code::HANDLER; }
  ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
677

678
 protected:
679
  DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
680
  DEFINE_TURBOFAN_CODE_STUB(KeyedStoreSloppyArguments, TurboFanCodeStub);
681 682
};

vogelheim's avatar
vogelheim committed
683
class CallApiCallbackStub : public PlatformCodeStub {
684
 public:
vogelheim's avatar
vogelheim committed
685 686
  static const int kArgBits = 3;
  static const int kArgMax = (1 << kArgBits) - 1;
687

vogelheim's avatar
vogelheim committed
688
  // CallApiCallbackStub for regular setters and getters.
689 690
  CallApiCallbackStub(Isolate* isolate, bool is_store, bool is_lazy)
      : CallApiCallbackStub(isolate, is_store ? 1 : 0, is_store, is_lazy) {}
691

vogelheim's avatar
vogelheim committed
692
  // CallApiCallbackStub for callback functions.
693 694
  CallApiCallbackStub(Isolate* isolate, int argc, bool is_lazy)
      : CallApiCallbackStub(isolate, argc, false, is_lazy) {}
695

vogelheim's avatar
vogelheim committed
696
 private:
697
  CallApiCallbackStub(Isolate* isolate, int argc, bool is_store, bool is_lazy)
698
      : PlatformCodeStub(isolate) {
vogelheim's avatar
vogelheim committed
699
    CHECK(0 <= argc && argc <= kArgMax);
700
    minor_key_ = IsStoreBits::encode(is_store) |
vogelheim's avatar
vogelheim committed
701
                 ArgumentBits::encode(argc) |
702
                 IsLazyAccessorBits::encode(is_lazy);
703 704
  }

705
  bool is_store() const { return IsStoreBits::decode(minor_key_); }
706
  bool is_lazy() const { return IsLazyAccessorBits::decode(minor_key_); }
707
  int argc() const { return ArgumentBits::decode(minor_key_); }
708

709
  class IsStoreBits: public BitField<bool, 0, 1> {};
710
  class IsLazyAccessorBits : public BitField<bool, 1, 1> {};
711
  class ArgumentBits : public BitField<int, 2, kArgBits> {};
712

713
  DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiCallback);
vogelheim's avatar
vogelheim committed
714
  DEFINE_PLATFORM_CODE_STUB(CallApiCallback, PlatformCodeStub);
715 716 717
};


dcarney@chromium.org's avatar
dcarney@chromium.org committed
718 719
class CallApiGetterStub : public PlatformCodeStub {
 public:
720
  explicit CallApiGetterStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
dcarney@chromium.org's avatar
dcarney@chromium.org committed
721

722
  DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiGetter);
723
  DEFINE_PLATFORM_CODE_STUB(CallApiGetter, PlatformCodeStub);
dcarney@chromium.org's avatar
dcarney@chromium.org committed
724
};
725 726


727
class StringAddStub final : public TurboFanCodeStub {
728
 public:
729
  StringAddStub(Isolate* isolate, StringAddFlags flags,
730
                PretenureFlag pretenure_flag)
731 732 733
      : TurboFanCodeStub(isolate) {
    minor_key_ = (StringAddFlagsBits::encode(flags) |
                  PretenureFlagBits::encode(pretenure_flag));
734
  }
735 736

  StringAddFlags flags() const {
737
    return StringAddFlagsBits::decode(minor_key_);
738 739 740
  }

  PretenureFlag pretenure_flag() const {
741
    return PretenureFlagBits::decode(minor_key_);
742 743 744
  }

 private:
745 746
  class StringAddFlagsBits : public BitField<StringAddFlags, 0, 3> {};
  class PretenureFlagBits : public BitField<PretenureFlag, 3, 1> {};
747

748
  void PrintBaseName(std::ostream& os) const override;  // NOLINT
749

750
  DEFINE_CALL_INTERFACE_DESCRIPTOR(StringAdd);
751
  DEFINE_TURBOFAN_CODE_STUB(StringAdd, TurboFanCodeStub);
752 753 754
};


755
class CEntryStub : public PlatformCodeStub {
756
 public:
757
  CEntryStub(Isolate* isolate, int result_size,
758
             SaveFPRegsMode save_doubles = kDontSaveFPRegs,
759
             ArgvMode argv_mode = kArgvOnStack, bool builtin_exit_frame = false)
760
      : PlatformCodeStub(isolate) {
761
    minor_key_ = SaveDoublesBits::encode(save_doubles == kSaveFPRegs) |
762
                 FrameTypeBits::encode(builtin_exit_frame) |
763
                 ArgvMode::encode(argv_mode == kArgvInRegister);
764
    DCHECK(result_size == 1 || result_size == 2 || result_size == 3);
765 766
    minor_key_ = ResultSizeBits::update(minor_key_, result_size);
  }
767

768 769
  // 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
770 771
  // their code generation.  On machines that always have gp registers (x64) we
  // can generate both variants ahead of time.
772
  static void GenerateAheadOfTime(Isolate* isolate);
773

774
 private:
775
  bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
776
  bool argv_in_register() const { return ArgvMode::decode(minor_key_); }
777
  bool is_builtin_exit() const { return FrameTypeBits::decode(minor_key_); }
778
  int result_size() const { return ResultSizeBits::decode(minor_key_); }
779

780
  bool NeedsImmovableCode() override;
781 782

  class SaveDoublesBits : public BitField<bool, 0, 1> {};
783
  class ArgvMode : public BitField<bool, 1, 1> {};
784 785
  class FrameTypeBits : public BitField<bool, 2, 1> {};
  class ResultSizeBits : public BitField<int, 3, 3> {};
786

787
  DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
788
  DEFINE_PLATFORM_CODE_STUB(CEntry, PlatformCodeStub);
789 790 791
};


792
class JSEntryStub : public PlatformCodeStub {
793
 public:
794 795
  JSEntryStub(Isolate* isolate, StackFrame::Type type)
      : PlatformCodeStub(isolate) {
796
    DCHECK(type == StackFrame::ENTRY || type == StackFrame::CONSTRUCT_ENTRY);
797 798
    minor_key_ = StackFrameTypeBits::encode(type);
  }
799 800

 private:
801
  void FinishCode(Handle<Code> code) override;
802

803
  void PrintName(std::ostream& os) const override {  // NOLINT
804 805 806
    os << (type() == StackFrame::ENTRY ? "JSEntryStub"
                                       : "JSConstructEntryStub");
  }
807

808 809 810
  StackFrame::Type type() const {
    return StackFrameTypeBits::decode(minor_key_);
  }
811

812
  class StackFrameTypeBits : public BitField<StackFrame::Type, 0, 5> {};
813

814
  int handler_offset_;
815

816
  DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
817
  DEFINE_PLATFORM_CODE_STUB(JSEntry, PlatformCodeStub);
818 819
};

820

821 822 823 824 825 826 827 828 829
enum ReceiverCheckMode {
  // We don't know anything about the receiver.
  RECEIVER_IS_UNKNOWN,

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


830 831 832 833 834 835 836 837
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
};

838 839
class DoubleToIStub : public PlatformCodeStub {
 public:
840 841 842 843 844 845 846 847 848
  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);
849 850
  }

851
  bool SometimesSetsUpAFrame() override { return false; }
852

853 854 855
 private:
  Register source() const {
    return Register::from_code(SourceRegisterBits::decode(minor_key_));
856
  }
857 858
  Register destination() const {
    return Register::from_code(DestinationRegisterBits::decode(minor_key_));
859
  }
860 861 862
  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_); }
863 864 865 866 867 868 869 870 871 872 873 874

  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
875 876
  class SkipFastPathBits:
      public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {};  // NOLINT
877 878
  class SSE3Bits:
      public BitField<int, 2 * kBitsPerRegisterNumber + 5, 1> {};  // NOLINT
879

880
  DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
881
  DEFINE_PLATFORM_CODE_STUB(DoubleToI, PlatformCodeStub);
882 883
};

884
class ScriptContextFieldStub : public TurboFanCodeStub {
885
 public:
886 887
  ScriptContextFieldStub(Isolate* isolate,
                         const ScriptContextTable::LookupResult* lookup_result)
888
      : TurboFanCodeStub(isolate) {
889
    DCHECK(Accepted(lookup_result));
890 891
    minor_key_ = ContextIndexBits::encode(lookup_result->context_index) |
                 SlotIndexBits::encode(lookup_result->slot_index);
892 893
  }

894
  Code::Kind GetCodeKind() const override { return Code::HANDLER; }
895

896 897 898
  int context_index() const { return ContextIndexBits::decode(minor_key_); }

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

900
  static bool Accepted(const ScriptContextTable::LookupResult* lookup_result) {
901 902 903 904 905
    return ContextIndexBits::is_valid(lookup_result->context_index) &&
           SlotIndexBits::is_valid(lookup_result->slot_index);
  }

 private:
906
  static const int kContextIndexBits = 9;
907
  static const int kSlotIndexBits = 12;
908 909 910 911
  class ContextIndexBits : public BitField<int, 0, kContextIndexBits> {};
  class SlotIndexBits
      : public BitField<int, kContextIndexBits, kSlotIndexBits> {};

912
  DEFINE_CODE_STUB_BASE(ScriptContextFieldStub, TurboFanCodeStub);
913
};
914 915


916
class LoadScriptContextFieldStub : public ScriptContextFieldStub {
917
 public:
918 919 920
  LoadScriptContextFieldStub(
      Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
      : ScriptContextFieldStub(isolate, lookup_result) {}
921

922
  ExtraICState GetExtraICState() const override { return Code::LOAD_IC; }
923

924
 private:
925
  DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
926
  DEFINE_TURBOFAN_CODE_STUB(LoadScriptContextField, ScriptContextFieldStub);
927 928 929
};


930
class StoreScriptContextFieldStub : public ScriptContextFieldStub {
931
 public:
932 933 934
  StoreScriptContextFieldStub(
      Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
      : ScriptContextFieldStub(isolate, lookup_result) {}
935

936
  ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
937

938
 private:
939
  DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
940
  DEFINE_TURBOFAN_CODE_STUB(StoreScriptContextField, ScriptContextFieldStub);
941 942
};

943
class StoreFastElementStub : public TurboFanCodeStub {
944
 public:
945 946
  StoreFastElementStub(Isolate* isolate, bool is_js_array,
                       ElementsKind elements_kind, KeyedAccessStoreMode mode)
947 948 949 950
      : TurboFanCodeStub(isolate) {
    minor_key_ = CommonStoreModeBits::encode(mode) |
                 ElementsKindBits::encode(elements_kind) |
                 IsJSArrayBits::encode(is_js_array);
951 952
  }

953 954
  static void GenerateAheadOfTime(Isolate* isolate);

955
  bool is_js_array() const { return IsJSArrayBits::decode(minor_key_); }
956 957

  ElementsKind elements_kind() const {
958
    return ElementsKindBits::decode(minor_key_);
959 960 961
  }

  KeyedAccessStoreMode store_mode() const {
962
    return CommonStoreModeBits::decode(minor_key_);
963 964
  }

965
  Code::Kind GetCodeKind() const override { return Code::HANDLER; }
966
  ExtraICState GetExtraICState() const override { return Code::KEYED_STORE_IC; }
967

968
 private:
969 970 971
  class ElementsKindBits
      : public BitField<ElementsKind, CommonStoreModeBits::kNext, 8> {};
  class IsJSArrayBits : public BitField<bool, ElementsKindBits::kNext, 1> {};
972

973
  DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
974
  DEFINE_TURBOFAN_CODE_STUB(StoreFastElement, TurboFanCodeStub);
975 976 977
};


978
class AllocateHeapNumberStub : public TurboFanCodeStub {
979 980
 public:
  explicit AllocateHeapNumberStub(Isolate* isolate)
981 982 983
      : TurboFanCodeStub(isolate) {}

  void InitializeDescriptor(CodeStubDescriptor* descriptor) override;
984 985

  DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateHeapNumber);
986 987 988
  DEFINE_TURBOFAN_CODE_STUB(AllocateHeapNumber, TurboFanCodeStub);
};

989 990 991 992
class CommonArrayConstructorStub : public TurboFanCodeStub {
 protected:
  CommonArrayConstructorStub(Isolate* isolate, ElementsKind kind,
                             AllocationSiteOverrideMode override_mode)
993 994 995 996 997
      : TurboFanCodeStub(isolate) {
    // 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.
    DCHECK(override_mode != DISABLE_ALLOCATION_SITES ||
998
           AllocationSite::ShouldTrack(kind));
999 1000 1001 1002 1003 1004 1005 1006
    set_sub_minor_key(ElementsKindBits::encode(kind) |
                      AllocationSiteOverrideModeBits::encode(override_mode));
  }

  void set_sub_minor_key(uint32_t key) { minor_key_ = key; }

  uint32_t sub_minor_key() const { return minor_key_; }

1007 1008 1009 1010
  CommonArrayConstructorStub(uint32_t key, Isolate* isolate)
      : TurboFanCodeStub(key, isolate) {}

 public:
1011 1012 1013 1014 1015 1016
  ElementsKind elements_kind() const {
    return ElementsKindBits::decode(sub_minor_key());
  }

  AllocationSiteOverrideMode override_mode() const {
    return AllocationSiteOverrideModeBits::decode(sub_minor_key());
1017 1018
  }

1019 1020
  static void GenerateStubsAheadOfTime(Isolate* isolate);

1021
 private:
1022 1023
  // Ensure data fits within available bits.
  STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
1024

1025 1026 1027
  class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
  class AllocationSiteOverrideModeBits
      : public BitField<AllocationSiteOverrideMode, 8, 1> {};  // NOLINT
1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056
};

class ArrayNoArgumentConstructorStub : public CommonArrayConstructorStub {
 public:
  ArrayNoArgumentConstructorStub(
      Isolate* isolate, ElementsKind kind,
      AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
      : CommonArrayConstructorStub(isolate, kind, override_mode) {}

 private:
  void PrintName(std::ostream& os) const override {  // NOLINT
    os << "ArrayNoArgumentConstructorStub";
  }

  DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNoArgumentConstructor);
  DEFINE_TURBOFAN_CODE_STUB(ArrayNoArgumentConstructor,
                            CommonArrayConstructorStub);
};

class InternalArrayNoArgumentConstructorStub
    : public CommonArrayConstructorStub {
 public:
  InternalArrayNoArgumentConstructorStub(Isolate* isolate, ElementsKind kind)
      : CommonArrayConstructorStub(isolate, kind, DONT_OVERRIDE) {}

 private:
  void PrintName(std::ostream& os) const override {  // NOLINT
    os << "InternalArrayNoArgumentConstructorStub";
  }
1057 1058

  DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNoArgumentConstructor);
1059 1060
  DEFINE_TURBOFAN_CODE_STUB(InternalArrayNoArgumentConstructor,
                            CommonArrayConstructorStub);
1061
};
1062

1063
class ArraySingleArgumentConstructorStub : public CommonArrayConstructorStub {
1064
 public:
1065
  ArraySingleArgumentConstructorStub(
1066
      Isolate* isolate, ElementsKind kind,
1067
      AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
1068
      : CommonArrayConstructorStub(isolate, kind, override_mode) {}
1069 1070

 private:
1071
  void PrintName(std::ostream& os) const override {  // NOLINT
1072
    os << "ArraySingleArgumentConstructorStub";
1073 1074
  }

1075 1076 1077
  DEFINE_CALL_INTERFACE_DESCRIPTOR(ArraySingleArgumentConstructor);
  DEFINE_TURBOFAN_CODE_STUB(ArraySingleArgumentConstructor,
                            CommonArrayConstructorStub);
1078 1079
};

1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095
class InternalArraySingleArgumentConstructorStub
    : public CommonArrayConstructorStub {
 public:
  InternalArraySingleArgumentConstructorStub(Isolate* isolate,
                                             ElementsKind kind)
      : CommonArrayConstructorStub(isolate, kind, DONT_OVERRIDE) {}

 private:
  void PrintName(std::ostream& os) const override {  // NOLINT
    os << "InternalArraySingleArgumentConstructorStub";
  }

  DEFINE_CALL_INTERFACE_DESCRIPTOR(ArraySingleArgumentConstructor);
  DEFINE_TURBOFAN_CODE_STUB(InternalArraySingleArgumentConstructor,
                            CommonArrayConstructorStub);
};
1096

1097
class ArrayNArgumentsConstructorStub : public PlatformCodeStub {
1098
 public:
1099 1100
  explicit ArrayNArgumentsConstructorStub(Isolate* isolate)
      : PlatformCodeStub(isolate) {}
1101

1102 1103
  CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
    return ArrayNArgumentsConstructorDescriptor(isolate());
1104
  }
1105 1106

 private:
1107
  DEFINE_PLATFORM_CODE_STUB(ArrayNArgumentsConstructor, PlatformCodeStub);
1108 1109
};

1110
class StoreSlowElementStub : public TurboFanCodeStub {
danno@chromium.org's avatar
danno@chromium.org committed
1111
 public:
1112 1113 1114
  StoreSlowElementStub(Isolate* isolate, KeyedAccessStoreMode mode)
      : TurboFanCodeStub(isolate) {
    minor_key_ = CommonStoreModeBits::encode(mode);
1115
  }
danno@chromium.org's avatar
danno@chromium.org committed
1116

1117
  Code::Kind GetCodeKind() const override { return Code::HANDLER; }
1118
  ExtraICState GetExtraICState() const override { return Code::KEYED_STORE_IC; }
1119

1120
 private:
1121
  DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
1122
  DEFINE_TURBOFAN_CODE_STUB(StoreSlowElement, TurboFanCodeStub);
danno@chromium.org's avatar
danno@chromium.org committed
1123 1124
};

1125
class ElementsTransitionAndStoreStub : public TurboFanCodeStub {
1126
 public:
1127 1128
  ElementsTransitionAndStoreStub(Isolate* isolate, ElementsKind from_kind,
                                 ElementsKind to_kind, bool is_jsarray,
1129
                                 KeyedAccessStoreMode store_mode)
1130 1131 1132 1133
      : TurboFanCodeStub(isolate) {
    minor_key_ = CommonStoreModeBits::encode(store_mode) |
                 FromBits::encode(from_kind) | ToBits::encode(to_kind) |
                 IsJSArrayBits::encode(is_jsarray);
1134
  }
1135

1136 1137 1138
  ElementsKind from_kind() const { return FromBits::decode(minor_key_); }
  ElementsKind to_kind() const { return ToBits::decode(minor_key_); }
  bool is_jsarray() const { return IsJSArrayBits::decode(minor_key_); }
1139
  KeyedAccessStoreMode store_mode() const {
1140
    return CommonStoreModeBits::decode(minor_key_);
1141
  }
1142

1143
  Code::Kind GetCodeKind() const override { return Code::HANDLER; }
1144
  ExtraICState GetExtraICState() const override { return Code::KEYED_STORE_IC; }
1145

1146
 private:
1147 1148
  class FromBits
      : public BitField<ElementsKind, CommonStoreModeBits::kNext, 8> {};
1149 1150
  class ToBits : public BitField<ElementsKind, 11, 8> {};
  class IsJSArrayBits : public BitField<bool, 19, 1> {};
1151

1152 1153
  DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreTransition);
  DEFINE_TURBOFAN_CODE_STUB(ElementsTransitionAndStore, TurboFanCodeStub);
1154 1155 1156
};


1157
class ProfileEntryHookStub : public PlatformCodeStub {
1158
 public:
1159
  explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
1160 1161

  // The profile entry hook function is not allowed to cause a GC.
1162
  bool SometimesSetsUpAFrame() override { return false; }
1163 1164 1165

  // Generates a call to the entry hook if it's enabled.
  static void MaybeCallEntryHook(MacroAssembler* masm);
1166
  static void MaybeCallEntryHookDelayed(TurboAssembler* tasm, Zone* zone);
1167 1168 1169

 private:
  static void EntryHookTrampoline(intptr_t function,
1170 1171
                                  intptr_t stack_pointer,
                                  Isolate* isolate);
1172

1173 1174 1175
  // ProfileEntryHookStub is called at the start of a function, so it has the
  // same register set.
  DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction)
1176
  DEFINE_PLATFORM_CODE_STUB(ProfileEntryHook, PlatformCodeStub);
1177 1178
};

1179

1180 1181 1182 1183 1184 1185 1186 1187
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);
1188
  bool SometimesSetsUpAFrame() override { return false; }
1189 1190 1191 1192 1193 1194

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

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

1195
  DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1196
  DEFINE_PLATFORM_CODE_STUB(StoreBufferOverflow, PlatformCodeStub);
1197 1198
};

1199
class SubStringStub : public TurboFanCodeStub {
1200
 public:
1201 1202
  explicit SubStringStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}

1203
  DEFINE_CALL_INTERFACE_DESCRIPTOR(SubString);
1204
  DEFINE_TURBOFAN_CODE_STUB(SubString, TurboFanCodeStub);
1205 1206
};

1207

1208
#undef DEFINE_CALL_INTERFACE_DESCRIPTOR
1209 1210
#undef DEFINE_PLATFORM_CODE_STUB
#undef DEFINE_HANDLER_CODE_STUB
1211 1212
#undef DEFINE_CODE_STUB
#undef DEFINE_CODE_STUB_BASE
1213

1214 1215
}  // namespace internal
}  // namespace v8
1216 1217

#endif  // V8_CODE_STUBS_H_