1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef V8_CODE_STUBS_H_
6 #define V8_CODE_STUBS_H_
7
8 #include "src/allocation.h"
9 #include "src/assembler.h"
10 #include "src/code-stub-assembler.h"
11 #include "src/codegen.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 #include "src/type-hints.h"
18
19 namespace v8 {
20 namespace internal {
21
22 class ObjectLiteral;
23
24 // List of code stubs used on all platforms.
25 #define CODE_STUB_LIST_ALL_PLATFORMS(V) \
26 /* --- PlatformCodeStubs --- */ \
27 V(ArrayConstructor) \
28 V(BinaryOpICWithAllocationSite) \
29 V(CallApiCallback) \
30 V(CallApiGetter) \
31 V(CallConstruct) \
32 V(CallIC) \
33 V(CEntry) \
34 V(CompareIC) \
35 V(DoubleToI) \
36 V(FunctionPrototype) \
37 V(InternalArrayConstructor) \
38 V(JSEntry) \
39 V(LoadIndexedString) \
40 V(MathPow) \
41 V(ProfileEntryHook) \
42 V(RecordWrite) \
43 V(RegExpExec) \
44 V(StoreBufferOverflow) \
45 V(StoreElement) \
46 V(SubString) \
47 V(KeyedStoreIC) \
48 V(LoadGlobalIC) \
49 V(FastNewObject) \
50 V(FastNewRestParameter) \
51 V(FastNewSloppyArguments) \
52 V(FastNewStrictArguments) \
53 V(NameDictionaryLookup) \
54 /* This can be removed once there are no */ \
55 /* more deopting Hydrogen stubs. */ \
56 V(StubFailureTrampoline) \
57 /* These are only called from FCG */ \
58 /* They can be removed when only the TF */ \
59 /* version of the corresponding stub is */ \
60 /* used universally */ \
61 V(CallICTrampoline) \
62 V(KeyedStoreICTrampoline) \
63 /* --- HydrogenCodeStubs --- */ \
64 /* These builtins w/ JS linkage are */ \
65 /* just fast-cases of C++ builtins. They */ \
66 /* require varg support from TF */ \
67 V(FastArrayPush) \
68 V(FastFunctionBind) \
69 /* These will be ported/eliminated */ \
70 /* as part of the new IC system, ask */ \
71 /* ishell before doing anything */ \
72 V(LoadConstant) \
73 V(LoadDictionaryElement) \
74 V(LoadFastElement) \
75 V(LoadField) \
76 /* These should never be ported to TF */ \
77 /* because they are either used only by */ \
78 /* FCG/Crankshaft or are deprecated */ \
79 V(BinaryOpIC) \
80 V(BinaryOpWithAllocationSite) \
81 V(ToBooleanIC) \
82 V(TransitionElementsKind) \
83 /* --- TurboFanCodeStubs --- */ \
84 V(AllocateHeapNumber) \
85 V(AllocateFloat32x4) \
86 V(AllocateInt32x4) \
87 V(AllocateUint32x4) \
88 V(AllocateBool32x4) \
89 V(AllocateInt16x8) \
90 V(AllocateUint16x8) \
91 V(AllocateBool16x8) \
92 V(AllocateInt8x16) \
93 V(AllocateUint8x16) \
94 V(AllocateBool8x16) \
95 V(ArrayNoArgumentConstructor) \
96 V(ArraySingleArgumentConstructor) \
97 V(ArrayNArgumentsConstructor) \
98 V(CreateAllocationSite) \
99 V(CreateWeakCell) \
100 V(StringLength) \
101 V(AddWithFeedback) \
102 V(SubtractWithFeedback) \
103 V(MultiplyWithFeedback) \
104 V(DivideWithFeedback) \
105 V(ModulusWithFeedback) \
106 V(Inc) \
107 V(InternalArrayNoArgumentConstructor) \
108 V(InternalArraySingleArgumentConstructor) \
109 V(Dec) \
110 V(ElementsTransitionAndStore) \
111 V(FastCloneRegExp) \
112 V(FastCloneShallowArray) \
113 V(FastCloneShallowObject) \
114 V(FastNewClosure) \
115 V(FastNewFunctionContext) \
116 V(KeyedLoadSloppyArguments) \
117 V(KeyedStoreSloppyArguments) \
118 V(LoadScriptContextField) \
119 V(StoreScriptContextField) \
120 V(NumberToString) \
121 V(StringAdd) \
122 V(GetProperty) \
123 V(LoadIC) \
124 V(LoadICProtoArray) \
125 V(KeyedLoadICTF) \
126 V(StoreFastElement) \
127 V(StoreField) \
128 V(StoreGlobal) \
129 V(StoreIC) \
130 V(KeyedStoreICTF) \
131 V(StoreInterceptor) \
132 V(StoreMap) \
133 V(StoreTransition) \
134 V(LoadApiGetter) \
135 V(LoadIndexedInterceptor) \
136 V(GrowArrayElements) \
137 /* These are only called from FGC and */ \
138 /* can be removed when we use ignition */ \
139 /* only */ \
140 V(LoadICTrampoline) \
141 V(LoadGlobalICTrampoline) \
142 V(KeyedLoadICTrampolineTF) \
143 V(StoreICTrampoline) \
144 V(KeyedStoreICTrampolineTF)
145
146 // List of code stubs only used on ARM 32 bits platforms.
147 #if V8_TARGET_ARCH_ARM
148 #define CODE_STUB_LIST_ARM(V) V(DirectCEntry)
149
150 #else
151 #define CODE_STUB_LIST_ARM(V)
152 #endif
153
154 // List of code stubs only used on ARM 64 bits platforms.
155 #if V8_TARGET_ARCH_ARM64
156 #define CODE_STUB_LIST_ARM64(V) \
157 V(DirectCEntry) \
158 V(RestoreRegistersState) \
159 V(StoreRegistersState)
160
161 #else
162 #define CODE_STUB_LIST_ARM64(V)
163 #endif
164
165 // List of code stubs only used on PPC platforms.
166 #ifdef V8_TARGET_ARCH_PPC
167 #define CODE_STUB_LIST_PPC(V) \
168 V(DirectCEntry) \
169 V(StoreRegistersState) \
170 V(RestoreRegistersState)
171 #else
172 #define CODE_STUB_LIST_PPC(V)
173 #endif
174
175 // List of code stubs only used on MIPS platforms.
176 #if V8_TARGET_ARCH_MIPS
177 #define CODE_STUB_LIST_MIPS(V) \
178 V(DirectCEntry) \
179 V(RestoreRegistersState) \
180 V(StoreRegistersState)
181 #elif V8_TARGET_ARCH_MIPS64
182 #define CODE_STUB_LIST_MIPS(V) \
183 V(DirectCEntry) \
184 V(RestoreRegistersState) \
185 V(StoreRegistersState)
186 #else
187 #define CODE_STUB_LIST_MIPS(V)
188 #endif
189
190 // List of code stubs only used on S390 platforms.
191 #ifdef V8_TARGET_ARCH_S390
192 #define CODE_STUB_LIST_S390(V) \
193 V(DirectCEntry) \
194 V(StoreRegistersState) \
195 V(RestoreRegistersState)
196 #else
197 #define CODE_STUB_LIST_S390(V)
198 #endif
199
200 // Combined list of code stubs.
201 #define CODE_STUB_LIST(V) \
202 CODE_STUB_LIST_ALL_PLATFORMS(V) \
203 CODE_STUB_LIST_ARM(V) \
204 CODE_STUB_LIST_ARM64(V) \
205 CODE_STUB_LIST_PPC(V) \
206 CODE_STUB_LIST_MIPS(V) \
207 CODE_STUB_LIST_S390(V)
208
209 static const int kHasReturnedMinusZeroSentinel = 1;
210
211 // Stub is base classes of all stubs.
212 class CodeStub BASE_EMBEDDED {
213 public:
214 enum Major {
215 // TODO(mvstanton): eliminate the NoCache key by getting rid
216 // of the non-monomorphic-cache.
217 NoCache = 0, // marker for stubs that do custom caching]
218 #define DEF_ENUM(name) name,
219 CODE_STUB_LIST(DEF_ENUM)
220 #undef DEF_ENUM
221 NUMBER_OF_IDS
222 };
223
224 // Retrieve the code for the stub. Generate the code if needed.
225 Handle<Code> GetCode();
226
227 // Retrieve the code for the stub, make and return a copy of the code.
228 Handle<Code> GetCodeCopy(const Code::FindAndReplacePattern& pattern);
229
MajorKeyFromKey(uint32_t key)230 static Major MajorKeyFromKey(uint32_t key) {
231 return static_cast<Major>(MajorKeyBits::decode(key));
232 }
MinorKeyFromKey(uint32_t key)233 static uint32_t MinorKeyFromKey(uint32_t key) {
234 return MinorKeyBits::decode(key);
235 }
236
237 // Gets the major key from a code object that is a code stub or binary op IC.
GetMajorKey(Code * code_stub)238 static Major GetMajorKey(Code* code_stub) {
239 return MajorKeyFromKey(code_stub->stub_key());
240 }
241
NoCacheKey()242 static uint32_t NoCacheKey() { return MajorKeyBits::encode(NoCache); }
243
244 static const char* MajorName(Major major_key);
245
CodeStub(Isolate * isolate)246 explicit CodeStub(Isolate* isolate) : minor_key_(0), isolate_(isolate) {}
~CodeStub()247 virtual ~CodeStub() {}
248
249 static void GenerateStubsAheadOfTime(Isolate* isolate);
250 static void GenerateFPStubs(Isolate* isolate);
251
252 // Some stubs put untagged junk on the stack that cannot be scanned by the
253 // GC. This means that we must be statically sure that no GC can occur while
254 // they are running. If that is the case they should override this to return
255 // true, which will cause an assertion if we try to call something that can
256 // GC or if we try to put a stack frame on top of the junk, which would not
257 // result in a traversable stack.
SometimesSetsUpAFrame()258 virtual bool SometimesSetsUpAFrame() { return true; }
259
260 // Lookup the code in the (possibly custom) cache.
261 bool FindCodeInCache(Code** code_out);
262
263 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() const = 0;
264
GetStackParameterCount()265 virtual int GetStackParameterCount() const {
266 return GetCallInterfaceDescriptor().GetStackParameterCount();
267 }
268
InitializeDescriptor(CodeStubDescriptor * descriptor)269 virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) {}
270
271 static void InitializeDescriptor(Isolate* isolate, uint32_t key,
272 CodeStubDescriptor* desc);
273
274 static MaybeHandle<Code> GetCode(Isolate* isolate, uint32_t key);
275
276 // Returns information for computing the number key.
277 virtual Major MajorKey() const = 0;
MinorKey()278 uint32_t MinorKey() const { return minor_key_; }
279
280 // BinaryOpStub needs to override this.
281 virtual Code::Kind GetCodeKind() const;
282
GetExtraICState()283 virtual ExtraICState GetExtraICState() const { return kNoExtraICState; }
284
285 Code::Flags GetCodeFlags() const;
286
287 friend std::ostream& operator<<(std::ostream& os, const CodeStub& s) {
288 s.PrintName(os);
289 return os;
290 }
291
isolate()292 Isolate* isolate() const { return isolate_; }
293
294 protected:
CodeStub(uint32_t key,Isolate * isolate)295 CodeStub(uint32_t key, Isolate* isolate)
296 : minor_key_(MinorKeyFromKey(key)), isolate_(isolate) {}
297
298 // Generates the assembler code for the stub.
299 virtual Handle<Code> GenerateCode() = 0;
300
301 // Returns whether the code generated for this stub needs to be allocated as
302 // a fixed (non-moveable) code object.
NeedsImmovableCode()303 virtual bool NeedsImmovableCode() { return false; }
304
305 virtual void PrintName(std::ostream& os) const; // NOLINT
306 virtual void PrintBaseName(std::ostream& os) const; // NOLINT
PrintState(std::ostream & os)307 virtual void PrintState(std::ostream& os) const { ; } // NOLINT
308
309 // Computes the key based on major and minor.
GetKey()310 uint32_t GetKey() {
311 DCHECK(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
312 return MinorKeyBits::encode(MinorKey()) | MajorKeyBits::encode(MajorKey());
313 }
314
315 uint32_t minor_key_;
316
317 private:
318 // Perform bookkeeping required after code generation when stub code is
319 // initially generated.
320 void RecordCodeGeneration(Handle<Code> code);
321
322 // Finish the code object after it has been generated.
FinishCode(Handle<Code> code)323 virtual void FinishCode(Handle<Code> code) { }
324
325 // Activate newly generated stub. Is called after
326 // registering stub in the stub cache.
Activate(Code * code)327 virtual void Activate(Code* code) { }
328
329 // Add the code to a specialized cache, specific to an individual
330 // stub type. Please note, this method must add the code object to a
331 // roots object, otherwise we will remove the code during GC.
AddToSpecialCache(Handle<Code> new_object)332 virtual void AddToSpecialCache(Handle<Code> new_object) { }
333
334 // Find code in a specialized cache, work is delegated to the specific stub.
FindCodeInSpecialCache(Code ** code_out)335 virtual bool FindCodeInSpecialCache(Code** code_out) {
336 return false;
337 }
338
339 // If a stub uses a special cache override this.
UseSpecialCache()340 virtual bool UseSpecialCache() { return false; }
341
342 // We use this dispatch to statically instantiate the correct code stub for
343 // the given stub key and call the passed function with that code stub.
344 typedef void (*DispatchedCall)(CodeStub* stub, void** value_out);
345 static void Dispatch(Isolate* isolate, uint32_t key, void** value_out,
346 DispatchedCall call);
347
348 static void GetCodeDispatchCall(CodeStub* stub, void** value_out);
349
350 STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits));
351 class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
352 class MinorKeyBits: public BitField<uint32_t,
353 kStubMajorKeyBits, kStubMinorKeyBits> {}; // NOLINT
354
355 friend class BreakPointIterator;
356
357 Isolate* isolate_;
358 };
359
360
361 #define DEFINE_CODE_STUB_BASE(NAME, SUPER) \
362 public: \
363 NAME(uint32_t key, Isolate* isolate) : SUPER(key, isolate) {} \
364 \
365 private: \
366 DISALLOW_COPY_AND_ASSIGN(NAME)
367
368
369 #define DEFINE_CODE_STUB(NAME, SUPER) \
370 public: \
371 inline Major MajorKey() const override { return NAME; }; \
372 \
373 protected: \
374 DEFINE_CODE_STUB_BASE(NAME##Stub, SUPER)
375
376
377 #define DEFINE_PLATFORM_CODE_STUB(NAME, SUPER) \
378 private: \
379 void Generate(MacroAssembler* masm) override; \
380 DEFINE_CODE_STUB(NAME, SUPER)
381
382
383 #define DEFINE_HYDROGEN_CODE_STUB(NAME, SUPER) \
384 public: \
385 void InitializeDescriptor(CodeStubDescriptor* descriptor) override; \
386 Handle<Code> GenerateCode() override; \
387 DEFINE_CODE_STUB(NAME, SUPER)
388
389 #define DEFINE_TURBOFAN_CODE_STUB(NAME, SUPER) \
390 public: \
391 void GenerateAssembly(CodeStubAssembler* assembler) const override; \
392 DEFINE_CODE_STUB(NAME, SUPER)
393
394 #define DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(NAME, SUPER) \
395 public: \
396 static compiler::Node* Generate(CodeStubAssembler* assembler, \
397 compiler::Node* left, compiler::Node* right, \
398 compiler::Node* context); \
399 void GenerateAssembly(CodeStubAssembler* assembler) const override { \
400 assembler->Return(Generate(assembler, assembler->Parameter(0), \
401 assembler->Parameter(1), \
402 assembler->Parameter(2))); \
403 } \
404 DEFINE_CODE_STUB(NAME, SUPER)
405
406 #define DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(NAME, SUPER) \
407 public: \
408 static compiler::Node* Generate( \
409 CodeStubAssembler* assembler, compiler::Node* left, \
410 compiler::Node* right, compiler::Node* slot_id, \
411 compiler::Node* type_feedback_vector, compiler::Node* context); \
412 void GenerateAssembly(CodeStubAssembler* assembler) const override { \
413 assembler->Return( \
414 Generate(assembler, assembler->Parameter(0), assembler->Parameter(1), \
415 assembler->Parameter(2), assembler->Parameter(3), \
416 assembler->Parameter(4))); \
417 } \
418 DEFINE_CODE_STUB(NAME, SUPER)
419
420 #define DEFINE_TURBOFAN_UNARY_OP_CODE_STUB(NAME, SUPER) \
421 public: \
422 static compiler::Node* Generate(CodeStubAssembler* assembler, \
423 compiler::Node* value, \
424 compiler::Node* context); \
425 void GenerateAssembly(CodeStubAssembler* assembler) const override { \
426 assembler->Return(Generate(assembler, assembler->Parameter(0), \
427 assembler->Parameter(1))); \
428 } \
429 DEFINE_CODE_STUB(NAME, SUPER)
430
431 #define DEFINE_TURBOFAN_UNARY_OP_CODE_STUB_WITH_FEEDBACK(NAME, SUPER) \
432 public: \
433 static compiler::Node* Generate( \
434 CodeStubAssembler* assembler, compiler::Node* value, \
435 compiler::Node* context, compiler::Node* type_feedback_vector, \
436 compiler::Node* slot_id); \
437 void GenerateAssembly(CodeStubAssembler* assembler) const override { \
438 assembler->Return( \
439 Generate(assembler, assembler->Parameter(0), assembler->Parameter(1), \
440 assembler->Parameter(2), assembler->Parameter(3))); \
441 } \
442 DEFINE_CODE_STUB(NAME, SUPER)
443
444 #define DEFINE_HANDLER_CODE_STUB(NAME, SUPER) \
445 public: \
446 Handle<Code> GenerateCode() override; \
447 DEFINE_CODE_STUB(NAME, SUPER)
448
449 #define DEFINE_CALL_INTERFACE_DESCRIPTOR(NAME) \
450 public: \
451 typedef NAME##Descriptor Descriptor; \
452 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
453 return Descriptor(isolate()); \
454 }
455
456 // There are some code stubs we just can't describe right now with a
457 // CallInterfaceDescriptor. Isolate behavior for those cases with this macro.
458 // An attempt to retrieve a descriptor will fail.
459 #define DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR() \
460 public: \
461 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
462 UNREACHABLE(); \
463 return CallInterfaceDescriptor(); \
464 }
465
466
467 class PlatformCodeStub : public CodeStub {
468 public:
469 // Retrieve the code for the stub. Generate the code if needed.
470 Handle<Code> GenerateCode() override;
471
472 protected:
PlatformCodeStub(Isolate * isolate)473 explicit PlatformCodeStub(Isolate* isolate) : CodeStub(isolate) {}
474
475 // Generates the assembler code for the stub.
476 virtual void Generate(MacroAssembler* masm) = 0;
477
478 DEFINE_CODE_STUB_BASE(PlatformCodeStub, CodeStub);
479 };
480
481
482 enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
483
484
485 class CodeStubDescriptor {
486 public:
487 explicit CodeStubDescriptor(CodeStub* stub);
488
489 CodeStubDescriptor(Isolate* isolate, uint32_t stub_key);
490
491 void Initialize(Address deoptimization_handler = NULL,
492 int hint_stack_parameter_count = -1,
493 StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
494 void Initialize(Register stack_parameter_count,
495 Address deoptimization_handler = NULL,
496 int hint_stack_parameter_count = -1,
497 StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
498
SetMissHandler(Runtime::FunctionId id)499 void SetMissHandler(Runtime::FunctionId id) {
500 miss_handler_id_ = id;
501 miss_handler_ = ExternalReference(Runtime::FunctionForId(id), isolate_);
502 has_miss_handler_ = true;
503 // Our miss handler infrastructure doesn't currently support
504 // variable stack parameter counts.
505 DCHECK(!stack_parameter_count_.is_valid());
506 }
507
set_call_descriptor(CallInterfaceDescriptor d)508 void set_call_descriptor(CallInterfaceDescriptor d) { call_descriptor_ = d; }
call_descriptor()509 CallInterfaceDescriptor call_descriptor() const { return call_descriptor_; }
510
GetRegisterParameterCount()511 int GetRegisterParameterCount() const {
512 return call_descriptor().GetRegisterParameterCount();
513 }
514
GetStackParameterCount()515 int GetStackParameterCount() const {
516 return call_descriptor().GetStackParameterCount();
517 }
518
GetParameterCount()519 int GetParameterCount() const {
520 return call_descriptor().GetParameterCount();
521 }
522
GetRegisterParameter(int index)523 Register GetRegisterParameter(int index) const {
524 return call_descriptor().GetRegisterParameter(index);
525 }
526
GetParameterType(int index)527 MachineType GetParameterType(int index) const {
528 return call_descriptor().GetParameterType(index);
529 }
530
miss_handler()531 ExternalReference miss_handler() const {
532 DCHECK(has_miss_handler_);
533 return miss_handler_;
534 }
535
miss_handler_id()536 Runtime::FunctionId miss_handler_id() const {
537 DCHECK(has_miss_handler_);
538 return miss_handler_id_;
539 }
540
has_miss_handler()541 bool has_miss_handler() const {
542 return has_miss_handler_;
543 }
544
GetHandlerParameterCount()545 int GetHandlerParameterCount() const {
546 int params = GetParameterCount();
547 if (PassesArgumentsToDeoptimizationHandler()) {
548 params += 1;
549 }
550 return params;
551 }
552
hint_stack_parameter_count()553 int hint_stack_parameter_count() const { return hint_stack_parameter_count_; }
stack_parameter_count()554 Register stack_parameter_count() const { return stack_parameter_count_; }
function_mode()555 StubFunctionMode function_mode() const { return function_mode_; }
deoptimization_handler()556 Address deoptimization_handler() const { return deoptimization_handler_; }
557
558 private:
PassesArgumentsToDeoptimizationHandler()559 bool PassesArgumentsToDeoptimizationHandler() const {
560 return stack_parameter_count_.is_valid();
561 }
562
563 Isolate* isolate_;
564 CallInterfaceDescriptor call_descriptor_;
565 Register stack_parameter_count_;
566 // If hint_stack_parameter_count_ > 0, the code stub can optimize the
567 // return sequence. Default value is -1, which means it is ignored.
568 int hint_stack_parameter_count_;
569 StubFunctionMode function_mode_;
570
571 Address deoptimization_handler_;
572
573 ExternalReference miss_handler_;
574 Runtime::FunctionId miss_handler_id_;
575 bool has_miss_handler_;
576 };
577
578
579 class HydrogenCodeStub : public CodeStub {
580 public:
581 enum InitializationState {
582 UNINITIALIZED,
583 INITIALIZED
584 };
585
586 template<class SubClass>
GetUninitialized(Isolate * isolate)587 static Handle<Code> GetUninitialized(Isolate* isolate) {
588 SubClass::GenerateAheadOfTime(isolate);
589 return SubClass().GetCode(isolate);
590 }
591
592 // Retrieve the code for the stub. Generate the code if needed.
593 Handle<Code> GenerateCode() override = 0;
594
IsUninitialized()595 bool IsUninitialized() const { return IsMissBits::decode(minor_key_); }
596
597 Handle<Code> GenerateLightweightMissCode(ExternalReference miss);
598
599 Handle<Code> GenerateRuntimeTailCall(CodeStubDescriptor* descriptor);
600
601 template<class StateType>
602 void TraceTransition(StateType from, StateType to);
603
604 protected:
605 explicit HydrogenCodeStub(Isolate* isolate,
606 InitializationState state = INITIALIZED)
CodeStub(isolate)607 : CodeStub(isolate) {
608 minor_key_ = IsMissBits::encode(state == UNINITIALIZED);
609 }
610
set_sub_minor_key(uint32_t key)611 void set_sub_minor_key(uint32_t key) {
612 minor_key_ = SubMinorKeyBits::update(minor_key_, key);
613 }
614
sub_minor_key()615 uint32_t sub_minor_key() const { return SubMinorKeyBits::decode(minor_key_); }
616
617 static const int kSubMinorKeyBits = kStubMinorKeyBits - 1;
618
619 private:
620 class IsMissBits : public BitField<bool, kSubMinorKeyBits, 1> {};
621 class SubMinorKeyBits : public BitField<int, 0, kSubMinorKeyBits> {};
622
623 void GenerateLightweightMiss(MacroAssembler* masm, ExternalReference miss);
624
625 DEFINE_CODE_STUB_BASE(HydrogenCodeStub, CodeStub);
626 };
627
628
629 class TurboFanCodeStub : public CodeStub {
630 public:
631 // Retrieve the code for the stub. Generate the code if needed.
632 Handle<Code> GenerateCode() override;
633
GetStackParameterCount()634 int GetStackParameterCount() const override {
635 return GetCallInterfaceDescriptor().GetStackParameterCount();
636 }
637
638 protected:
TurboFanCodeStub(Isolate * isolate)639 explicit TurboFanCodeStub(Isolate* isolate) : CodeStub(isolate) {}
640
641 virtual void GenerateAssembly(CodeStubAssembler* assembler) const = 0;
642
643 private:
644 DEFINE_CODE_STUB_BASE(TurboFanCodeStub, CodeStub);
645 };
646
647
648 // Helper interface to prepare to/restore after making runtime calls.
649 class RuntimeCallHelper {
650 public:
~RuntimeCallHelper()651 virtual ~RuntimeCallHelper() {}
652
653 virtual void BeforeCall(MacroAssembler* masm) const = 0;
654
655 virtual void AfterCall(MacroAssembler* masm) const = 0;
656
657 protected:
RuntimeCallHelper()658 RuntimeCallHelper() {}
659
660 private:
661 DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
662 };
663
664
665 } // namespace internal
666 } // namespace v8
667
668 #if V8_TARGET_ARCH_IA32
669 #include "src/ia32/code-stubs-ia32.h"
670 #elif V8_TARGET_ARCH_X64
671 #include "src/x64/code-stubs-x64.h"
672 #elif V8_TARGET_ARCH_ARM64
673 #include "src/arm64/code-stubs-arm64.h"
674 #elif V8_TARGET_ARCH_ARM
675 #include "src/arm/code-stubs-arm.h"
676 #elif V8_TARGET_ARCH_PPC
677 #include "src/ppc/code-stubs-ppc.h"
678 #elif V8_TARGET_ARCH_MIPS
679 #include "src/mips/code-stubs-mips.h"
680 #elif V8_TARGET_ARCH_MIPS64
681 #include "src/mips64/code-stubs-mips64.h"
682 #elif V8_TARGET_ARCH_S390
683 #include "src/s390/code-stubs-s390.h"
684 #elif V8_TARGET_ARCH_X87
685 #include "src/x87/code-stubs-x87.h"
686 #else
687 #error Unsupported target architecture.
688 #endif
689
690 namespace v8 {
691 namespace internal {
692
693
694 // RuntimeCallHelper implementation used in stubs: enters/leaves a
695 // newly created internal frame before/after the runtime call.
696 class StubRuntimeCallHelper : public RuntimeCallHelper {
697 public:
StubRuntimeCallHelper()698 StubRuntimeCallHelper() {}
699
700 void BeforeCall(MacroAssembler* masm) const override;
701
702 void AfterCall(MacroAssembler* masm) const override;
703 };
704
705
706 // Trivial RuntimeCallHelper implementation.
707 class NopRuntimeCallHelper : public RuntimeCallHelper {
708 public:
NopRuntimeCallHelper()709 NopRuntimeCallHelper() {}
710
BeforeCall(MacroAssembler * masm)711 void BeforeCall(MacroAssembler* masm) const override {}
712
AfterCall(MacroAssembler * masm)713 void AfterCall(MacroAssembler* masm) const override {}
714 };
715
716
717 class StringLengthStub : public TurboFanCodeStub {
718 public:
StringLengthStub(Isolate * isolate)719 explicit StringLengthStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
720
GetCodeKind()721 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()722 ExtraICState GetExtraICState() const override { return Code::LOAD_IC; }
723
724 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
725 DEFINE_TURBOFAN_CODE_STUB(StringLength, TurboFanCodeStub);
726 };
727
728 class AddWithFeedbackStub final : public TurboFanCodeStub {
729 public:
AddWithFeedbackStub(Isolate * isolate)730 explicit AddWithFeedbackStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
731
732 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithVector);
733 DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(AddWithFeedback,
734 TurboFanCodeStub);
735 };
736
737 class SubtractWithFeedbackStub final : public TurboFanCodeStub {
738 public:
SubtractWithFeedbackStub(Isolate * isolate)739 explicit SubtractWithFeedbackStub(Isolate* isolate)
740 : TurboFanCodeStub(isolate) {}
741
742 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithVector);
743 DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(SubtractWithFeedback,
744 TurboFanCodeStub);
745 };
746
747 class MultiplyWithFeedbackStub final : public TurboFanCodeStub {
748 public:
MultiplyWithFeedbackStub(Isolate * isolate)749 explicit MultiplyWithFeedbackStub(Isolate* isolate)
750 : TurboFanCodeStub(isolate) {}
751
752 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithVector);
753 DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(MultiplyWithFeedback,
754 TurboFanCodeStub);
755 };
756
757 class DivideWithFeedbackStub final : public TurboFanCodeStub {
758 public:
DivideWithFeedbackStub(Isolate * isolate)759 explicit DivideWithFeedbackStub(Isolate* isolate)
760 : TurboFanCodeStub(isolate) {}
761
762 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithVector);
763 DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(DivideWithFeedback,
764 TurboFanCodeStub);
765 };
766
767 class ModulusWithFeedbackStub final : public TurboFanCodeStub {
768 public:
ModulusWithFeedbackStub(Isolate * isolate)769 explicit ModulusWithFeedbackStub(Isolate* isolate)
770 : TurboFanCodeStub(isolate) {}
771
772 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithVector);
773 DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(ModulusWithFeedback,
774 TurboFanCodeStub);
775 };
776
777 class IncStub final : public TurboFanCodeStub {
778 public:
IncStub(Isolate * isolate)779 explicit IncStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
780
781 DEFINE_CALL_INTERFACE_DESCRIPTOR(CountOp);
782 DEFINE_TURBOFAN_UNARY_OP_CODE_STUB_WITH_FEEDBACK(Inc, TurboFanCodeStub);
783 };
784
785 class DecStub final : public TurboFanCodeStub {
786 public:
DecStub(Isolate * isolate)787 explicit DecStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
788
789 DEFINE_CALL_INTERFACE_DESCRIPTOR(CountOp);
790 DEFINE_TURBOFAN_UNARY_OP_CODE_STUB_WITH_FEEDBACK(Dec, TurboFanCodeStub);
791 };
792
793 class StoreInterceptorStub : public TurboFanCodeStub {
794 public:
StoreInterceptorStub(Isolate * isolate)795 explicit StoreInterceptorStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
796
797 void GenerateAssembly(CodeStubAssembler* assember) const override;
798
GetCodeKind()799 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()800 ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
801
802 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
803 DEFINE_CODE_STUB(StoreInterceptor, TurboFanCodeStub);
804 };
805
806 class LoadIndexedInterceptorStub : public TurboFanCodeStub {
807 public:
LoadIndexedInterceptorStub(Isolate * isolate)808 explicit LoadIndexedInterceptorStub(Isolate* isolate)
809 : TurboFanCodeStub(isolate) {}
810
GetCodeKind()811 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()812 ExtraICState GetExtraICState() const override { return Code::KEYED_LOAD_IC; }
813
814 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
815 DEFINE_TURBOFAN_CODE_STUB(LoadIndexedInterceptor, TurboFanCodeStub);
816 };
817
818 // ES6 [[Get]] operation.
819 class GetPropertyStub : public TurboFanCodeStub {
820 public:
GetPropertyStub(Isolate * isolate)821 explicit GetPropertyStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
822
823 DEFINE_CALL_INTERFACE_DESCRIPTOR(GetProperty);
824 DEFINE_TURBOFAN_CODE_STUB(GetProperty, TurboFanCodeStub);
825 };
826
827 class NumberToStringStub final : public TurboFanCodeStub {
828 public:
NumberToStringStub(Isolate * isolate)829 explicit NumberToStringStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
830
831 DEFINE_CALL_INTERFACE_DESCRIPTOR(TypeConversion);
832 DEFINE_TURBOFAN_CODE_STUB(NumberToString, TurboFanCodeStub);
833 };
834
835 class FastNewClosureStub : public TurboFanCodeStub {
836 public:
FastNewClosureStub(Isolate * isolate)837 explicit FastNewClosureStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
838
839 static compiler::Node* Generate(CodeStubAssembler* assembler,
840 compiler::Node* shared_info,
841 compiler::Node* context);
842
843 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewClosure);
844 DEFINE_TURBOFAN_CODE_STUB(FastNewClosure, TurboFanCodeStub);
845 };
846
847 class FastNewFunctionContextStub final : public TurboFanCodeStub {
848 public:
849 static const int kMaximumSlots = 0x8000;
850
FastNewFunctionContextStub(Isolate * isolate)851 explicit FastNewFunctionContextStub(Isolate* isolate)
852 : TurboFanCodeStub(isolate) {}
853
854 static compiler::Node* Generate(CodeStubAssembler* assembler,
855 compiler::Node* function,
856 compiler::Node* slots,
857 compiler::Node* context);
858
859 private:
860 // FastNewFunctionContextStub can only allocate closures which fit in the
861 // new space.
862 STATIC_ASSERT(((kMaximumSlots + Context::MIN_CONTEXT_SLOTS) * kPointerSize +
863 FixedArray::kHeaderSize) < kMaxRegularHeapObjectSize);
864
865 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewFunctionContext);
866 DEFINE_TURBOFAN_CODE_STUB(FastNewFunctionContext, TurboFanCodeStub);
867 };
868
869
870 class FastNewObjectStub final : public PlatformCodeStub {
871 public:
FastNewObjectStub(Isolate * isolate)872 explicit FastNewObjectStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
873
874 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewObject);
875 DEFINE_PLATFORM_CODE_STUB(FastNewObject, PlatformCodeStub);
876 };
877
878
879 // TODO(turbofan): This stub should be possible to write in TurboFan
880 // using the CodeStubAssembler very soon in a way that is as efficient
881 // and easy as the current handwritten version, which is partly a copy
882 // of the strict arguments object materialization code.
883 class FastNewRestParameterStub final : public PlatformCodeStub {
884 public:
885 explicit FastNewRestParameterStub(Isolate* isolate,
886 bool skip_stub_frame = false)
PlatformCodeStub(isolate)887 : PlatformCodeStub(isolate) {
888 minor_key_ = SkipStubFrameBits::encode(skip_stub_frame);
889 }
890
891 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewRestParameter);
892 DEFINE_PLATFORM_CODE_STUB(FastNewRestParameter, PlatformCodeStub);
893
skip_stub_frame()894 int skip_stub_frame() const { return SkipStubFrameBits::decode(minor_key_); }
895
896 private:
897 class SkipStubFrameBits : public BitField<bool, 0, 1> {};
898 };
899
900
901 // TODO(turbofan): This stub should be possible to write in TurboFan
902 // using the CodeStubAssembler very soon in a way that is as efficient
903 // and easy as the current handwritten version.
904 class FastNewSloppyArgumentsStub final : public PlatformCodeStub {
905 public:
906 explicit FastNewSloppyArgumentsStub(Isolate* isolate,
907 bool skip_stub_frame = false)
PlatformCodeStub(isolate)908 : PlatformCodeStub(isolate) {
909 minor_key_ = SkipStubFrameBits::encode(skip_stub_frame);
910 }
911
skip_stub_frame()912 int skip_stub_frame() const { return SkipStubFrameBits::decode(minor_key_); }
913
914 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewSloppyArguments);
915 DEFINE_PLATFORM_CODE_STUB(FastNewSloppyArguments, PlatformCodeStub);
916
917 private:
918 class SkipStubFrameBits : public BitField<bool, 0, 1> {};
919 };
920
921
922 // TODO(turbofan): This stub should be possible to write in TurboFan
923 // using the CodeStubAssembler very soon in a way that is as efficient
924 // and easy as the current handwritten version.
925 class FastNewStrictArgumentsStub final : public PlatformCodeStub {
926 public:
927 explicit FastNewStrictArgumentsStub(Isolate* isolate,
928 bool skip_stub_frame = false)
PlatformCodeStub(isolate)929 : PlatformCodeStub(isolate) {
930 minor_key_ = SkipStubFrameBits::encode(skip_stub_frame);
931 }
932
933 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewStrictArguments);
934 DEFINE_PLATFORM_CODE_STUB(FastNewStrictArguments, PlatformCodeStub);
935
skip_stub_frame()936 int skip_stub_frame() const { return SkipStubFrameBits::decode(minor_key_); }
937
938 private:
939 class SkipStubFrameBits : public BitField<bool, 0, 1> {};
940 };
941
942 class FastCloneRegExpStub final : public TurboFanCodeStub {
943 public:
FastCloneRegExpStub(Isolate * isolate)944 explicit FastCloneRegExpStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
945
946 static compiler::Node* Generate(CodeStubAssembler* assembler,
947 compiler::Node* closure,
948 compiler::Node* literal_index,
949 compiler::Node* pattern,
950 compiler::Node* flags,
951 compiler::Node* context);
952
953 private:
954 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneRegExp);
955 DEFINE_TURBOFAN_CODE_STUB(FastCloneRegExp, TurboFanCodeStub);
956 };
957
958 class FastCloneShallowArrayStub : public TurboFanCodeStub {
959 public:
FastCloneShallowArrayStub(Isolate * isolate,AllocationSiteMode allocation_site_mode)960 FastCloneShallowArrayStub(Isolate* isolate,
961 AllocationSiteMode allocation_site_mode)
962 : TurboFanCodeStub(isolate) {
963 minor_key_ = AllocationSiteModeBits::encode(allocation_site_mode);
964 }
965
966 static compiler::Node* Generate(CodeStubAssembler* assembler,
967 compiler::Node* closure,
968 compiler::Node* literal_index,
969 compiler::Node* context,
970 CodeStubAssembler::Label* call_runtime,
971 AllocationSiteMode allocation_site_mode);
972
allocation_site_mode()973 AllocationSiteMode allocation_site_mode() const {
974 return AllocationSiteModeBits::decode(minor_key_);
975 }
976
977 private:
978 class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {};
979
980 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowArray);
981 DEFINE_TURBOFAN_CODE_STUB(FastCloneShallowArray, TurboFanCodeStub);
982 };
983
984 class FastCloneShallowObjectStub : public TurboFanCodeStub {
985 public:
986 // Maximum number of properties in copied object.
987 static const int kMaximumClonedProperties = 6;
988
FastCloneShallowObjectStub(Isolate * isolate,int length)989 FastCloneShallowObjectStub(Isolate* isolate, int length)
990 : TurboFanCodeStub(isolate) {
991 DCHECK_GE(length, 0);
992 DCHECK_LE(length, kMaximumClonedProperties);
993 minor_key_ = LengthBits::encode(LengthBits::encode(length));
994 }
995
996 static compiler::Node* GenerateFastPath(
997 CodeStubAssembler* assembler,
998 compiler::CodeAssembler::Label* call_runtime, compiler::Node* closure,
999 compiler::Node* literals_index, compiler::Node* properties_count);
1000
1001 static bool IsSupported(ObjectLiteral* expr);
1002 static int PropertiesCount(int literal_length);
1003
length()1004 int length() const { return LengthBits::decode(minor_key_); }
1005
1006 private:
1007 class LengthBits : public BitField<int, 0, 4> {};
1008
1009 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowObject);
1010 DEFINE_TURBOFAN_CODE_STUB(FastCloneShallowObject, TurboFanCodeStub);
1011 };
1012
1013 class CreateAllocationSiteStub : public TurboFanCodeStub {
1014 public:
CreateAllocationSiteStub(Isolate * isolate)1015 explicit CreateAllocationSiteStub(Isolate* isolate)
1016 : TurboFanCodeStub(isolate) {}
1017 static void GenerateAheadOfTime(Isolate* isolate);
1018
1019 DEFINE_CALL_INTERFACE_DESCRIPTOR(CreateAllocationSite);
1020 DEFINE_TURBOFAN_CODE_STUB(CreateAllocationSite, TurboFanCodeStub);
1021 };
1022
1023 class CreateWeakCellStub : public TurboFanCodeStub {
1024 public:
CreateWeakCellStub(Isolate * isolate)1025 explicit CreateWeakCellStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
1026
1027 static void GenerateAheadOfTime(Isolate* isolate);
1028
1029 DEFINE_CALL_INTERFACE_DESCRIPTOR(CreateWeakCell);
1030 DEFINE_TURBOFAN_CODE_STUB(CreateWeakCell, TurboFanCodeStub);
1031 };
1032
1033 class GrowArrayElementsStub : public TurboFanCodeStub {
1034 public:
GrowArrayElementsStub(Isolate * isolate,ElementsKind kind)1035 GrowArrayElementsStub(Isolate* isolate, ElementsKind kind)
1036 : TurboFanCodeStub(isolate) {
1037 minor_key_ = ElementsKindBits::encode(GetHoleyElementsKind(kind));
1038 }
1039
elements_kind()1040 ElementsKind elements_kind() const {
1041 return ElementsKindBits::decode(minor_key_);
1042 }
1043
1044 private:
1045 class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
1046
1047 DEFINE_CALL_INTERFACE_DESCRIPTOR(GrowArrayElements);
1048 DEFINE_TURBOFAN_CODE_STUB(GrowArrayElements, TurboFanCodeStub);
1049 };
1050
1051 class FastArrayPushStub : public HydrogenCodeStub {
1052 public:
FastArrayPushStub(Isolate * isolate)1053 explicit FastArrayPushStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
1054
1055 private:
1056 DEFINE_CALL_INTERFACE_DESCRIPTOR(VarArgFunction);
1057 DEFINE_HYDROGEN_CODE_STUB(FastArrayPush, HydrogenCodeStub);
1058 };
1059
1060 class FastFunctionBindStub : public HydrogenCodeStub {
1061 public:
FastFunctionBindStub(Isolate * isolate)1062 explicit FastFunctionBindStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
1063
1064 private:
1065 DEFINE_CALL_INTERFACE_DESCRIPTOR(VarArgFunction);
1066 DEFINE_HYDROGEN_CODE_STUB(FastFunctionBind, HydrogenCodeStub);
1067 };
1068
1069 enum AllocationSiteOverrideMode {
1070 DONT_OVERRIDE,
1071 DISABLE_ALLOCATION_SITES,
1072 LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
1073 };
1074
1075
1076 class ArrayConstructorStub: public PlatformCodeStub {
1077 public:
1078 explicit ArrayConstructorStub(Isolate* isolate);
1079
1080 private:
1081 void GenerateDispatchToArrayStub(MacroAssembler* masm,
1082 AllocationSiteOverrideMode mode);
1083
1084 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNArgumentsConstructor);
1085 DEFINE_PLATFORM_CODE_STUB(ArrayConstructor, PlatformCodeStub);
1086 };
1087
1088
1089 class InternalArrayConstructorStub: public PlatformCodeStub {
1090 public:
1091 explicit InternalArrayConstructorStub(Isolate* isolate);
1092
1093 private:
1094 void GenerateCase(MacroAssembler* masm, ElementsKind kind);
1095
1096 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNArgumentsConstructor);
1097 DEFINE_PLATFORM_CODE_STUB(InternalArrayConstructor, PlatformCodeStub);
1098 };
1099
1100
1101 class MathPowStub: public PlatformCodeStub {
1102 public:
1103 enum ExponentType { INTEGER, DOUBLE, TAGGED };
1104
MathPowStub(Isolate * isolate,ExponentType exponent_type)1105 MathPowStub(Isolate* isolate, ExponentType exponent_type)
1106 : PlatformCodeStub(isolate) {
1107 minor_key_ = ExponentTypeBits::encode(exponent_type);
1108 }
1109
GetCallInterfaceDescriptor()1110 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
1111 if (exponent_type() == TAGGED) {
1112 return MathPowTaggedDescriptor(isolate());
1113 } else if (exponent_type() == INTEGER) {
1114 return MathPowIntegerDescriptor(isolate());
1115 } else {
1116 // A CallInterfaceDescriptor doesn't specify double registers (yet).
1117 DCHECK_EQ(DOUBLE, exponent_type());
1118 return ContextOnlyDescriptor(isolate());
1119 }
1120 }
1121
1122 private:
exponent_type()1123 ExponentType exponent_type() const {
1124 return ExponentTypeBits::decode(minor_key_);
1125 }
1126
1127 class ExponentTypeBits : public BitField<ExponentType, 0, 2> {};
1128
1129 DEFINE_PLATFORM_CODE_STUB(MathPow, PlatformCodeStub);
1130 };
1131
1132
1133 class CallICStub: public PlatformCodeStub {
1134 public:
CallICStub(Isolate * isolate,const CallICState & state)1135 CallICStub(Isolate* isolate, const CallICState& state)
1136 : PlatformCodeStub(isolate) {
1137 minor_key_ = state.GetExtraICState();
1138 }
1139
GetCodeKind()1140 Code::Kind GetCodeKind() const override { return Code::CALL_IC; }
1141
GetExtraICState()1142 ExtraICState GetExtraICState() const final {
1143 return static_cast<ExtraICState>(minor_key_);
1144 }
1145
1146 protected:
convert_mode()1147 ConvertReceiverMode convert_mode() const { return state().convert_mode(); }
tail_call_mode()1148 TailCallMode tail_call_mode() const { return state().tail_call_mode(); }
1149
state()1150 CallICState state() const { return CallICState(GetExtraICState()); }
1151
1152 // Code generation helpers.
1153 void GenerateMiss(MacroAssembler* masm);
1154 void HandleArrayCase(MacroAssembler* masm, Label* miss);
1155
1156 private:
1157 void PrintState(std::ostream& os) const override; // NOLINT
1158
1159 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunctionWithFeedbackAndVector);
1160 DEFINE_PLATFORM_CODE_STUB(CallIC, PlatformCodeStub);
1161 };
1162
1163
1164 // TODO(verwaest): Translate to hydrogen code stub.
1165 class FunctionPrototypeStub : public PlatformCodeStub {
1166 public:
FunctionPrototypeStub(Isolate * isolate)1167 explicit FunctionPrototypeStub(Isolate* isolate)
1168 : PlatformCodeStub(isolate) {}
1169
GetCodeKind()1170 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()1171 ExtraICState GetExtraICState() const override { return Code::LOAD_IC; }
1172
1173 // TODO(mvstanton): only the receiver register is accessed. When this is
1174 // translated to a hydrogen code stub, a new CallInterfaceDescriptor
1175 // should be created that just uses that register for more efficient code.
GetCallInterfaceDescriptor()1176 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
1177 return LoadWithVectorDescriptor(isolate());
1178 }
1179
1180 DEFINE_PLATFORM_CODE_STUB(FunctionPrototype, PlatformCodeStub);
1181 };
1182
1183
1184 class LoadIndexedStringStub : public PlatformCodeStub {
1185 public:
LoadIndexedStringStub(Isolate * isolate)1186 explicit LoadIndexedStringStub(Isolate* isolate)
1187 : PlatformCodeStub(isolate) {}
1188
GetCodeKind()1189 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()1190 ExtraICState GetExtraICState() const override { return Code::KEYED_LOAD_IC; }
1191
1192 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1193 DEFINE_PLATFORM_CODE_STUB(LoadIndexedString, PlatformCodeStub);
1194 };
1195
1196
1197 class HandlerStub : public HydrogenCodeStub {
1198 public:
GetCodeKind()1199 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()1200 ExtraICState GetExtraICState() const override { return kind(); }
1201
1202 void InitializeDescriptor(CodeStubDescriptor* descriptor) override;
1203
1204 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override;
1205
1206 protected:
HandlerStub(Isolate * isolate)1207 explicit HandlerStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
1208
1209 virtual Code::Kind kind() const = 0;
1210
1211 DEFINE_CODE_STUB_BASE(HandlerStub, HydrogenCodeStub);
1212 };
1213
1214
1215 class LoadFieldStub: public HandlerStub {
1216 public:
LoadFieldStub(Isolate * isolate,FieldIndex index)1217 LoadFieldStub(Isolate* isolate, FieldIndex index) : HandlerStub(isolate) {
1218 int property_index_key = index.GetFieldAccessStubKey();
1219 set_sub_minor_key(LoadFieldByIndexBits::encode(property_index_key));
1220 }
1221
index()1222 FieldIndex index() const {
1223 int property_index_key = LoadFieldByIndexBits::decode(sub_minor_key());
1224 return FieldIndex::FromFieldAccessStubKey(property_index_key);
1225 }
1226
1227 protected:
kind()1228 Code::Kind kind() const override { return Code::LOAD_IC; }
1229
1230 private:
1231 class LoadFieldByIndexBits : public BitField<int, 0, 13> {};
1232
1233 // TODO(ishell): The stub uses only kReceiver parameter.
1234 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
1235 DEFINE_HANDLER_CODE_STUB(LoadField, HandlerStub);
1236 };
1237
1238 class KeyedLoadSloppyArgumentsStub : public TurboFanCodeStub {
1239 public:
KeyedLoadSloppyArgumentsStub(Isolate * isolate)1240 explicit KeyedLoadSloppyArgumentsStub(Isolate* isolate)
1241 : TurboFanCodeStub(isolate) {}
1242
GetCodeKind()1243 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()1244 ExtraICState GetExtraICState() const override { return Code::LOAD_IC; }
1245
1246 protected:
1247 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
1248 DEFINE_TURBOFAN_CODE_STUB(KeyedLoadSloppyArguments, TurboFanCodeStub);
1249 };
1250
1251
1252 class CommonStoreModeBits : public BitField<KeyedAccessStoreMode, 0, 3> {};
1253
1254 class KeyedStoreSloppyArgumentsStub : public TurboFanCodeStub {
1255 public:
KeyedStoreSloppyArgumentsStub(Isolate * isolate,KeyedAccessStoreMode mode)1256 explicit KeyedStoreSloppyArgumentsStub(Isolate* isolate,
1257 KeyedAccessStoreMode mode)
1258 : TurboFanCodeStub(isolate) {
1259 minor_key_ = CommonStoreModeBits::encode(mode);
1260 }
1261
GetCodeKind()1262 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()1263 ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
1264
1265 protected:
1266 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
1267 DEFINE_TURBOFAN_CODE_STUB(KeyedStoreSloppyArguments, TurboFanCodeStub);
1268 };
1269
1270
1271 class LoadConstantStub : public HandlerStub {
1272 public:
LoadConstantStub(Isolate * isolate,int constant_index)1273 LoadConstantStub(Isolate* isolate, int constant_index)
1274 : HandlerStub(isolate) {
1275 set_sub_minor_key(ConstantIndexBits::encode(constant_index));
1276 }
1277
constant_index()1278 int constant_index() const {
1279 return ConstantIndexBits::decode(sub_minor_key());
1280 }
1281
1282 protected:
kind()1283 Code::Kind kind() const override { return Code::LOAD_IC; }
1284
1285 private:
1286 class ConstantIndexBits : public BitField<int, 0, kSubMinorKeyBits> {};
1287
1288 // TODO(ishell): The stub uses only kReceiver parameter.
1289 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
1290 DEFINE_HANDLER_CODE_STUB(LoadConstant, HandlerStub);
1291 };
1292
1293 class LoadApiGetterStub : public TurboFanCodeStub {
1294 public:
LoadApiGetterStub(Isolate * isolate,bool receiver_is_holder,int index)1295 LoadApiGetterStub(Isolate* isolate, bool receiver_is_holder, int index)
1296 : TurboFanCodeStub(isolate) {
1297 // If that's not true, we need to ensure that the receiver is actually a
1298 // JSReceiver. http://crbug.com/609134
1299 DCHECK(receiver_is_holder);
1300 minor_key_ = IndexBits::encode(index) |
1301 ReceiverIsHolderBits::encode(receiver_is_holder);
1302 }
1303
GetCodeKind()1304 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()1305 ExtraICState GetExtraICState() const override { return Code::LOAD_IC; }
1306
index()1307 int index() const { return IndexBits::decode(minor_key_); }
receiver_is_holder()1308 bool receiver_is_holder() const {
1309 return ReceiverIsHolderBits::decode(minor_key_);
1310 }
1311
1312 private:
1313 class ReceiverIsHolderBits : public BitField<bool, 0, 1> {};
1314 class IndexBits : public BitField<int, 1, kDescriptorIndexBitCount> {};
1315
1316 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1317 DEFINE_TURBOFAN_CODE_STUB(LoadApiGetter, TurboFanCodeStub);
1318 };
1319
1320 class StoreFieldStub : public TurboFanCodeStub {
1321 public:
StoreFieldStub(Isolate * isolate,FieldIndex index,Representation representation)1322 StoreFieldStub(Isolate* isolate, FieldIndex index,
1323 Representation representation)
1324 : TurboFanCodeStub(isolate) {
1325 int property_index_key = index.GetFieldAccessStubKey();
1326 minor_key_ = StoreFieldByIndexBits::encode(property_index_key) |
1327 RepresentationBits::encode(representation.kind());
1328 }
1329
GetCodeKind()1330 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()1331 ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
1332
index()1333 FieldIndex index() const {
1334 int property_index_key = StoreFieldByIndexBits::decode(minor_key_);
1335 return FieldIndex::FromFieldAccessStubKey(property_index_key);
1336 }
1337
representation()1338 Representation representation() const {
1339 return Representation::FromKind(RepresentationBits::decode(minor_key_));
1340 }
1341
1342 private:
1343 class StoreFieldByIndexBits : public BitField<int, 0, 13> {};
1344 class RepresentationBits
1345 : public BitField<Representation::Kind, StoreFieldByIndexBits::kNext, 4> {
1346 };
1347 STATIC_ASSERT(Representation::kNumRepresentations - 1 <
1348 RepresentationBits::kMax);
1349
1350 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
1351 DEFINE_TURBOFAN_CODE_STUB(StoreField, TurboFanCodeStub);
1352 };
1353
1354 class StoreMapStub : public TurboFanCodeStub {
1355 public:
StoreMapStub(Isolate * isolate)1356 explicit StoreMapStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
1357
GetCodeKind()1358 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()1359 ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
1360
1361 private:
1362 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreTransition);
1363 DEFINE_TURBOFAN_CODE_STUB(StoreMap, TurboFanCodeStub);
1364 };
1365
1366 class StoreTransitionStub : public TurboFanCodeStub {
1367 public:
1368 enum StoreMode {
1369 StoreMapAndValue,
1370 ExtendStorageAndStoreMapAndValue
1371 };
1372
StoreTransitionStub(Isolate * isolate,bool is_inobject,Representation representation,StoreMode store_mode)1373 StoreTransitionStub(Isolate* isolate, bool is_inobject,
1374 Representation representation, StoreMode store_mode)
1375 : TurboFanCodeStub(isolate) {
1376 minor_key_ = IsInobjectBits::encode(is_inobject) |
1377 RepresentationBits::encode(representation.kind()) |
1378 StoreModeBits::encode(store_mode);
1379 }
1380
GetCodeKind()1381 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()1382 ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
1383
is_inobject()1384 bool is_inobject() const { return IsInobjectBits::decode(minor_key_); }
1385
representation()1386 Representation representation() const {
1387 return Representation::FromKind(RepresentationBits::decode(minor_key_));
1388 }
1389
store_mode()1390 StoreMode store_mode() const { return StoreModeBits::decode(minor_key_); }
1391
1392 private:
1393 class IsInobjectBits : public BitField<bool, 0, 1> {};
1394 class RepresentationBits
1395 : public BitField<Representation::Kind, IsInobjectBits::kNext, 4> {};
1396 STATIC_ASSERT(Representation::kNumRepresentations - 1 <
1397 RepresentationBits::kMax);
1398 class StoreModeBits
1399 : public BitField<StoreMode, RepresentationBits::kNext, 1> {};
1400
1401 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreNamedTransition);
1402 DEFINE_TURBOFAN_CODE_STUB(StoreTransition, TurboFanCodeStub);
1403 };
1404
1405 class StoreGlobalStub : public TurboFanCodeStub {
1406 public:
StoreGlobalStub(Isolate * isolate,PropertyCellType type,Maybe<PropertyCellConstantType> constant_type,bool check_global)1407 StoreGlobalStub(Isolate* isolate, PropertyCellType type,
1408 Maybe<PropertyCellConstantType> constant_type,
1409 bool check_global)
1410 : TurboFanCodeStub(isolate) {
1411 PropertyCellConstantType encoded_constant_type =
1412 constant_type.FromMaybe(PropertyCellConstantType::kSmi);
1413 minor_key_ = CellTypeBits::encode(type) |
1414 ConstantTypeBits::encode(encoded_constant_type) |
1415 CheckGlobalBits::encode(check_global);
1416 }
1417
GetCodeKind()1418 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()1419 ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
1420
property_cell_placeholder(Isolate * isolate)1421 static Handle<HeapObject> property_cell_placeholder(Isolate* isolate) {
1422 return isolate->factory()->uninitialized_value();
1423 }
1424
global_map_placeholder(Isolate * isolate)1425 static Handle<HeapObject> global_map_placeholder(Isolate* isolate) {
1426 return isolate->factory()->termination_exception();
1427 }
1428
GetCodeCopyFromTemplate(Handle<JSGlobalObject> global,Handle<PropertyCell> cell)1429 Handle<Code> GetCodeCopyFromTemplate(Handle<JSGlobalObject> global,
1430 Handle<PropertyCell> cell) {
1431 Code::FindAndReplacePattern pattern;
1432 if (check_global()) {
1433 pattern.Add(handle(global_map_placeholder(isolate())->map()),
1434 Map::WeakCellForMap(Handle<Map>(global->map())));
1435 }
1436 pattern.Add(handle(property_cell_placeholder(isolate())->map()),
1437 isolate()->factory()->NewWeakCell(cell));
1438 return CodeStub::GetCodeCopy(pattern);
1439 }
1440
cell_type()1441 PropertyCellType cell_type() const {
1442 return CellTypeBits::decode(minor_key_);
1443 }
1444
constant_type()1445 PropertyCellConstantType constant_type() const {
1446 DCHECK(PropertyCellType::kConstantType == cell_type());
1447 return ConstantTypeBits::decode(minor_key_);
1448 }
1449
check_global()1450 bool check_global() const { return CheckGlobalBits::decode(minor_key_); }
1451
1452 private:
1453 class CellTypeBits : public BitField<PropertyCellType, 0, 2> {};
1454 class ConstantTypeBits
1455 : public BitField<PropertyCellConstantType, CellTypeBits::kNext, 2> {};
1456 class CheckGlobalBits : public BitField<bool, ConstantTypeBits::kNext, 1> {};
1457
1458 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
1459 DEFINE_TURBOFAN_CODE_STUB(StoreGlobal, TurboFanCodeStub);
1460 };
1461
1462 class CallApiCallbackStub : public PlatformCodeStub {
1463 public:
1464 static const int kArgBits = 3;
1465 static const int kArgMax = (1 << kArgBits) - 1;
1466
1467 // CallApiCallbackStub for regular setters and getters.
CallApiCallbackStub(Isolate * isolate,bool is_store,bool call_data_undefined,bool is_lazy)1468 CallApiCallbackStub(Isolate* isolate, bool is_store, bool call_data_undefined,
1469 bool is_lazy)
1470 : CallApiCallbackStub(isolate, is_store ? 1 : 0, is_store,
1471 call_data_undefined, is_lazy) {}
1472
1473 // CallApiCallbackStub for callback functions.
CallApiCallbackStub(Isolate * isolate,int argc,bool call_data_undefined,bool is_lazy)1474 CallApiCallbackStub(Isolate* isolate, int argc, bool call_data_undefined,
1475 bool is_lazy)
1476 : CallApiCallbackStub(isolate, argc, false, call_data_undefined,
1477 is_lazy) {}
1478
1479 private:
CallApiCallbackStub(Isolate * isolate,int argc,bool is_store,bool call_data_undefined,bool is_lazy)1480 CallApiCallbackStub(Isolate* isolate, int argc, bool is_store,
1481 bool call_data_undefined, bool is_lazy)
1482 : PlatformCodeStub(isolate) {
1483 CHECK(0 <= argc && argc <= kArgMax);
1484 minor_key_ = IsStoreBits::encode(is_store) |
1485 CallDataUndefinedBits::encode(call_data_undefined) |
1486 ArgumentBits::encode(argc) |
1487 IsLazyAccessorBits::encode(is_lazy);
1488 }
1489
is_store()1490 bool is_store() const { return IsStoreBits::decode(minor_key_); }
is_lazy()1491 bool is_lazy() const { return IsLazyAccessorBits::decode(minor_key_); }
call_data_undefined()1492 bool call_data_undefined() const {
1493 return CallDataUndefinedBits::decode(minor_key_);
1494 }
argc()1495 int argc() const { return ArgumentBits::decode(minor_key_); }
1496
1497 class IsStoreBits: public BitField<bool, 0, 1> {};
1498 class CallDataUndefinedBits: public BitField<bool, 1, 1> {};
1499 class ArgumentBits : public BitField<int, 2, kArgBits> {};
1500 class IsLazyAccessorBits : public BitField<bool, 3 + kArgBits, 1> {};
1501
1502 DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiCallback);
1503 DEFINE_PLATFORM_CODE_STUB(CallApiCallback, PlatformCodeStub);
1504 };
1505
1506
1507 class CallApiGetterStub : public PlatformCodeStub {
1508 public:
CallApiGetterStub(Isolate * isolate)1509 explicit CallApiGetterStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
1510
1511 DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiGetter);
1512 DEFINE_PLATFORM_CODE_STUB(CallApiGetter, PlatformCodeStub);
1513 };
1514
1515
1516 class BinaryOpICStub : public HydrogenCodeStub {
1517 public:
BinaryOpICStub(Isolate * isolate,Token::Value op)1518 BinaryOpICStub(Isolate* isolate, Token::Value op)
1519 : HydrogenCodeStub(isolate, UNINITIALIZED) {
1520 BinaryOpICState state(isolate, op);
1521 set_sub_minor_key(state.GetExtraICState());
1522 }
1523
BinaryOpICStub(Isolate * isolate,const BinaryOpICState & state)1524 BinaryOpICStub(Isolate* isolate, const BinaryOpICState& state)
1525 : HydrogenCodeStub(isolate) {
1526 set_sub_minor_key(state.GetExtraICState());
1527 }
1528
1529 static void GenerateAheadOfTime(Isolate* isolate);
1530
GetCodeKind()1531 Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; }
1532
GetExtraICState()1533 ExtraICState GetExtraICState() const final {
1534 return static_cast<ExtraICState>(sub_minor_key());
1535 }
1536
state()1537 BinaryOpICState state() const {
1538 return BinaryOpICState(isolate(), GetExtraICState());
1539 }
1540
1541 void PrintState(std::ostream& os) const final; // NOLINT
1542
1543 private:
1544 static void GenerateAheadOfTime(Isolate* isolate,
1545 const BinaryOpICState& state);
1546
1547 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1548 DEFINE_HYDROGEN_CODE_STUB(BinaryOpIC, HydrogenCodeStub);
1549 };
1550
1551
1552 // TODO(bmeurer): Merge this into the BinaryOpICStub once we have proper tail
1553 // call support for stubs in Hydrogen.
1554 class BinaryOpICWithAllocationSiteStub final : public PlatformCodeStub {
1555 public:
BinaryOpICWithAllocationSiteStub(Isolate * isolate,const BinaryOpICState & state)1556 BinaryOpICWithAllocationSiteStub(Isolate* isolate,
1557 const BinaryOpICState& state)
1558 : PlatformCodeStub(isolate) {
1559 minor_key_ = state.GetExtraICState();
1560 }
1561
1562 static void GenerateAheadOfTime(Isolate* isolate);
1563
GetCodeCopyFromTemplate(Handle<AllocationSite> allocation_site)1564 Handle<Code> GetCodeCopyFromTemplate(Handle<AllocationSite> allocation_site) {
1565 Code::FindAndReplacePattern pattern;
1566 pattern.Add(isolate()->factory()->undefined_map(), allocation_site);
1567 return CodeStub::GetCodeCopy(pattern);
1568 }
1569
GetCodeKind()1570 Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; }
1571
GetExtraICState()1572 ExtraICState GetExtraICState() const override {
1573 return static_cast<ExtraICState>(minor_key_);
1574 }
1575
1576 void PrintState(std::ostream& os) const override; // NOLINT
1577
1578 private:
state()1579 BinaryOpICState state() const {
1580 return BinaryOpICState(isolate(), GetExtraICState());
1581 }
1582
1583 static void GenerateAheadOfTime(Isolate* isolate,
1584 const BinaryOpICState& state);
1585
1586 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1587 DEFINE_PLATFORM_CODE_STUB(BinaryOpICWithAllocationSite, PlatformCodeStub);
1588 };
1589
1590
1591 class BinaryOpWithAllocationSiteStub final : public BinaryOpICStub {
1592 public:
BinaryOpWithAllocationSiteStub(Isolate * isolate,Token::Value op)1593 BinaryOpWithAllocationSiteStub(Isolate* isolate, Token::Value op)
1594 : BinaryOpICStub(isolate, op) {}
1595
BinaryOpWithAllocationSiteStub(Isolate * isolate,const BinaryOpICState & state)1596 BinaryOpWithAllocationSiteStub(Isolate* isolate, const BinaryOpICState& state)
1597 : BinaryOpICStub(isolate, state) {}
1598
GetCodeKind()1599 Code::Kind GetCodeKind() const final { return Code::STUB; }
1600
1601 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1602 DEFINE_HYDROGEN_CODE_STUB(BinaryOpWithAllocationSite, BinaryOpICStub);
1603 };
1604
1605 class StringAddStub final : public TurboFanCodeStub {
1606 public:
StringAddStub(Isolate * isolate,StringAddFlags flags,PretenureFlag pretenure_flag)1607 StringAddStub(Isolate* isolate, StringAddFlags flags,
1608 PretenureFlag pretenure_flag)
1609 : TurboFanCodeStub(isolate) {
1610 minor_key_ = (StringAddFlagsBits::encode(flags) |
1611 PretenureFlagBits::encode(pretenure_flag));
1612 }
1613
flags()1614 StringAddFlags flags() const {
1615 return StringAddFlagsBits::decode(minor_key_);
1616 }
1617
pretenure_flag()1618 PretenureFlag pretenure_flag() const {
1619 return PretenureFlagBits::decode(minor_key_);
1620 }
1621
1622 private:
1623 class StringAddFlagsBits : public BitField<StringAddFlags, 0, 3> {};
1624 class PretenureFlagBits : public BitField<PretenureFlag, 3, 1> {};
1625
1626 void PrintBaseName(std::ostream& os) const override; // NOLINT
1627
1628 DEFINE_CALL_INTERFACE_DESCRIPTOR(StringAdd);
1629 DEFINE_TURBOFAN_CODE_STUB(StringAdd, TurboFanCodeStub);
1630 };
1631
1632
1633 class CompareICStub : public PlatformCodeStub {
1634 public:
CompareICStub(Isolate * isolate,Token::Value op,CompareICState::State left,CompareICState::State right,CompareICState::State state)1635 CompareICStub(Isolate* isolate, Token::Value op, CompareICState::State left,
1636 CompareICState::State right, CompareICState::State state)
1637 : PlatformCodeStub(isolate) {
1638 DCHECK(Token::IsCompareOp(op));
1639 DCHECK(OpBits::is_valid(op - Token::EQ));
1640 minor_key_ = OpBits::encode(op - Token::EQ) |
1641 LeftStateBits::encode(left) | RightStateBits::encode(right) |
1642 StateBits::encode(state);
1643 }
1644 // Creates uninitialized compare stub.
CompareICStub(Isolate * isolate,Token::Value op)1645 CompareICStub(Isolate* isolate, Token::Value op)
1646 : CompareICStub(isolate, op, CompareICState::UNINITIALIZED,
1647 CompareICState::UNINITIALIZED,
1648 CompareICState::UNINITIALIZED) {}
1649
CompareICStub(Isolate * isolate,ExtraICState extra_ic_state)1650 CompareICStub(Isolate* isolate, ExtraICState extra_ic_state)
1651 : PlatformCodeStub(isolate) {
1652 minor_key_ = extra_ic_state;
1653 }
1654
GetExtraICState()1655 ExtraICState GetExtraICState() const final {
1656 return static_cast<ExtraICState>(minor_key_);
1657 }
1658
set_known_map(Handle<Map> map)1659 void set_known_map(Handle<Map> map) { known_map_ = map; }
1660
1661 InlineCacheState GetICState() const;
1662
op()1663 Token::Value op() const {
1664 return static_cast<Token::Value>(Token::EQ + OpBits::decode(minor_key_));
1665 }
1666
left()1667 CompareICState::State left() const {
1668 return LeftStateBits::decode(minor_key_);
1669 }
right()1670 CompareICState::State right() const {
1671 return RightStateBits::decode(minor_key_);
1672 }
state()1673 CompareICState::State state() const { return StateBits::decode(minor_key_); }
1674
1675 private:
GetCodeKind()1676 Code::Kind GetCodeKind() const override { return Code::COMPARE_IC; }
1677
1678 void GenerateBooleans(MacroAssembler* masm);
1679 void GenerateSmis(MacroAssembler* masm);
1680 void GenerateNumbers(MacroAssembler* masm);
1681 void GenerateInternalizedStrings(MacroAssembler* masm);
1682 void GenerateStrings(MacroAssembler* masm);
1683 void GenerateUniqueNames(MacroAssembler* masm);
1684 void GenerateReceivers(MacroAssembler* masm);
1685 void GenerateMiss(MacroAssembler* masm);
1686 void GenerateKnownReceivers(MacroAssembler* masm);
1687 void GenerateGeneric(MacroAssembler* masm);
1688
strict()1689 bool strict() const { return op() == Token::EQ_STRICT; }
1690 Condition GetCondition() const;
1691
1692 // Although we don't cache anything in the special cache we have to define
1693 // this predicate to avoid appearance of code stubs with embedded maps in
1694 // the global stub cache.
UseSpecialCache()1695 bool UseSpecialCache() override {
1696 return state() == CompareICState::KNOWN_RECEIVER;
1697 }
1698
1699 class OpBits : public BitField<int, 0, 3> {};
1700 class LeftStateBits : public BitField<CompareICState::State, 3, 4> {};
1701 class RightStateBits : public BitField<CompareICState::State, 7, 4> {};
1702 class StateBits : public BitField<CompareICState::State, 11, 4> {};
1703
1704 Handle<Map> known_map_;
1705
1706 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1707 DEFINE_PLATFORM_CODE_STUB(CompareIC, PlatformCodeStub);
1708 };
1709
1710
1711 class CEntryStub : public PlatformCodeStub {
1712 public:
1713 CEntryStub(Isolate* isolate, int result_size,
1714 SaveFPRegsMode save_doubles = kDontSaveFPRegs,
1715 ArgvMode argv_mode = kArgvOnStack, bool builtin_exit_frame = false)
PlatformCodeStub(isolate)1716 : PlatformCodeStub(isolate) {
1717 minor_key_ = SaveDoublesBits::encode(save_doubles == kSaveFPRegs) |
1718 FrameTypeBits::encode(builtin_exit_frame) |
1719 ArgvMode::encode(argv_mode == kArgvInRegister);
1720 DCHECK(result_size == 1 || result_size == 2 || result_size == 3);
1721 minor_key_ = ResultSizeBits::update(minor_key_, result_size);
1722 }
1723
1724 // The version of this stub that doesn't save doubles is generated ahead of
1725 // time, so it's OK to call it from other stubs that can't cope with GC during
1726 // their code generation. On machines that always have gp registers (x64) we
1727 // can generate both variants ahead of time.
1728 static void GenerateAheadOfTime(Isolate* isolate);
1729
1730 private:
save_doubles()1731 bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
argv_in_register()1732 bool argv_in_register() const { return ArgvMode::decode(minor_key_); }
is_builtin_exit()1733 bool is_builtin_exit() const { return FrameTypeBits::decode(minor_key_); }
result_size()1734 int result_size() const { return ResultSizeBits::decode(minor_key_); }
1735
1736 bool NeedsImmovableCode() override;
1737
1738 class SaveDoublesBits : public BitField<bool, 0, 1> {};
1739 class ArgvMode : public BitField<bool, 1, 1> {};
1740 class FrameTypeBits : public BitField<bool, 2, 1> {};
1741 class ResultSizeBits : public BitField<int, 3, 3> {};
1742
1743 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1744 DEFINE_PLATFORM_CODE_STUB(CEntry, PlatformCodeStub);
1745 };
1746
1747
1748 class JSEntryStub : public PlatformCodeStub {
1749 public:
JSEntryStub(Isolate * isolate,StackFrame::Type type)1750 JSEntryStub(Isolate* isolate, StackFrame::Type type)
1751 : PlatformCodeStub(isolate) {
1752 DCHECK(type == StackFrame::ENTRY || type == StackFrame::ENTRY_CONSTRUCT);
1753 minor_key_ = StackFrameTypeBits::encode(type);
1754 }
1755
1756 private:
1757 void FinishCode(Handle<Code> code) override;
1758
PrintName(std::ostream & os)1759 void PrintName(std::ostream& os) const override { // NOLINT
1760 os << (type() == StackFrame::ENTRY ? "JSEntryStub"
1761 : "JSConstructEntryStub");
1762 }
1763
type()1764 StackFrame::Type type() const {
1765 return StackFrameTypeBits::decode(minor_key_);
1766 }
1767
1768 class StackFrameTypeBits : public BitField<StackFrame::Type, 0, 5> {};
1769
1770 int handler_offset_;
1771
1772 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1773 DEFINE_PLATFORM_CODE_STUB(JSEntry, PlatformCodeStub);
1774 };
1775
1776
1777 class RegExpExecStub: public PlatformCodeStub {
1778 public:
RegExpExecStub(Isolate * isolate)1779 explicit RegExpExecStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
1780
1781 DEFINE_CALL_INTERFACE_DESCRIPTOR(RegExpExec);
1782 DEFINE_PLATFORM_CODE_STUB(RegExpExec, PlatformCodeStub);
1783 };
1784
1785 // TODO(bmeurer/mvstanton): Turn CallConstructStub into ConstructICStub.
1786 class CallConstructStub final : public PlatformCodeStub {
1787 public:
CallConstructStub(Isolate * isolate)1788 explicit CallConstructStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
1789
1790 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallConstruct);
1791 DEFINE_PLATFORM_CODE_STUB(CallConstruct, PlatformCodeStub);
1792 };
1793
1794
1795 enum ReceiverCheckMode {
1796 // We don't know anything about the receiver.
1797 RECEIVER_IS_UNKNOWN,
1798
1799 // We know the receiver is a string.
1800 RECEIVER_IS_STRING
1801 };
1802
1803
1804 enum EmbedMode {
1805 // The code being generated is part of an IC handler, which may MISS
1806 // to an IC in failure cases.
1807 PART_OF_IC_HANDLER,
1808
1809 NOT_PART_OF_IC_HANDLER
1810 };
1811
1812
1813 // Generates code implementing String.prototype.charCodeAt.
1814 //
1815 // Only supports the case when the receiver is a string and the index
1816 // is a number (smi or heap number) that is a valid index into the
1817 // string. Additional index constraints are specified by the
1818 // flags. Otherwise, bails out to the provided labels.
1819 //
1820 // Register usage: |object| may be changed to another string in a way
1821 // that doesn't affect charCodeAt/charAt semantics, |index| is
1822 // preserved, |scratch| and |result| are clobbered.
1823 class StringCharCodeAtGenerator {
1824 public:
1825 StringCharCodeAtGenerator(Register object, Register index, Register result,
1826 Label* receiver_not_string, Label* index_not_number,
1827 Label* index_out_of_range,
1828 ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN)
object_(object)1829 : object_(object),
1830 index_(index),
1831 result_(result),
1832 receiver_not_string_(receiver_not_string),
1833 index_not_number_(index_not_number),
1834 index_out_of_range_(index_out_of_range),
1835 check_mode_(check_mode) {
1836 DCHECK(!result_.is(object_));
1837 DCHECK(!result_.is(index_));
1838 }
1839
1840 // Generates the fast case code. On the fallthrough path |result|
1841 // register contains the result.
1842 void GenerateFast(MacroAssembler* masm);
1843
1844 // Generates the slow case code. Must not be naturally
1845 // reachable. Expected to be put after a ret instruction (e.g., in
1846 // deferred code). Always jumps back to the fast case.
1847 void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode,
1848 const RuntimeCallHelper& call_helper);
1849
1850 // Skip handling slow case and directly jump to bailout.
SkipSlow(MacroAssembler * masm,Label * bailout)1851 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1852 masm->bind(&index_not_smi_);
1853 masm->bind(&call_runtime_);
1854 masm->jmp(bailout);
1855 }
1856
1857 private:
1858 Register object_;
1859 Register index_;
1860 Register result_;
1861
1862 Label* receiver_not_string_;
1863 Label* index_not_number_;
1864 Label* index_out_of_range_;
1865
1866 ReceiverCheckMode check_mode_;
1867
1868 Label call_runtime_;
1869 Label index_not_smi_;
1870 Label got_smi_index_;
1871 Label exit_;
1872
1873 DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
1874 };
1875
1876
1877 // Generates code for creating a one-char string from a char code.
1878 class StringCharFromCodeGenerator {
1879 public:
StringCharFromCodeGenerator(Register code,Register result)1880 StringCharFromCodeGenerator(Register code,
1881 Register result)
1882 : code_(code),
1883 result_(result) {
1884 DCHECK(!code_.is(result_));
1885 }
1886
1887 // Generates the fast case code. On the fallthrough path |result|
1888 // register contains the result.
1889 void GenerateFast(MacroAssembler* masm);
1890
1891 // Generates the slow case code. Must not be naturally
1892 // reachable. Expected to be put after a ret instruction (e.g., in
1893 // deferred code). Always jumps back to the fast case.
1894 void GenerateSlow(MacroAssembler* masm,
1895 const RuntimeCallHelper& call_helper);
1896
1897 // Skip handling slow case and directly jump to bailout.
SkipSlow(MacroAssembler * masm,Label * bailout)1898 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1899 masm->bind(&slow_case_);
1900 masm->jmp(bailout);
1901 }
1902
1903 private:
1904 Register code_;
1905 Register result_;
1906
1907 Label slow_case_;
1908 Label exit_;
1909
1910 DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
1911 };
1912
1913
1914 // Generates code implementing String.prototype.charAt.
1915 //
1916 // Only supports the case when the receiver is a string and the index
1917 // is a number (smi or heap number) that is a valid index into the
1918 // string. Additional index constraints are specified by the
1919 // flags. Otherwise, bails out to the provided labels.
1920 //
1921 // Register usage: |object| may be changed to another string in a way
1922 // that doesn't affect charCodeAt/charAt semantics, |index| is
1923 // preserved, |scratch1|, |scratch2|, and |result| are clobbered.
1924 class StringCharAtGenerator {
1925 public:
1926 StringCharAtGenerator(Register object, Register index, Register scratch,
1927 Register result, Label* receiver_not_string,
1928 Label* index_not_number, Label* index_out_of_range,
1929 ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN)
char_code_at_generator_(object,index,scratch,receiver_not_string,index_not_number,index_out_of_range,check_mode)1930 : char_code_at_generator_(object, index, scratch, receiver_not_string,
1931 index_not_number, index_out_of_range,
1932 check_mode),
1933 char_from_code_generator_(scratch, result) {}
1934
1935 // Generates the fast case code. On the fallthrough path |result|
1936 // register contains the result.
GenerateFast(MacroAssembler * masm)1937 void GenerateFast(MacroAssembler* masm) {
1938 char_code_at_generator_.GenerateFast(masm);
1939 char_from_code_generator_.GenerateFast(masm);
1940 }
1941
1942 // Generates the slow case code. Must not be naturally
1943 // reachable. Expected to be put after a ret instruction (e.g., in
1944 // deferred code). Always jumps back to the fast case.
GenerateSlow(MacroAssembler * masm,EmbedMode embed_mode,const RuntimeCallHelper & call_helper)1945 void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode,
1946 const RuntimeCallHelper& call_helper) {
1947 char_code_at_generator_.GenerateSlow(masm, embed_mode, call_helper);
1948 char_from_code_generator_.GenerateSlow(masm, call_helper);
1949 }
1950
1951 // Skip handling slow case and directly jump to bailout.
SkipSlow(MacroAssembler * masm,Label * bailout)1952 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1953 char_code_at_generator_.SkipSlow(masm, bailout);
1954 char_from_code_generator_.SkipSlow(masm, bailout);
1955 }
1956
1957 private:
1958 StringCharCodeAtGenerator char_code_at_generator_;
1959 StringCharFromCodeGenerator char_from_code_generator_;
1960
1961 DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
1962 };
1963
1964
1965 class LoadDictionaryElementStub : public HydrogenCodeStub {
1966 public:
LoadDictionaryElementStub(Isolate * isolate)1967 explicit LoadDictionaryElementStub(Isolate* isolate)
1968 : HydrogenCodeStub(isolate) {}
1969
1970 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
1971 DEFINE_HYDROGEN_CODE_STUB(LoadDictionaryElement, HydrogenCodeStub);
1972 };
1973
1974 class LoadICTrampolineStub : public TurboFanCodeStub {
1975 public:
LoadICTrampolineStub(Isolate * isolate)1976 explicit LoadICTrampolineStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
1977
1978 void GenerateAssembly(CodeStubAssembler* assembler) const override;
1979
GetCodeKind()1980 Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
1981
1982 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1983 DEFINE_CODE_STUB(LoadICTrampoline, TurboFanCodeStub);
1984 };
1985
1986 class LoadGlobalICTrampolineStub : public TurboFanCodeStub {
1987 public:
LoadGlobalICTrampolineStub(Isolate * isolate,const LoadGlobalICState & state)1988 explicit LoadGlobalICTrampolineStub(Isolate* isolate,
1989 const LoadGlobalICState& state)
1990 : TurboFanCodeStub(isolate) {
1991 minor_key_ = state.GetExtraICState();
1992 }
1993
1994 void GenerateAssembly(CodeStubAssembler* assembler) const override;
1995
GetCodeKind()1996 Code::Kind GetCodeKind() const override { return Code::LOAD_GLOBAL_IC; }
1997
GetExtraICState()1998 ExtraICState GetExtraICState() const final {
1999 return static_cast<ExtraICState>(minor_key_);
2000 }
2001
2002 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadGlobal);
2003 DEFINE_CODE_STUB(LoadGlobalICTrampoline, TurboFanCodeStub);
2004 };
2005
2006 class KeyedLoadICTrampolineTFStub : public LoadICTrampolineStub {
2007 public:
KeyedLoadICTrampolineTFStub(Isolate * isolate)2008 explicit KeyedLoadICTrampolineTFStub(Isolate* isolate)
2009 : LoadICTrampolineStub(isolate) {}
2010
2011 void GenerateAssembly(CodeStubAssembler* assembler) const override;
2012
GetCodeKind()2013 Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
2014
2015 DEFINE_CODE_STUB(KeyedLoadICTrampolineTF, LoadICTrampolineStub);
2016 };
2017
2018 class StoreICTrampolineStub : public TurboFanCodeStub {
2019 public:
StoreICTrampolineStub(Isolate * isolate,const StoreICState & state)2020 StoreICTrampolineStub(Isolate* isolate, const StoreICState& state)
2021 : TurboFanCodeStub(isolate) {
2022 minor_key_ = state.GetExtraICState();
2023 }
2024
2025 void GenerateAssembly(CodeStubAssembler* assembler) const override;
2026
GetCodeKind()2027 Code::Kind GetCodeKind() const override { return Code::STORE_IC; }
2028
GetExtraICState()2029 ExtraICState GetExtraICState() const final {
2030 return static_cast<ExtraICState>(minor_key_);
2031 }
2032
2033 protected:
state()2034 StoreICState state() const { return StoreICState(GetExtraICState()); }
2035
2036 DEFINE_CALL_INTERFACE_DESCRIPTOR(Store);
2037 DEFINE_CODE_STUB(StoreICTrampoline, TurboFanCodeStub);
2038 };
2039
2040 class KeyedStoreICTrampolineStub : public PlatformCodeStub {
2041 public:
KeyedStoreICTrampolineStub(Isolate * isolate,const StoreICState & state)2042 KeyedStoreICTrampolineStub(Isolate* isolate, const StoreICState& state)
2043 : PlatformCodeStub(isolate) {
2044 minor_key_ = state.GetExtraICState();
2045 }
2046
GetCodeKind()2047 Code::Kind GetCodeKind() const override { return Code::KEYED_STORE_IC; }
2048
GetExtraICState()2049 ExtraICState GetExtraICState() const final {
2050 return static_cast<ExtraICState>(minor_key_);
2051 }
2052
2053 protected:
state()2054 StoreICState state() const { return StoreICState(GetExtraICState()); }
2055
2056 private:
2057 DEFINE_CALL_INTERFACE_DESCRIPTOR(Store);
2058 DEFINE_PLATFORM_CODE_STUB(KeyedStoreICTrampoline, PlatformCodeStub);
2059 };
2060
2061 class KeyedStoreICTrampolineTFStub : public StoreICTrampolineStub {
2062 public:
KeyedStoreICTrampolineTFStub(Isolate * isolate,const StoreICState & state)2063 KeyedStoreICTrampolineTFStub(Isolate* isolate, const StoreICState& state)
2064 : StoreICTrampolineStub(isolate, state) {}
2065
2066 void GenerateAssembly(CodeStubAssembler* assembler) const override;
2067
GetCodeKind()2068 Code::Kind GetCodeKind() const override { return Code::KEYED_STORE_IC; }
2069
2070 DEFINE_CODE_STUB(KeyedStoreICTrampolineTF, StoreICTrampolineStub);
2071 };
2072
2073 class CallICTrampolineStub : public PlatformCodeStub {
2074 public:
CallICTrampolineStub(Isolate * isolate,const CallICState & state)2075 CallICTrampolineStub(Isolate* isolate, const CallICState& state)
2076 : PlatformCodeStub(isolate) {
2077 minor_key_ = state.GetExtraICState();
2078 }
2079
GetCodeKind()2080 Code::Kind GetCodeKind() const override { return Code::CALL_IC; }
2081
GetExtraICState()2082 ExtraICState GetExtraICState() const final {
2083 return static_cast<ExtraICState>(minor_key_);
2084 }
2085
2086 protected:
state()2087 CallICState state() const {
2088 return CallICState(static_cast<ExtraICState>(minor_key_));
2089 }
2090
2091 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunctionWithFeedback);
2092 DEFINE_PLATFORM_CODE_STUB(CallICTrampoline, PlatformCodeStub);
2093 };
2094
2095 class LoadICStub : public TurboFanCodeStub {
2096 public:
LoadICStub(Isolate * isolate)2097 explicit LoadICStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
2098
2099 void GenerateAssembly(CodeStubAssembler* assembler) const override;
2100
GetCodeKind()2101 Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
2102
2103 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
2104 DEFINE_CODE_STUB(LoadIC, TurboFanCodeStub);
2105 };
2106
2107 class LoadICProtoArrayStub : public TurboFanCodeStub {
2108 public:
LoadICProtoArrayStub(Isolate * isolate)2109 explicit LoadICProtoArrayStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
2110
2111 void GenerateAssembly(CodeStubAssembler* assembler) const override;
2112
2113 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadICProtoArray);
2114 DEFINE_CODE_STUB(LoadICProtoArray, TurboFanCodeStub);
2115 };
2116
2117 class LoadGlobalICStub : public TurboFanCodeStub {
2118 public:
LoadGlobalICStub(Isolate * isolate,const LoadGlobalICState & state)2119 explicit LoadGlobalICStub(Isolate* isolate, const LoadGlobalICState& state)
2120 : TurboFanCodeStub(isolate) {
2121 minor_key_ = state.GetExtraICState();
2122 }
2123
2124 void GenerateAssembly(CodeStubAssembler* assembler) const override;
2125
GetCodeKind()2126 Code::Kind GetCodeKind() const override { return Code::LOAD_GLOBAL_IC; }
2127
GetExtraICState()2128 ExtraICState GetExtraICState() const final {
2129 return static_cast<ExtraICState>(minor_key_);
2130 }
2131
2132 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadGlobalWithVector);
2133 DEFINE_CODE_STUB(LoadGlobalIC, TurboFanCodeStub);
2134 };
2135
2136 class KeyedLoadICTFStub : public LoadICStub {
2137 public:
KeyedLoadICTFStub(Isolate * isolate)2138 explicit KeyedLoadICTFStub(Isolate* isolate) : LoadICStub(isolate) {}
2139
2140 void GenerateAssembly(CodeStubAssembler* assembler) const override;
2141
GetCodeKind()2142 Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
2143
2144 DEFINE_CODE_STUB(KeyedLoadICTF, LoadICStub);
2145 };
2146
2147 class StoreICStub : public TurboFanCodeStub {
2148 public:
StoreICStub(Isolate * isolate,const StoreICState & state)2149 StoreICStub(Isolate* isolate, const StoreICState& state)
2150 : TurboFanCodeStub(isolate) {
2151 minor_key_ = state.GetExtraICState();
2152 }
2153
2154 void GenerateAssembly(CodeStubAssembler* assembler) const override;
2155
GetCodeKind()2156 Code::Kind GetCodeKind() const override { return Code::STORE_IC; }
GetExtraICState()2157 ExtraICState GetExtraICState() const final {
2158 return static_cast<ExtraICState>(minor_key_);
2159 }
2160
2161 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
2162 DEFINE_CODE_STUB(StoreIC, TurboFanCodeStub);
2163 };
2164
2165 class KeyedStoreICStub : public PlatformCodeStub {
2166 public:
KeyedStoreICStub(Isolate * isolate,const StoreICState & state)2167 KeyedStoreICStub(Isolate* isolate, const StoreICState& state)
2168 : PlatformCodeStub(isolate) {
2169 minor_key_ = state.GetExtraICState();
2170 }
2171
2172 void GenerateForTrampoline(MacroAssembler* masm);
2173
GetCodeKind()2174 Code::Kind GetCodeKind() const final { return Code::KEYED_STORE_IC; }
2175
GetExtraICState()2176 ExtraICState GetExtraICState() const final {
2177 return static_cast<ExtraICState>(minor_key_);
2178 }
2179
2180 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
2181 DEFINE_PLATFORM_CODE_STUB(KeyedStoreIC, PlatformCodeStub);
2182
2183 protected:
2184 void GenerateImpl(MacroAssembler* masm, bool in_frame);
2185 };
2186
2187 class KeyedStoreICTFStub : public StoreICStub {
2188 public:
KeyedStoreICTFStub(Isolate * isolate,const StoreICState & state)2189 KeyedStoreICTFStub(Isolate* isolate, const StoreICState& state)
2190 : StoreICStub(isolate, state) {}
2191
2192 void GenerateAssembly(CodeStubAssembler* assembler) const override;
2193
GetCodeKind()2194 Code::Kind GetCodeKind() const override { return Code::KEYED_STORE_IC; }
2195
2196 DEFINE_CODE_STUB(KeyedStoreICTF, StoreICStub);
2197 };
2198
2199 class DoubleToIStub : public PlatformCodeStub {
2200 public:
2201 DoubleToIStub(Isolate* isolate, Register source, Register destination,
2202 int offset, bool is_truncating, bool skip_fastpath = false)
PlatformCodeStub(isolate)2203 : PlatformCodeStub(isolate) {
2204 minor_key_ = SourceRegisterBits::encode(source.code()) |
2205 DestinationRegisterBits::encode(destination.code()) |
2206 OffsetBits::encode(offset) |
2207 IsTruncatingBits::encode(is_truncating) |
2208 SkipFastPathBits::encode(skip_fastpath) |
2209 SSE3Bits::encode(CpuFeatures::IsSupported(SSE3) ? 1 : 0);
2210 }
2211
SometimesSetsUpAFrame()2212 bool SometimesSetsUpAFrame() override { return false; }
2213
2214 private:
source()2215 Register source() const {
2216 return Register::from_code(SourceRegisterBits::decode(minor_key_));
2217 }
destination()2218 Register destination() const {
2219 return Register::from_code(DestinationRegisterBits::decode(minor_key_));
2220 }
is_truncating()2221 bool is_truncating() const { return IsTruncatingBits::decode(minor_key_); }
skip_fastpath()2222 bool skip_fastpath() const { return SkipFastPathBits::decode(minor_key_); }
offset()2223 int offset() const { return OffsetBits::decode(minor_key_); }
2224
2225 static const int kBitsPerRegisterNumber = 6;
2226 STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
2227 class SourceRegisterBits:
2228 public BitField<int, 0, kBitsPerRegisterNumber> {}; // NOLINT
2229 class DestinationRegisterBits:
2230 public BitField<int, kBitsPerRegisterNumber,
2231 kBitsPerRegisterNumber> {}; // NOLINT
2232 class IsTruncatingBits:
2233 public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {}; // NOLINT
2234 class OffsetBits:
2235 public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {}; // NOLINT
2236 class SkipFastPathBits:
2237 public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {}; // NOLINT
2238 class SSE3Bits:
2239 public BitField<int, 2 * kBitsPerRegisterNumber + 5, 1> {}; // NOLINT
2240
2241 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2242 DEFINE_PLATFORM_CODE_STUB(DoubleToI, PlatformCodeStub);
2243 };
2244
2245 class ScriptContextFieldStub : public TurboFanCodeStub {
2246 public:
ScriptContextFieldStub(Isolate * isolate,const ScriptContextTable::LookupResult * lookup_result)2247 ScriptContextFieldStub(Isolate* isolate,
2248 const ScriptContextTable::LookupResult* lookup_result)
2249 : TurboFanCodeStub(isolate) {
2250 DCHECK(Accepted(lookup_result));
2251 minor_key_ = ContextIndexBits::encode(lookup_result->context_index) |
2252 SlotIndexBits::encode(lookup_result->slot_index);
2253 }
2254
GetCodeKind()2255 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
2256
context_index()2257 int context_index() const { return ContextIndexBits::decode(minor_key_); }
2258
slot_index()2259 int slot_index() const { return SlotIndexBits::decode(minor_key_); }
2260
Accepted(const ScriptContextTable::LookupResult * lookup_result)2261 static bool Accepted(const ScriptContextTable::LookupResult* lookup_result) {
2262 return ContextIndexBits::is_valid(lookup_result->context_index) &&
2263 SlotIndexBits::is_valid(lookup_result->slot_index);
2264 }
2265
2266 private:
2267 static const int kContextIndexBits = 9;
2268 static const int kSlotIndexBits = 12;
2269 class ContextIndexBits : public BitField<int, 0, kContextIndexBits> {};
2270 class SlotIndexBits
2271 : public BitField<int, kContextIndexBits, kSlotIndexBits> {};
2272
2273 DEFINE_CODE_STUB_BASE(ScriptContextFieldStub, TurboFanCodeStub);
2274 };
2275
2276
2277 class LoadScriptContextFieldStub : public ScriptContextFieldStub {
2278 public:
LoadScriptContextFieldStub(Isolate * isolate,const ScriptContextTable::LookupResult * lookup_result)2279 LoadScriptContextFieldStub(
2280 Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
2281 : ScriptContextFieldStub(isolate, lookup_result) {}
2282
GetExtraICState()2283 ExtraICState GetExtraICState() const override { return Code::LOAD_IC; }
2284
2285 private:
2286 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
2287 DEFINE_TURBOFAN_CODE_STUB(LoadScriptContextField, ScriptContextFieldStub);
2288 };
2289
2290
2291 class StoreScriptContextFieldStub : public ScriptContextFieldStub {
2292 public:
StoreScriptContextFieldStub(Isolate * isolate,const ScriptContextTable::LookupResult * lookup_result)2293 StoreScriptContextFieldStub(
2294 Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
2295 : ScriptContextFieldStub(isolate, lookup_result) {}
2296
GetExtraICState()2297 ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
2298
2299 private:
2300 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
2301 DEFINE_TURBOFAN_CODE_STUB(StoreScriptContextField, ScriptContextFieldStub);
2302 };
2303
2304
2305 class LoadFastElementStub : public HandlerStub {
2306 public:
2307 LoadFastElementStub(Isolate* isolate, bool is_js_array,
2308 ElementsKind elements_kind,
2309 bool convert_hole_to_undefined = false)
HandlerStub(isolate)2310 : HandlerStub(isolate) {
2311 set_sub_minor_key(
2312 ElementsKindBits::encode(elements_kind) |
2313 IsJSArrayBits::encode(is_js_array) |
2314 CanConvertHoleToUndefined::encode(convert_hole_to_undefined));
2315 }
2316
kind()2317 Code::Kind kind() const override { return Code::KEYED_LOAD_IC; }
2318
is_js_array()2319 bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
convert_hole_to_undefined()2320 bool convert_hole_to_undefined() const {
2321 return CanConvertHoleToUndefined::decode(sub_minor_key());
2322 }
2323
elements_kind()2324 ElementsKind elements_kind() const {
2325 return ElementsKindBits::decode(sub_minor_key());
2326 }
2327
2328 private:
2329 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2330 class IsJSArrayBits: public BitField<bool, 8, 1> {};
2331 class CanConvertHoleToUndefined : public BitField<bool, 9, 1> {};
2332
2333 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
2334 DEFINE_HANDLER_CODE_STUB(LoadFastElement, HandlerStub);
2335 };
2336
2337 class StoreFastElementStub : public TurboFanCodeStub {
2338 public:
StoreFastElementStub(Isolate * isolate,bool is_js_array,ElementsKind elements_kind,KeyedAccessStoreMode mode)2339 StoreFastElementStub(Isolate* isolate, bool is_js_array,
2340 ElementsKind elements_kind, KeyedAccessStoreMode mode)
2341 : TurboFanCodeStub(isolate) {
2342 minor_key_ = CommonStoreModeBits::encode(mode) |
2343 ElementsKindBits::encode(elements_kind) |
2344 IsJSArrayBits::encode(is_js_array);
2345 }
2346
2347 static void GenerateAheadOfTime(Isolate* isolate);
2348
is_js_array()2349 bool is_js_array() const { return IsJSArrayBits::decode(minor_key_); }
2350
elements_kind()2351 ElementsKind elements_kind() const {
2352 return ElementsKindBits::decode(minor_key_);
2353 }
2354
store_mode()2355 KeyedAccessStoreMode store_mode() const {
2356 return CommonStoreModeBits::decode(minor_key_);
2357 }
2358
GetCodeKind()2359 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()2360 ExtraICState GetExtraICState() const override { return Code::KEYED_STORE_IC; }
2361
2362 private:
2363 class ElementsKindBits
2364 : public BitField<ElementsKind, CommonStoreModeBits::kNext, 8> {};
2365 class IsJSArrayBits : public BitField<bool, ElementsKindBits::kNext, 1> {};
2366
2367 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
2368 DEFINE_TURBOFAN_CODE_STUB(StoreFastElement, TurboFanCodeStub);
2369 };
2370
2371
2372 class TransitionElementsKindStub : public HydrogenCodeStub {
2373 public:
TransitionElementsKindStub(Isolate * isolate,ElementsKind from_kind,ElementsKind to_kind)2374 TransitionElementsKindStub(Isolate* isolate, ElementsKind from_kind,
2375 ElementsKind to_kind)
2376 : HydrogenCodeStub(isolate) {
2377 set_sub_minor_key(FromKindBits::encode(from_kind) |
2378 ToKindBits::encode(to_kind));
2379 }
2380
from_kind()2381 ElementsKind from_kind() const {
2382 return FromKindBits::decode(sub_minor_key());
2383 }
2384
to_kind()2385 ElementsKind to_kind() const { return ToKindBits::decode(sub_minor_key()); }
2386
2387 private:
2388 class FromKindBits: public BitField<ElementsKind, 8, 8> {};
2389 class ToKindBits: public BitField<ElementsKind, 0, 8> {};
2390
2391 DEFINE_CALL_INTERFACE_DESCRIPTOR(TransitionElementsKind);
2392 DEFINE_HYDROGEN_CODE_STUB(TransitionElementsKind, HydrogenCodeStub);
2393 };
2394
2395 class AllocateHeapNumberStub : public TurboFanCodeStub {
2396 public:
AllocateHeapNumberStub(Isolate * isolate)2397 explicit AllocateHeapNumberStub(Isolate* isolate)
2398 : TurboFanCodeStub(isolate) {}
2399
2400 void InitializeDescriptor(CodeStubDescriptor* descriptor) override;
2401 void GenerateAssembly(CodeStubAssembler* assembler) const override;
2402
2403 DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateHeapNumber);
2404 DEFINE_CODE_STUB(AllocateHeapNumber, TurboFanCodeStub);
2405 };
2406
2407 #define SIMD128_ALLOC_STUB(TYPE, Type, type, lane_count, lane_type) \
2408 class Allocate##Type##Stub : public TurboFanCodeStub { \
2409 public: \
2410 explicit Allocate##Type##Stub(Isolate* isolate) \
2411 : TurboFanCodeStub(isolate) {} \
2412 \
2413 void InitializeDescriptor(CodeStubDescriptor* descriptor) override; \
2414 void GenerateAssembly(CodeStubAssembler* assembler) const override; \
2415 \
2416 DEFINE_CALL_INTERFACE_DESCRIPTOR(Allocate##Type); \
2417 DEFINE_CODE_STUB(Allocate##Type, TurboFanCodeStub); \
2418 };
SIMD128_TYPES(SIMD128_ALLOC_STUB)2419 SIMD128_TYPES(SIMD128_ALLOC_STUB)
2420 #undef SIMD128_ALLOC_STUB
2421
2422 class CommonArrayConstructorStub : public TurboFanCodeStub {
2423 protected:
2424 CommonArrayConstructorStub(Isolate* isolate, ElementsKind kind,
2425 AllocationSiteOverrideMode override_mode)
2426 : TurboFanCodeStub(isolate) {
2427 // It only makes sense to override local allocation site behavior
2428 // if there is a difference between the global allocation site policy
2429 // for an ElementsKind and the desired usage of the stub.
2430 DCHECK(override_mode != DISABLE_ALLOCATION_SITES ||
2431 AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE);
2432 set_sub_minor_key(ElementsKindBits::encode(kind) |
2433 AllocationSiteOverrideModeBits::encode(override_mode));
2434 }
2435
2436 void set_sub_minor_key(uint32_t key) { minor_key_ = key; }
2437
2438 uint32_t sub_minor_key() const { return minor_key_; }
2439
2440 CommonArrayConstructorStub(uint32_t key, Isolate* isolate)
2441 : TurboFanCodeStub(key, isolate) {}
2442
2443 public:
2444 ElementsKind elements_kind() const {
2445 return ElementsKindBits::decode(sub_minor_key());
2446 }
2447
2448 AllocationSiteOverrideMode override_mode() const {
2449 return AllocationSiteOverrideModeBits::decode(sub_minor_key());
2450 }
2451
2452 static void GenerateStubsAheadOfTime(Isolate* isolate);
2453
2454 private:
2455 // Ensure data fits within available bits.
2456 STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
2457
2458 class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
2459 class AllocationSiteOverrideModeBits
2460 : public BitField<AllocationSiteOverrideMode, 8, 1> {}; // NOLINT
2461 };
2462
2463 class ArrayNoArgumentConstructorStub : public CommonArrayConstructorStub {
2464 public:
2465 ArrayNoArgumentConstructorStub(
2466 Isolate* isolate, ElementsKind kind,
2467 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
CommonArrayConstructorStub(isolate,kind,override_mode)2468 : CommonArrayConstructorStub(isolate, kind, override_mode) {}
2469
2470 private:
PrintName(std::ostream & os)2471 void PrintName(std::ostream& os) const override { // NOLINT
2472 os << "ArrayNoArgumentConstructorStub";
2473 }
2474
2475 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNoArgumentConstructor);
2476 DEFINE_TURBOFAN_CODE_STUB(ArrayNoArgumentConstructor,
2477 CommonArrayConstructorStub);
2478 };
2479
2480 class InternalArrayNoArgumentConstructorStub
2481 : public CommonArrayConstructorStub {
2482 public:
InternalArrayNoArgumentConstructorStub(Isolate * isolate,ElementsKind kind)2483 InternalArrayNoArgumentConstructorStub(Isolate* isolate, ElementsKind kind)
2484 : CommonArrayConstructorStub(isolate, kind, DONT_OVERRIDE) {}
2485
2486 private:
PrintName(std::ostream & os)2487 void PrintName(std::ostream& os) const override { // NOLINT
2488 os << "InternalArrayNoArgumentConstructorStub";
2489 }
2490
2491 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNoArgumentConstructor);
2492 DEFINE_TURBOFAN_CODE_STUB(InternalArrayNoArgumentConstructor,
2493 CommonArrayConstructorStub);
2494 };
2495
2496 class ArraySingleArgumentConstructorStub : public CommonArrayConstructorStub {
2497 public:
2498 ArraySingleArgumentConstructorStub(
2499 Isolate* isolate, ElementsKind kind,
2500 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
CommonArrayConstructorStub(isolate,kind,override_mode)2501 : CommonArrayConstructorStub(isolate, kind, override_mode) {}
2502
2503 private:
PrintName(std::ostream & os)2504 void PrintName(std::ostream& os) const override { // NOLINT
2505 os << "ArraySingleArgumentConstructorStub";
2506 }
2507
2508 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArraySingleArgumentConstructor);
2509 DEFINE_TURBOFAN_CODE_STUB(ArraySingleArgumentConstructor,
2510 CommonArrayConstructorStub);
2511 };
2512
2513 class InternalArraySingleArgumentConstructorStub
2514 : public CommonArrayConstructorStub {
2515 public:
InternalArraySingleArgumentConstructorStub(Isolate * isolate,ElementsKind kind)2516 InternalArraySingleArgumentConstructorStub(Isolate* isolate,
2517 ElementsKind kind)
2518 : CommonArrayConstructorStub(isolate, kind, DONT_OVERRIDE) {}
2519
2520 private:
PrintName(std::ostream & os)2521 void PrintName(std::ostream& os) const override { // NOLINT
2522 os << "InternalArraySingleArgumentConstructorStub";
2523 }
2524
2525 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArraySingleArgumentConstructor);
2526 DEFINE_TURBOFAN_CODE_STUB(InternalArraySingleArgumentConstructor,
2527 CommonArrayConstructorStub);
2528 };
2529
2530 class ArrayNArgumentsConstructorStub : public PlatformCodeStub {
2531 public:
ArrayNArgumentsConstructorStub(Isolate * isolate)2532 explicit ArrayNArgumentsConstructorStub(Isolate* isolate)
2533 : PlatformCodeStub(isolate) {}
2534
GetCallInterfaceDescriptor()2535 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
2536 return ArrayNArgumentsConstructorDescriptor(isolate());
2537 }
2538
2539 private:
2540 DEFINE_PLATFORM_CODE_STUB(ArrayNArgumentsConstructor, PlatformCodeStub);
2541 };
2542
2543 class StoreElementStub : public PlatformCodeStub {
2544 public:
StoreElementStub(Isolate * isolate,ElementsKind elements_kind,KeyedAccessStoreMode mode)2545 StoreElementStub(Isolate* isolate, ElementsKind elements_kind,
2546 KeyedAccessStoreMode mode)
2547 : PlatformCodeStub(isolate) {
2548 // TODO(jkummerow): Rename this stub to StoreSlowElementStub,
2549 // drop elements_kind parameter.
2550 DCHECK_EQ(DICTIONARY_ELEMENTS, elements_kind);
2551 minor_key_ = ElementsKindBits::encode(elements_kind) |
2552 CommonStoreModeBits::encode(mode);
2553 }
2554
GetCodeKind()2555 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()2556 ExtraICState GetExtraICState() const override { return Code::KEYED_STORE_IC; }
2557
2558 private:
elements_kind()2559 ElementsKind elements_kind() const {
2560 return ElementsKindBits::decode(minor_key_);
2561 }
2562
2563 class ElementsKindBits
2564 : public BitField<ElementsKind, CommonStoreModeBits::kNext, 8> {};
2565
2566 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
2567 DEFINE_PLATFORM_CODE_STUB(StoreElement, PlatformCodeStub);
2568 };
2569
2570 class ToBooleanICStub : public HydrogenCodeStub {
2571 public:
ToBooleanICStub(Isolate * isolate,ExtraICState state)2572 ToBooleanICStub(Isolate* isolate, ExtraICState state)
2573 : HydrogenCodeStub(isolate) {
2574 set_sub_minor_key(HintsBits::encode(static_cast<uint16_t>(state)));
2575 }
2576
2577 bool UpdateStatus(Handle<Object> object);
hints()2578 ToBooleanHints hints() const {
2579 return ToBooleanHints(HintsBits::decode(sub_minor_key()));
2580 }
2581
GetCodeKind()2582 Code::Kind GetCodeKind() const override { return Code::TO_BOOLEAN_IC; }
2583 void PrintState(std::ostream& os) const override; // NOLINT
2584
SometimesSetsUpAFrame()2585 bool SometimesSetsUpAFrame() override { return false; }
2586
GetUninitialized(Isolate * isolate)2587 static Handle<Code> GetUninitialized(Isolate* isolate) {
2588 return ToBooleanICStub(isolate, UNINITIALIZED).GetCode();
2589 }
2590
GetExtraICState()2591 ExtraICState GetExtraICState() const override { return hints(); }
2592
GetICState()2593 InlineCacheState GetICState() const {
2594 if (hints() == ToBooleanHint::kNone) {
2595 return ::v8::internal::UNINITIALIZED;
2596 } else {
2597 return MONOMORPHIC;
2598 }
2599 }
2600
2601 private:
ToBooleanICStub(Isolate * isolate,InitializationState init_state)2602 ToBooleanICStub(Isolate* isolate, InitializationState init_state)
2603 : HydrogenCodeStub(isolate, init_state) {}
2604
2605 static const int kNumHints = 9;
2606 STATIC_ASSERT(static_cast<int>(ToBooleanHint::kAny) ==
2607 ((1 << kNumHints) - 1));
2608 class HintsBits : public BitField<uint16_t, 0, kNumHints> {};
2609
2610 DEFINE_CALL_INTERFACE_DESCRIPTOR(TypeConversion);
2611 DEFINE_HYDROGEN_CODE_STUB(ToBooleanIC, HydrogenCodeStub);
2612 };
2613
2614 class ElementsTransitionAndStoreStub : public TurboFanCodeStub {
2615 public:
ElementsTransitionAndStoreStub(Isolate * isolate,ElementsKind from_kind,ElementsKind to_kind,bool is_jsarray,KeyedAccessStoreMode store_mode)2616 ElementsTransitionAndStoreStub(Isolate* isolate, ElementsKind from_kind,
2617 ElementsKind to_kind, bool is_jsarray,
2618 KeyedAccessStoreMode store_mode)
2619 : TurboFanCodeStub(isolate) {
2620 minor_key_ = CommonStoreModeBits::encode(store_mode) |
2621 FromBits::encode(from_kind) | ToBits::encode(to_kind) |
2622 IsJSArrayBits::encode(is_jsarray);
2623 }
2624
from_kind()2625 ElementsKind from_kind() const { return FromBits::decode(minor_key_); }
to_kind()2626 ElementsKind to_kind() const { return ToBits::decode(minor_key_); }
is_jsarray()2627 bool is_jsarray() const { return IsJSArrayBits::decode(minor_key_); }
store_mode()2628 KeyedAccessStoreMode store_mode() const {
2629 return CommonStoreModeBits::decode(minor_key_);
2630 }
2631
GetCodeKind()2632 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()2633 ExtraICState GetExtraICState() const override { return Code::KEYED_STORE_IC; }
2634
2635 private:
2636 class FromBits
2637 : public BitField<ElementsKind, CommonStoreModeBits::kNext, 8> {};
2638 class ToBits : public BitField<ElementsKind, 11, 8> {};
2639 class IsJSArrayBits : public BitField<bool, 19, 1> {};
2640
2641 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreTransition);
2642 DEFINE_TURBOFAN_CODE_STUB(ElementsTransitionAndStore, TurboFanCodeStub);
2643 };
2644
2645
2646 class StubFailureTrampolineStub : public PlatformCodeStub {
2647 public:
StubFailureTrampolineStub(Isolate * isolate,StubFunctionMode function_mode)2648 StubFailureTrampolineStub(Isolate* isolate, StubFunctionMode function_mode)
2649 : PlatformCodeStub(isolate) {
2650 minor_key_ = FunctionModeField::encode(function_mode);
2651 }
2652
2653 static void GenerateAheadOfTime(Isolate* isolate);
2654
2655 private:
function_mode()2656 StubFunctionMode function_mode() const {
2657 return FunctionModeField::decode(minor_key_);
2658 }
2659
2660 class FunctionModeField : public BitField<StubFunctionMode, 0, 1> {};
2661
2662 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2663 DEFINE_PLATFORM_CODE_STUB(StubFailureTrampoline, PlatformCodeStub);
2664 };
2665
2666
2667 class ProfileEntryHookStub : public PlatformCodeStub {
2668 public:
ProfileEntryHookStub(Isolate * isolate)2669 explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2670
2671 // The profile entry hook function is not allowed to cause a GC.
SometimesSetsUpAFrame()2672 bool SometimesSetsUpAFrame() override { return false; }
2673
2674 // Generates a call to the entry hook if it's enabled.
2675 static void MaybeCallEntryHook(MacroAssembler* masm);
2676
2677 private:
2678 static void EntryHookTrampoline(intptr_t function,
2679 intptr_t stack_pointer,
2680 Isolate* isolate);
2681
2682 // ProfileEntryHookStub is called at the start of a function, so it has the
2683 // same register set.
2684 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction)
2685 DEFINE_PLATFORM_CODE_STUB(ProfileEntryHook, PlatformCodeStub);
2686 };
2687
2688
2689 class StoreBufferOverflowStub : public PlatformCodeStub {
2690 public:
StoreBufferOverflowStub(Isolate * isolate,SaveFPRegsMode save_fp)2691 StoreBufferOverflowStub(Isolate* isolate, SaveFPRegsMode save_fp)
2692 : PlatformCodeStub(isolate) {
2693 minor_key_ = SaveDoublesBits::encode(save_fp == kSaveFPRegs);
2694 }
2695
2696 static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
SometimesSetsUpAFrame()2697 bool SometimesSetsUpAFrame() override { return false; }
2698
2699 private:
save_doubles()2700 bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
2701
2702 class SaveDoublesBits : public BitField<bool, 0, 1> {};
2703
2704 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2705 DEFINE_PLATFORM_CODE_STUB(StoreBufferOverflow, PlatformCodeStub);
2706 };
2707
2708 class SubStringStub : public TurboFanCodeStub {
2709 public:
SubStringStub(Isolate * isolate)2710 explicit SubStringStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
2711
2712 static compiler::Node* Generate(CodeStubAssembler* assembler,
2713 compiler::Node* string, compiler::Node* from,
2714 compiler::Node* to, compiler::Node* context);
2715
GenerateAssembly(CodeStubAssembler * assembler)2716 void GenerateAssembly(CodeStubAssembler* assembler) const override {
2717 assembler->Return(Generate(assembler,
2718 assembler->Parameter(Descriptor::kString),
2719 assembler->Parameter(Descriptor::kFrom),
2720 assembler->Parameter(Descriptor::kTo),
2721 assembler->Parameter(Descriptor::kContext)));
2722 }
2723
2724 DEFINE_CALL_INTERFACE_DESCRIPTOR(SubString);
2725 DEFINE_CODE_STUB(SubString, TurboFanCodeStub);
2726 };
2727
2728
2729 #undef DEFINE_CALL_INTERFACE_DESCRIPTOR
2730 #undef DEFINE_PLATFORM_CODE_STUB
2731 #undef DEFINE_HANDLER_CODE_STUB
2732 #undef DEFINE_HYDROGEN_CODE_STUB
2733 #undef DEFINE_CODE_STUB
2734 #undef DEFINE_CODE_STUB_BASE
2735
2736 } // namespace internal
2737 } // namespace v8
2738
2739 #endif // V8_CODE_STUBS_H_
2740