Line data Source code
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/factory.h"
11 : #include "src/globals.h"
12 : #include "src/interface-descriptors.h"
13 : #include "src/macro-assembler.h"
14 : #include "src/ostreams.h"
15 : #include "src/type-hints.h"
16 :
17 : namespace v8 {
18 : namespace internal {
19 :
20 : // Forward declarations.
21 : class CodeStubAssembler;
22 : namespace compiler {
23 : class CodeAssemblerLabel;
24 : class CodeAssemblerState;
25 : class Node;
26 : }
27 :
28 : // List of code stubs used on all platforms.
29 : #define CODE_STUB_LIST_ALL_PLATFORMS(V) \
30 : /* --- PlatformCodeStubs --- */ \
31 : V(ArrayConstructor) \
32 : V(CallApiCallback) \
33 : V(CallApiGetter) \
34 : V(CEntry) \
35 : V(DoubleToI) \
36 : V(InternalArrayConstructor) \
37 : V(JSEntry) \
38 : V(MathPow) \
39 : V(ProfileEntryHook) \
40 : V(RecordWrite) \
41 : V(StoreBufferOverflow) \
42 : V(StoreSlowElement) \
43 : V(NameDictionaryLookup) \
44 : /* --- TurboFanCodeStubs --- */ \
45 : V(ArrayNoArgumentConstructor) \
46 : V(ArraySingleArgumentConstructor) \
47 : V(ArrayNArgumentsConstructor) \
48 : V(InternalArrayNoArgumentConstructor) \
49 : V(InternalArraySingleArgumentConstructor) \
50 : V(ElementsTransitionAndStore) \
51 : V(KeyedLoadSloppyArguments) \
52 : V(KeyedStoreSloppyArguments) \
53 : V(LoadScriptContextField) \
54 : V(StoreScriptContextField) \
55 : V(NumberToString) \
56 : V(StringAdd) \
57 : V(GetProperty) \
58 : V(StoreFastElement) \
59 : V(StoreInterceptor) \
60 : V(TransitionElementsKind) \
61 : V(LoadIndexedInterceptor) \
62 : V(GrowArrayElements)
63 :
64 : // List of code stubs only used on ARM 32 bits platforms.
65 : #if V8_TARGET_ARCH_ARM
66 : #define CODE_STUB_LIST_ARM(V) V(DirectCEntry)
67 :
68 : #else
69 : #define CODE_STUB_LIST_ARM(V)
70 : #endif
71 :
72 : // List of code stubs only used on ARM 64 bits platforms.
73 : #if V8_TARGET_ARCH_ARM64
74 : #define CODE_STUB_LIST_ARM64(V) V(DirectCEntry)
75 :
76 : #else
77 : #define CODE_STUB_LIST_ARM64(V)
78 : #endif
79 :
80 : // List of code stubs only used on PPC platforms.
81 : #ifdef V8_TARGET_ARCH_PPC
82 : #define CODE_STUB_LIST_PPC(V) \
83 : V(DirectCEntry) \
84 : V(StoreRegistersState) \
85 : V(RestoreRegistersState)
86 : #else
87 : #define CODE_STUB_LIST_PPC(V)
88 : #endif
89 :
90 : // List of code stubs only used on MIPS platforms.
91 : #if V8_TARGET_ARCH_MIPS
92 : #define CODE_STUB_LIST_MIPS(V) \
93 : V(DirectCEntry) \
94 : V(RestoreRegistersState) \
95 : V(StoreRegistersState)
96 : #elif V8_TARGET_ARCH_MIPS64
97 : #define CODE_STUB_LIST_MIPS(V) \
98 : V(DirectCEntry) \
99 : V(RestoreRegistersState) \
100 : V(StoreRegistersState)
101 : #else
102 : #define CODE_STUB_LIST_MIPS(V)
103 : #endif
104 :
105 : // List of code stubs only used on S390 platforms.
106 : #ifdef V8_TARGET_ARCH_S390
107 : #define CODE_STUB_LIST_S390(V) \
108 : V(DirectCEntry) \
109 : V(StoreRegistersState) \
110 : V(RestoreRegistersState)
111 : #else
112 : #define CODE_STUB_LIST_S390(V)
113 : #endif
114 :
115 : // Combined list of code stubs.
116 : #define CODE_STUB_LIST(V) \
117 : CODE_STUB_LIST_ALL_PLATFORMS(V) \
118 : CODE_STUB_LIST_ARM(V) \
119 : CODE_STUB_LIST_ARM64(V) \
120 : CODE_STUB_LIST_PPC(V) \
121 : CODE_STUB_LIST_MIPS(V) \
122 : CODE_STUB_LIST_S390(V)
123 :
124 : static const int kHasReturnedMinusZeroSentinel = 1;
125 :
126 : class CodeStub : public ZoneObject {
127 : public:
128 : enum Major {
129 : // TODO(mvstanton): eliminate the NoCache key by getting rid
130 : // of the non-monomorphic-cache.
131 : NoCache = 0, // marker for stubs that do custom caching]
132 : #define DEF_ENUM(name) name,
133 : CODE_STUB_LIST(DEF_ENUM)
134 : #undef DEF_ENUM
135 : NUMBER_OF_IDS
136 : };
137 :
138 : // Retrieve the code for the stub. Generate the code if needed.
139 : Handle<Code> GetCode();
140 :
141 : static Major MajorKeyFromKey(uint32_t key) {
142 : return static_cast<Major>(MajorKeyBits::decode(key));
143 : }
144 : static uint32_t MinorKeyFromKey(uint32_t key) {
145 : return MinorKeyBits::decode(key);
146 : }
147 :
148 : // Gets the major key from a code object that is a code stub or binary op IC.
149 : static Major GetMajorKey(Code* code_stub);
150 :
151 : static uint32_t NoCacheKey() { return MajorKeyBits::encode(NoCache); }
152 :
153 : static const char* MajorName(Major major_key);
154 :
155 2490307 : explicit CodeStub(Isolate* isolate) : minor_key_(0), isolate_(isolate) {}
156 683939 : virtual ~CodeStub() {}
157 :
158 : static void GenerateStubsAheadOfTime(Isolate* isolate);
159 : static void GenerateFPStubs(Isolate* isolate);
160 :
161 : // Some stubs put untagged junk on the stack that cannot be scanned by the
162 : // GC. This means that we must be statically sure that no GC can occur while
163 : // they are running. If that is the case they should override this to return
164 : // true, which will cause an assertion if we try to call something that can
165 : // GC or if we try to put a stack frame on top of the junk, which would not
166 : // result in a traversable stack.
167 0 : virtual bool SometimesSetsUpAFrame() { return true; }
168 :
169 : // Lookup the code in the (possibly custom) cache.
170 : bool FindCodeInCache(Code** code_out);
171 :
172 : virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() const = 0;
173 :
174 0 : virtual int GetStackParameterCount() const {
175 0 : return GetCallInterfaceDescriptor().GetStackParameterCount();
176 : }
177 :
178 0 : virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) {}
179 :
180 : static void InitializeDescriptor(Isolate* isolate, uint32_t key,
181 : CodeStubDescriptor* desc);
182 :
183 : static MaybeHandle<Code> GetCode(Isolate* isolate, uint32_t key);
184 :
185 : // Returns information for computing the number key.
186 : virtual Major MajorKey() const = 0;
187 : uint32_t MinorKey() const { return minor_key_; }
188 :
189 : friend std::ostream& operator<<(std::ostream& os, const CodeStub& s) {
190 44268 : s.PrintName(os);
191 : return os;
192 : }
193 :
194 : Isolate* isolate() const { return isolate_; }
195 : void set_isolate(Isolate* isolate) {
196 : DCHECK_NOT_NULL(isolate);
197 : DCHECK(isolate_ == nullptr || isolate_ == isolate);
198 45519 : isolate_ = isolate;
199 : }
200 :
201 : void DeleteStubFromCacheForTesting();
202 :
203 : protected:
204 : CodeStub(uint32_t key, Isolate* isolate)
205 312 : : minor_key_(MinorKeyFromKey(key)), isolate_(isolate) {}
206 :
207 : // Generates the assembler code for the stub.
208 : virtual Handle<Code> GenerateCode() = 0;
209 :
210 : // Returns whether the code generated for this stub needs to be allocated as
211 : // a fixed (non-moveable) code object.
212 6376 : virtual bool NeedsImmovableCode() { return false; }
213 :
214 : virtual void PrintName(std::ostream& os) const; // NOLINT
215 : virtual void PrintBaseName(std::ostream& os) const; // NOLINT
216 43586 : virtual void PrintState(std::ostream& os) const { ; } // NOLINT
217 :
218 : // Computes the key based on major and minor.
219 2578859 : uint32_t GetKey() {
220 : DCHECK(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
221 2578859 : return MinorKeyBits::encode(MinorKey()) | MajorKeyBits::encode(MajorKey());
222 : }
223 :
224 : uint32_t minor_key_;
225 :
226 : private:
227 : // Perform bookkeeping required after code generation when stub code is
228 : // initially generated.
229 : void RecordCodeGeneration(Handle<Code> code);
230 :
231 : // Activate newly generated stub. Is called after
232 : // registering stub in the stub cache.
233 44268 : virtual void Activate(Code* code) { }
234 :
235 : // We use this dispatch to statically instantiate the correct code stub for
236 : // the given stub key and call the passed function with that code stub.
237 : typedef void (*DispatchedCall)(CodeStub* stub, void** value_out);
238 : static void Dispatch(Isolate* isolate, uint32_t key, void** value_out,
239 : DispatchedCall call);
240 :
241 : static void GetCodeDispatchCall(CodeStub* stub, void** value_out);
242 :
243 : STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits));
244 : class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
245 : class MinorKeyBits: public BitField<uint32_t,
246 : kStubMajorKeyBits, kStubMinorKeyBits> {}; // NOLINT
247 :
248 : friend class BreakPointIterator;
249 :
250 : Isolate* isolate_;
251 : };
252 :
253 :
254 : #define DEFINE_CODE_STUB_BASE(NAME, SUPER) \
255 : public: \
256 : NAME(uint32_t key, Isolate* isolate) : SUPER(key, isolate) {} \
257 : \
258 : private: \
259 : DISALLOW_COPY_AND_ASSIGN(NAME)
260 :
261 :
262 : #define DEFINE_CODE_STUB(NAME, SUPER) \
263 : public: \
264 : inline Major MajorKey() const override { return NAME; }; \
265 : \
266 : DEFINE_CODE_STUB_BASE(NAME##Stub, SUPER)
267 :
268 :
269 : #define DEFINE_PLATFORM_CODE_STUB(NAME, SUPER) \
270 : private: \
271 : void Generate(MacroAssembler* masm) override; \
272 : DEFINE_CODE_STUB(NAME, SUPER)
273 :
274 :
275 : #define DEFINE_TURBOFAN_CODE_STUB(NAME, SUPER) \
276 : public: \
277 : void GenerateAssembly(compiler::CodeAssemblerState* state) const override; \
278 : DEFINE_CODE_STUB(NAME, SUPER)
279 :
280 : #define DEFINE_HANDLER_CODE_STUB(NAME, SUPER) \
281 : public: \
282 : Handle<Code> GenerateCode() override; \
283 : DEFINE_CODE_STUB(NAME, SUPER)
284 :
285 : #define DEFINE_CALL_INTERFACE_DESCRIPTOR(NAME) \
286 : public: \
287 : typedef NAME##Descriptor Descriptor; \
288 : CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
289 : return Descriptor(isolate()); \
290 : }
291 :
292 : // There are some code stubs we just can't describe right now with a
293 : // CallInterfaceDescriptor. Isolate behavior for those cases with this macro.
294 : // An attempt to retrieve a descriptor will fail.
295 : #define DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR() \
296 : public: \
297 : CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
298 : UNREACHABLE(); \
299 : return CallInterfaceDescriptor(); \
300 : }
301 :
302 :
303 524679 : class PlatformCodeStub : public CodeStub {
304 : public:
305 : // Retrieve the code for the stub. Generate the code if needed.
306 : Handle<Code> GenerateCode() override;
307 :
308 : protected:
309 2225447 : explicit PlatformCodeStub(Isolate* isolate) : CodeStub(isolate) {}
310 :
311 : // Generates the assembler code for the stub.
312 : virtual void Generate(MacroAssembler* masm) = 0;
313 :
314 : // Generates the exception handler table for the stub.
315 : virtual Handle<HandlerTable> GenerateHandlerTable();
316 :
317 138 : DEFINE_CODE_STUB_BASE(PlatformCodeStub, CodeStub);
318 : };
319 :
320 :
321 : enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
322 :
323 :
324 : class CodeStubDescriptor {
325 : public:
326 : explicit CodeStubDescriptor(CodeStub* stub);
327 :
328 : CodeStubDescriptor(Isolate* isolate, uint32_t stub_key);
329 :
330 : void Initialize(Address deoptimization_handler = nullptr,
331 : int hint_stack_parameter_count = -1,
332 : StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
333 : void Initialize(Register stack_parameter_count,
334 : Address deoptimization_handler = nullptr,
335 : int hint_stack_parameter_count = -1,
336 : StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
337 :
338 : void SetMissHandler(Runtime::FunctionId id) {
339 : miss_handler_id_ = id;
340 : miss_handler_ = ExternalReference(Runtime::FunctionForId(id), isolate_);
341 : has_miss_handler_ = true;
342 : // Our miss handler infrastructure doesn't currently support
343 : // variable stack parameter counts.
344 : DCHECK(!stack_parameter_count_.is_valid());
345 : }
346 :
347 0 : void set_call_descriptor(CallInterfaceDescriptor d) { call_descriptor_ = d; }
348 : CallInterfaceDescriptor call_descriptor() const { return call_descriptor_; }
349 :
350 : int GetRegisterParameterCount() const {
351 : return call_descriptor().GetRegisterParameterCount();
352 : }
353 :
354 : int GetStackParameterCount() const {
355 : return call_descriptor().GetStackParameterCount();
356 : }
357 :
358 : int GetParameterCount() const {
359 : return call_descriptor().GetParameterCount();
360 : }
361 :
362 : Register GetRegisterParameter(int index) const {
363 : return call_descriptor().GetRegisterParameter(index);
364 : }
365 :
366 : MachineType GetParameterType(int index) const {
367 : return call_descriptor().GetParameterType(index);
368 : }
369 :
370 : ExternalReference miss_handler() const {
371 : DCHECK(has_miss_handler_);
372 : return miss_handler_;
373 : }
374 :
375 : Runtime::FunctionId miss_handler_id() const {
376 : DCHECK(has_miss_handler_);
377 : return miss_handler_id_;
378 : }
379 :
380 : bool has_miss_handler() const {
381 : return has_miss_handler_;
382 : }
383 :
384 : int GetHandlerParameterCount() const {
385 : int params = GetParameterCount();
386 : if (PassesArgumentsToDeoptimizationHandler()) {
387 : params += 1;
388 : }
389 : return params;
390 : }
391 :
392 : int hint_stack_parameter_count() const { return hint_stack_parameter_count_; }
393 : Register stack_parameter_count() const { return stack_parameter_count_; }
394 : StubFunctionMode function_mode() const { return function_mode_; }
395 : Address deoptimization_handler() const { return deoptimization_handler_; }
396 :
397 : private:
398 : bool PassesArgumentsToDeoptimizationHandler() const {
399 : return stack_parameter_count_.is_valid();
400 : }
401 :
402 : Isolate* isolate_;
403 : CallInterfaceDescriptor call_descriptor_;
404 : Register stack_parameter_count_;
405 : // If hint_stack_parameter_count_ > 0, the code stub can optimize the
406 : // return sequence. Default value is -1, which means it is ignored.
407 : int hint_stack_parameter_count_;
408 : StubFunctionMode function_mode_;
409 :
410 : Address deoptimization_handler_;
411 :
412 : ExternalReference miss_handler_;
413 : Runtime::FunctionId miss_handler_id_;
414 : bool has_miss_handler_;
415 : };
416 :
417 :
418 159260 : class TurboFanCodeStub : public CodeStub {
419 : public:
420 : // Retrieve the code for the stub. Generate the code if needed.
421 : Handle<Code> GenerateCode() override;
422 :
423 0 : int GetStackParameterCount() const override {
424 0 : return GetCallInterfaceDescriptor().GetStackParameterCount();
425 : }
426 :
427 : protected:
428 264860 : explicit TurboFanCodeStub(Isolate* isolate) : CodeStub(isolate) {}
429 :
430 : virtual void GenerateAssembly(compiler::CodeAssemblerState* state) const = 0;
431 :
432 : private:
433 108 : DEFINE_CODE_STUB_BASE(TurboFanCodeStub, CodeStub);
434 : };
435 :
436 : } // namespace internal
437 : } // namespace v8
438 :
439 : #if V8_TARGET_ARCH_IA32
440 : #include "src/ia32/code-stubs-ia32.h"
441 : #elif V8_TARGET_ARCH_X64
442 : #include "src/x64/code-stubs-x64.h"
443 : #elif V8_TARGET_ARCH_ARM64
444 : #include "src/arm64/code-stubs-arm64.h"
445 : #elif V8_TARGET_ARCH_ARM
446 : #include "src/arm/code-stubs-arm.h"
447 : #elif V8_TARGET_ARCH_PPC
448 : #include "src/ppc/code-stubs-ppc.h"
449 : #elif V8_TARGET_ARCH_MIPS
450 : #include "src/mips/code-stubs-mips.h"
451 : #elif V8_TARGET_ARCH_MIPS64
452 : #include "src/mips64/code-stubs-mips64.h"
453 : #elif V8_TARGET_ARCH_S390
454 : #include "src/s390/code-stubs-s390.h"
455 : #else
456 : #error Unsupported target architecture.
457 : #endif
458 :
459 : namespace v8 {
460 : namespace internal {
461 :
462 0 : class StoreInterceptorStub : public TurboFanCodeStub {
463 : public:
464 131 : explicit StoreInterceptorStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
465 :
466 166 : DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
467 469 : DEFINE_TURBOFAN_CODE_STUB(StoreInterceptor, TurboFanCodeStub);
468 : };
469 :
470 0 : class TransitionElementsKindStub : public TurboFanCodeStub {
471 : public:
472 : TransitionElementsKindStub(Isolate* isolate, ElementsKind from_kind,
473 : ElementsKind to_kind, bool is_jsarray)
474 62 : : TurboFanCodeStub(isolate) {
475 62 : set_sub_minor_key(FromKindBits::encode(from_kind) |
476 : ToKindBits::encode(to_kind) |
477 62 : IsJSArrayBits::encode(is_jsarray));
478 : }
479 :
480 62 : void set_sub_minor_key(uint32_t key) { minor_key_ = key; }
481 :
482 : uint32_t sub_minor_key() const { return minor_key_; }
483 :
484 : ElementsKind from_kind() const {
485 : return FromKindBits::decode(sub_minor_key());
486 : }
487 :
488 : ElementsKind to_kind() const { return ToKindBits::decode(sub_minor_key()); }
489 :
490 31 : bool is_jsarray() const { return IsJSArrayBits::decode(sub_minor_key()); }
491 :
492 : private:
493 : class ToKindBits : public BitField<ElementsKind, 0, 8> {};
494 : class FromKindBits : public BitField<ElementsKind, ToKindBits::kNext, 8> {};
495 : class IsJSArrayBits : public BitField<bool, FromKindBits::kNext, 1> {};
496 :
497 62 : DEFINE_CALL_INTERFACE_DESCRIPTOR(TransitionElementsKind);
498 192 : DEFINE_TURBOFAN_CODE_STUB(TransitionElementsKind, TurboFanCodeStub);
499 : };
500 :
501 0 : class LoadIndexedInterceptorStub : public TurboFanCodeStub {
502 : public:
503 : explicit LoadIndexedInterceptorStub(Isolate* isolate)
504 83 : : TurboFanCodeStub(isolate) {}
505 :
506 112 : DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
507 313 : DEFINE_TURBOFAN_CODE_STUB(LoadIndexedInterceptor, TurboFanCodeStub);
508 : };
509 :
510 : // ES6 [[Get]] operation.
511 0 : class GetPropertyStub : public TurboFanCodeStub {
512 : public:
513 3602 : explicit GetPropertyStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
514 :
515 62 : DEFINE_CALL_INTERFACE_DESCRIPTOR(GetProperty);
516 3732 : DEFINE_TURBOFAN_CODE_STUB(GetProperty, TurboFanCodeStub);
517 : };
518 :
519 0 : class NumberToStringStub final : public TurboFanCodeStub {
520 : public:
521 1612 : explicit NumberToStringStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
522 :
523 62 : DEFINE_CALL_INTERFACE_DESCRIPTOR(TypeConversion);
524 1742 : DEFINE_TURBOFAN_CODE_STUB(NumberToString, TurboFanCodeStub);
525 : };
526 :
527 0 : class GrowArrayElementsStub : public TurboFanCodeStub {
528 : public:
529 : GrowArrayElementsStub(Isolate* isolate, ElementsKind kind)
530 : : TurboFanCodeStub(isolate) {
531 : minor_key_ = ElementsKindBits::encode(GetHoleyElementsKind(kind));
532 : }
533 :
534 : ElementsKind elements_kind() const {
535 : return ElementsKindBits::decode(minor_key_);
536 : }
537 :
538 : private:
539 : class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
540 :
541 0 : DEFINE_CALL_INTERFACE_DESCRIPTOR(GrowArrayElements);
542 6 : DEFINE_TURBOFAN_CODE_STUB(GrowArrayElements, TurboFanCodeStub);
543 : };
544 :
545 : enum AllocationSiteOverrideMode {
546 : DONT_OVERRIDE,
547 : DISABLE_ALLOCATION_SITES,
548 : LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
549 : };
550 :
551 :
552 61 : class ArrayConstructorStub: public PlatformCodeStub {
553 : public:
554 : explicit ArrayConstructorStub(Isolate* isolate);
555 :
556 : private:
557 : void GenerateDispatchToArrayStub(MacroAssembler* masm,
558 : AllocationSiteOverrideMode mode);
559 :
560 0 : DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
561 443572 : DEFINE_PLATFORM_CODE_STUB(ArrayConstructor, PlatformCodeStub);
562 : };
563 :
564 :
565 0 : class InternalArrayConstructorStub: public PlatformCodeStub {
566 : public:
567 : explicit InternalArrayConstructorStub(Isolate* isolate);
568 :
569 : private:
570 : void GenerateCase(MacroAssembler* masm, ElementsKind kind);
571 :
572 0 : DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNArgumentsConstructor);
573 252 : DEFINE_PLATFORM_CODE_STUB(InternalArrayConstructor, PlatformCodeStub);
574 : };
575 :
576 :
577 0 : class MathPowStub: public PlatformCodeStub {
578 : public:
579 : enum ExponentType { INTEGER, DOUBLE, TAGGED };
580 :
581 : MathPowStub(Isolate* isolate, ExponentType exponent_type)
582 140 : : PlatformCodeStub(isolate) {
583 140 : minor_key_ = ExponentTypeBits::encode(exponent_type);
584 : }
585 :
586 0 : CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
587 0 : if (exponent_type() == TAGGED) {
588 0 : return MathPowTaggedDescriptor(isolate());
589 0 : } else if (exponent_type() == INTEGER) {
590 0 : return MathPowIntegerDescriptor(isolate());
591 : } else {
592 : // A CallInterfaceDescriptor doesn't specify double registers (yet).
593 : DCHECK_EQ(DOUBLE, exponent_type());
594 0 : return ContextOnlyDescriptor(isolate());
595 : }
596 : }
597 :
598 : private:
599 : ExponentType exponent_type() const {
600 : return ExponentTypeBits::decode(minor_key_);
601 : }
602 :
603 : class ExponentTypeBits : public BitField<ExponentType, 0, 2> {};
604 :
605 235 : DEFINE_PLATFORM_CODE_STUB(MathPow, PlatformCodeStub);
606 : };
607 :
608 0 : class KeyedLoadSloppyArgumentsStub : public TurboFanCodeStub {
609 : public:
610 : explicit KeyedLoadSloppyArgumentsStub(Isolate* isolate)
611 1826 : : TurboFanCodeStub(isolate) {}
612 :
613 : protected:
614 590 : DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
615 3012 : DEFINE_TURBOFAN_CODE_STUB(KeyedLoadSloppyArguments, TurboFanCodeStub);
616 : };
617 :
618 :
619 : class CommonStoreModeBits : public BitField<KeyedAccessStoreMode, 0, 3> {};
620 :
621 0 : class KeyedStoreSloppyArgumentsStub : public TurboFanCodeStub {
622 : public:
623 : explicit KeyedStoreSloppyArgumentsStub(Isolate* isolate,
624 : KeyedAccessStoreMode mode)
625 0 : : TurboFanCodeStub(isolate) {
626 0 : minor_key_ = CommonStoreModeBits::encode(mode);
627 : }
628 :
629 : protected:
630 0 : DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
631 6 : DEFINE_TURBOFAN_CODE_STUB(KeyedStoreSloppyArguments, TurboFanCodeStub);
632 : };
633 :
634 0 : class CallApiCallbackStub : public PlatformCodeStub {
635 : public:
636 : static const int kArgBits = 3;
637 : static const int kArgMax = (1 << kArgBits) - 1;
638 :
639 : // CallApiCallbackStub for regular setters and getters.
640 : CallApiCallbackStub(Isolate* isolate, bool is_store, bool is_lazy)
641 3786 : : CallApiCallbackStub(isolate, is_store ? 1 : 0, is_store, is_lazy) {}
642 :
643 : // CallApiCallbackStub for callback functions.
644 : CallApiCallbackStub(Isolate* isolate, int argc, bool is_lazy)
645 11126 : : CallApiCallbackStub(isolate, argc, false, is_lazy) {}
646 :
647 : private:
648 14912 : CallApiCallbackStub(Isolate* isolate, int argc, bool is_store, bool is_lazy)
649 14912 : : PlatformCodeStub(isolate) {
650 14912 : CHECK(0 <= argc && argc <= kArgMax);
651 14912 : minor_key_ = IsStoreBits::encode(is_store) |
652 14912 : ArgumentBits::encode(argc) |
653 14912 : IsLazyAccessorBits::encode(is_lazy);
654 14912 : }
655 :
656 : bool is_store() const { return IsStoreBits::decode(minor_key_); }
657 : bool is_lazy() const { return IsLazyAccessorBits::decode(minor_key_); }
658 : int argc() const { return ArgumentBits::decode(minor_key_); }
659 :
660 : class IsStoreBits: public BitField<bool, 0, 1> {};
661 : class IsLazyAccessorBits : public BitField<bool, 1, 1> {};
662 : class ArgumentBits : public BitField<int, 2, kArgBits> {};
663 :
664 22252 : DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiCallback);
665 25358 : DEFINE_PLATFORM_CODE_STUB(CallApiCallback, PlatformCodeStub);
666 : };
667 :
668 :
669 0 : class CallApiGetterStub : public PlatformCodeStub {
670 : public:
671 1178 : explicit CallApiGetterStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
672 :
673 0 : DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiGetter);
674 1277 : DEFINE_PLATFORM_CODE_STUB(CallApiGetter, PlatformCodeStub);
675 : };
676 :
677 :
678 0 : class StringAddStub final : public TurboFanCodeStub {
679 : public:
680 : StringAddStub(Isolate* isolate, StringAddFlags flags,
681 : PretenureFlag pretenure_flag)
682 48745 : : TurboFanCodeStub(isolate) {
683 48745 : minor_key_ = (StringAddFlagsBits::encode(flags) |
684 48745 : PretenureFlagBits::encode(pretenure_flag));
685 : }
686 :
687 : StringAddFlags flags() const {
688 : return StringAddFlagsBits::decode(minor_key_);
689 : }
690 :
691 : PretenureFlag pretenure_flag() const {
692 : return PretenureFlagBits::decode(minor_key_);
693 : }
694 :
695 : private:
696 : class StringAddFlagsBits : public BitField<StringAddFlags, 0, 3> {};
697 : class PretenureFlagBits : public BitField<PretenureFlag, 3, 1> {};
698 :
699 : void PrintBaseName(std::ostream& os) const override; // NOLINT
700 :
701 186 : DEFINE_CALL_INTERFACE_DESCRIPTOR(StringAdd);
702 49030 : DEFINE_TURBOFAN_CODE_STUB(StringAdd, TurboFanCodeStub);
703 : };
704 :
705 :
706 524492 : class CEntryStub : public PlatformCodeStub {
707 : public:
708 : CEntryStub(Isolate* isolate, int result_size,
709 : SaveFPRegsMode save_doubles = kDontSaveFPRegs,
710 : ArgvMode argv_mode = kArgvOnStack, bool builtin_exit_frame = false)
711 1609328 : : PlatformCodeStub(isolate) {
712 1785138 : minor_key_ = SaveDoublesBits::encode(save_doubles == kSaveFPRegs) |
713 891789 : FrameTypeBits::encode(builtin_exit_frame) |
714 1890218 : ArgvMode::encode(argv_mode == kArgvInRegister);
715 : DCHECK(result_size == 1 || result_size == 2);
716 1609328 : minor_key_ = ResultSizeBits::update(minor_key_, result_size);
717 : }
718 :
719 : // The version of this stub that doesn't save doubles is generated ahead of
720 : // time, so it's OK to call it from other stubs that can't cope with GC during
721 : // their code generation. On machines that always have gp registers (x64) we
722 : // can generate both variants ahead of time.
723 : static void GenerateAheadOfTime(Isolate* isolate);
724 :
725 : private:
726 : bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
727 : bool argv_in_register() const { return ArgvMode::decode(minor_key_); }
728 : bool is_builtin_exit() const { return FrameTypeBits::decode(minor_key_); }
729 : int result_size() const { return ResultSizeBits::decode(minor_key_); }
730 :
731 : bool NeedsImmovableCode() override;
732 :
733 : class SaveDoublesBits : public BitField<bool, 0, 1> {};
734 : class ArgvMode : public BitField<bool, 1, 1> {};
735 : class FrameTypeBits : public BitField<bool, 2, 1> {};
736 : class ResultSizeBits : public BitField<int, 3, 3> {};
737 :
738 0 : DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
739 1650879 : DEFINE_PLATFORM_CODE_STUB(CEntry, PlatformCodeStub);
740 : };
741 :
742 :
743 0 : class JSEntryStub : public PlatformCodeStub {
744 : public:
745 : JSEntryStub(Isolate* isolate, StackFrame::Type type)
746 62 : : PlatformCodeStub(isolate) {
747 : DCHECK(type == StackFrame::ENTRY || type == StackFrame::CONSTRUCT_ENTRY);
748 62 : minor_key_ = StackFrameTypeBits::encode(type);
749 : }
750 :
751 : private:
752 : Handle<HandlerTable> GenerateHandlerTable() override;
753 :
754 62 : void PrintName(std::ostream& os) const override { // NOLINT
755 : os << (type() == StackFrame::ENTRY ? "JSEntryStub"
756 62 : : "JSConstructEntryStub");
757 62 : }
758 :
759 : StackFrame::Type type() const {
760 : return StackFrameTypeBits::decode(minor_key_);
761 : }
762 :
763 : class StackFrameTypeBits : public BitField<StackFrame::Type, 0, 5> {};
764 :
765 : int handler_offset_;
766 :
767 0 : DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
768 192 : DEFINE_PLATFORM_CODE_STUB(JSEntry, PlatformCodeStub);
769 : };
770 :
771 :
772 : enum ReceiverCheckMode {
773 : // We don't know anything about the receiver.
774 : RECEIVER_IS_UNKNOWN,
775 :
776 : // We know the receiver is a string.
777 : RECEIVER_IS_STRING
778 : };
779 :
780 :
781 : enum EmbedMode {
782 : // The code being generated is part of an IC handler, which may MISS
783 : // to an IC in failure cases.
784 : PART_OF_IC_HANDLER,
785 :
786 : NOT_PART_OF_IC_HANDLER
787 : };
788 :
789 48 : class DoubleToIStub : public PlatformCodeStub {
790 : public:
791 : DoubleToIStub(Isolate* isolate, Register destination)
792 45458 : : PlatformCodeStub(isolate) {
793 45458 : minor_key_ = DestinationRegisterBits::encode(destination.code());
794 : }
795 :
796 0 : bool SometimesSetsUpAFrame() override { return false; }
797 :
798 : private:
799 : Register destination() const {
800 : return Register::from_code(DestinationRegisterBits::decode(minor_key_));
801 : }
802 :
803 : static const int kBitsPerRegisterNumber = 6;
804 : STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
805 : class DestinationRegisterBits
806 : : public BitField<int, 0, kBitsPerRegisterNumber> {}; // NOLINT
807 :
808 0 : DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
809 53293 : DEFINE_PLATFORM_CODE_STUB(DoubleToI, PlatformCodeStub);
810 : };
811 :
812 50 : class ScriptContextFieldStub : public TurboFanCodeStub {
813 : public:
814 : ScriptContextFieldStub(Isolate* isolate,
815 : const ScriptContextTable::LookupResult* lookup_result)
816 49404 : : TurboFanCodeStub(isolate) {
817 : DCHECK(Accepted(lookup_result));
818 98808 : minor_key_ = ContextIndexBits::encode(lookup_result->context_index) |
819 98808 : SlotIndexBits::encode(lookup_result->slot_index);
820 : }
821 :
822 : int context_index() const { return ContextIndexBits::decode(minor_key_); }
823 :
824 : int slot_index() const { return SlotIndexBits::decode(minor_key_); }
825 :
826 : static bool Accepted(const ScriptContextTable::LookupResult* lookup_result) {
827 148212 : return ContextIndexBits::is_valid(lookup_result->context_index) &&
828 49404 : SlotIndexBits::is_valid(lookup_result->slot_index);
829 : }
830 :
831 : private:
832 : static const int kContextIndexBits = 9;
833 : static const int kSlotIndexBits = 12;
834 : class ContextIndexBits : public BitField<int, 0, kContextIndexBits> {};
835 : class SlotIndexBits
836 : : public BitField<int, kContextIndexBits, kSlotIndexBits> {};
837 :
838 12 : DEFINE_CODE_STUB_BASE(ScriptContextFieldStub, TurboFanCodeStub);
839 : };
840 :
841 :
842 0 : class LoadScriptContextFieldStub : public ScriptContextFieldStub {
843 : public:
844 : LoadScriptContextFieldStub(
845 : Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
846 49366 : : ScriptContextFieldStub(isolate, lookup_result) {}
847 :
848 : private:
849 34866 : DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
850 119104 : DEFINE_TURBOFAN_CODE_STUB(LoadScriptContextField, ScriptContextFieldStub);
851 : };
852 :
853 :
854 38 : class StoreScriptContextFieldStub : public ScriptContextFieldStub {
855 : public:
856 : StoreScriptContextFieldStub(
857 : Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
858 38 : : ScriptContextFieldStub(isolate, lookup_result) {}
859 :
860 : private:
861 58 : DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
862 160 : DEFINE_TURBOFAN_CODE_STUB(StoreScriptContextField, ScriptContextFieldStub);
863 : };
864 :
865 154349 : class StoreFastElementStub : public TurboFanCodeStub {
866 : public:
867 : StoreFastElementStub(Isolate* isolate, bool is_js_array,
868 : ElementsKind elements_kind, KeyedAccessStoreMode mode)
869 154349 : : TurboFanCodeStub(isolate) {
870 153915 : minor_key_ = CommonStoreModeBits::encode(mode) |
871 154287 : ElementsKindBits::encode(elements_kind) |
872 154349 : IsJSArrayBits::encode(is_js_array);
873 : }
874 :
875 : static void GenerateAheadOfTime(Isolate* isolate);
876 :
877 : bool is_js_array() const { return IsJSArrayBits::decode(minor_key_); }
878 :
879 : ElementsKind elements_kind() const {
880 : return ElementsKindBits::decode(minor_key_);
881 : }
882 :
883 : KeyedAccessStoreMode store_mode() const {
884 : return CommonStoreModeBits::decode(minor_key_);
885 : }
886 :
887 : private:
888 : class ElementsKindBits
889 : : public BitField<ElementsKind, CommonStoreModeBits::kNext, 8> {};
890 : class IsJSArrayBits : public BitField<bool, ElementsKindBits::kNext, 1> {};
891 :
892 7802 : DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
893 169959 : DEFINE_TURBOFAN_CODE_STUB(StoreFastElement, TurboFanCodeStub);
894 : };
895 :
896 :
897 1047 : class CommonArrayConstructorStub : public TurboFanCodeStub {
898 : protected:
899 : CommonArrayConstructorStub(Isolate* isolate, ElementsKind kind,
900 : AllocationSiteOverrideMode override_mode);
901 :
902 1304 : void set_sub_minor_key(uint32_t key) { minor_key_ = key; }
903 :
904 : uint32_t sub_minor_key() const { return minor_key_; }
905 :
906 : CommonArrayConstructorStub(uint32_t key, Isolate* isolate)
907 24 : : TurboFanCodeStub(key, isolate) {}
908 :
909 : public:
910 620 : ElementsKind elements_kind() const {
911 : return ElementsKindBits::decode(sub_minor_key());
912 : }
913 :
914 372 : AllocationSiteOverrideMode override_mode() const {
915 : return AllocationSiteOverrideModeBits::decode(sub_minor_key());
916 : }
917 :
918 : static void GenerateStubsAheadOfTime(Isolate* isolate);
919 :
920 : private:
921 : // Ensure data fits within available bits.
922 : STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
923 :
924 : class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
925 : class AllocationSiteOverrideModeBits
926 : : public BitField<AllocationSiteOverrideMode, 8, 1> {}; // NOLINT
927 : };
928 :
929 434 : class ArrayNoArgumentConstructorStub : public CommonArrayConstructorStub {
930 : public:
931 : ArrayNoArgumentConstructorStub(
932 : Isolate* isolate, ElementsKind kind,
933 : AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
934 465 : : CommonArrayConstructorStub(isolate, kind, override_mode) {}
935 :
936 : private:
937 248 : void PrintName(std::ostream& os) const override { // NOLINT
938 248 : os << "ArrayNoArgumentConstructorStub";
939 248 : }
940 :
941 496 : DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNoArgumentConstructor);
942 1215 : DEFINE_TURBOFAN_CODE_STUB(ArrayNoArgumentConstructor,
943 : CommonArrayConstructorStub);
944 : };
945 :
946 62 : class InternalArrayNoArgumentConstructorStub
947 : : public CommonArrayConstructorStub {
948 : public:
949 : InternalArrayNoArgumentConstructorStub(Isolate* isolate, ElementsKind kind)
950 124 : : CommonArrayConstructorStub(isolate, kind, DONT_OVERRIDE) {}
951 :
952 : private:
953 62 : void PrintName(std::ostream& os) const override { // NOLINT
954 62 : os << "InternalArrayNoArgumentConstructorStub";
955 62 : }
956 :
957 124 : DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNoArgumentConstructor);
958 316 : DEFINE_TURBOFAN_CODE_STUB(InternalArrayNoArgumentConstructor,
959 : CommonArrayConstructorStub);
960 : };
961 :
962 434 : class ArraySingleArgumentConstructorStub : public CommonArrayConstructorStub {
963 : public:
964 : ArraySingleArgumentConstructorStub(
965 : Isolate* isolate, ElementsKind kind,
966 : AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
967 560 : : CommonArrayConstructorStub(isolate, kind, override_mode) {}
968 :
969 : private:
970 248 : void PrintName(std::ostream& os) const override { // NOLINT
971 248 : os << "ArraySingleArgumentConstructorStub";
972 248 : }
973 :
974 686 : DEFINE_CALL_INTERFACE_DESCRIPTOR(ArraySingleArgumentConstructor);
975 1310 : DEFINE_TURBOFAN_CODE_STUB(ArraySingleArgumentConstructor,
976 : CommonArrayConstructorStub);
977 : };
978 :
979 93 : class InternalArraySingleArgumentConstructorStub
980 : : public CommonArrayConstructorStub {
981 : public:
982 : InternalArraySingleArgumentConstructorStub(Isolate* isolate,
983 : ElementsKind kind)
984 155 : : CommonArrayConstructorStub(isolate, kind, DONT_OVERRIDE) {}
985 :
986 : private:
987 62 : void PrintName(std::ostream& os) const override { // NOLINT
988 62 : os << "InternalArraySingleArgumentConstructorStub";
989 62 : }
990 :
991 124 : DEFINE_CALL_INTERFACE_DESCRIPTOR(ArraySingleArgumentConstructor);
992 347 : DEFINE_TURBOFAN_CODE_STUB(InternalArraySingleArgumentConstructor,
993 : CommonArrayConstructorStub);
994 : };
995 :
996 0 : class ArrayNArgumentsConstructorStub : public PlatformCodeStub {
997 : public:
998 : explicit ArrayNArgumentsConstructorStub(Isolate* isolate)
999 155 : : PlatformCodeStub(isolate) {}
1000 :
1001 0 : CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
1002 0 : return ArrayNArgumentsConstructorDescriptor(isolate());
1003 : }
1004 :
1005 : private:
1006 254 : DEFINE_PLATFORM_CODE_STUB(ArrayNArgumentsConstructor, PlatformCodeStub);
1007 : };
1008 :
1009 1831 : class StoreSlowElementStub : public TurboFanCodeStub {
1010 : public:
1011 : StoreSlowElementStub(Isolate* isolate, KeyedAccessStoreMode mode)
1012 1831 : : TurboFanCodeStub(isolate) {
1013 1831 : minor_key_ = CommonStoreModeBits::encode(mode);
1014 : }
1015 :
1016 : private:
1017 1120 : DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
1018 4077 : DEFINE_TURBOFAN_CODE_STUB(StoreSlowElement, TurboFanCodeStub);
1019 : };
1020 :
1021 1911 : class ElementsTransitionAndStoreStub : public TurboFanCodeStub {
1022 : public:
1023 : ElementsTransitionAndStoreStub(Isolate* isolate, ElementsKind from_kind,
1024 : ElementsKind to_kind, bool is_jsarray,
1025 : KeyedAccessStoreMode store_mode)
1026 1911 : : TurboFanCodeStub(isolate) {
1027 1911 : minor_key_ = CommonStoreModeBits::encode(store_mode) |
1028 3822 : FromBits::encode(from_kind) | ToBits::encode(to_kind) |
1029 1911 : IsJSArrayBits::encode(is_jsarray);
1030 : }
1031 :
1032 : ElementsKind from_kind() const { return FromBits::decode(minor_key_); }
1033 : ElementsKind to_kind() const { return ToBits::decode(minor_key_); }
1034 : bool is_jsarray() const { return IsJSArrayBits::decode(minor_key_); }
1035 : KeyedAccessStoreMode store_mode() const {
1036 : return CommonStoreModeBits::decode(minor_key_);
1037 : }
1038 :
1039 : private:
1040 : class FromBits
1041 : : public BitField<ElementsKind, CommonStoreModeBits::kNext, 8> {};
1042 : class ToBits : public BitField<ElementsKind, 11, 8> {};
1043 : class IsJSArrayBits : public BitField<bool, 19, 1> {};
1044 :
1045 1760 : DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreTransition);
1046 5437 : DEFINE_TURBOFAN_CODE_STUB(ElementsTransitionAndStore, TurboFanCodeStub);
1047 : };
1048 :
1049 :
1050 0 : class ProfileEntryHookStub : public PlatformCodeStub {
1051 : public:
1052 0 : explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
1053 :
1054 : // The profile entry hook function is not allowed to cause a GC.
1055 0 : bool SometimesSetsUpAFrame() override { return false; }
1056 :
1057 : // Generates a call to the entry hook if it's enabled.
1058 : static void MaybeCallEntryHook(MacroAssembler* masm);
1059 : static void MaybeCallEntryHookDelayed(TurboAssembler* tasm, Zone* zone);
1060 :
1061 : private:
1062 : static void EntryHookTrampoline(intptr_t function,
1063 : intptr_t stack_pointer,
1064 : Isolate* isolate);
1065 :
1066 : // ProfileEntryHookStub is called at the start of a function, so it has the
1067 : // same register set.
1068 0 : DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction)
1069 6 : DEFINE_PLATFORM_CODE_STUB(ProfileEntryHook, PlatformCodeStub);
1070 : };
1071 :
1072 :
1073 0 : class StoreBufferOverflowStub : public PlatformCodeStub {
1074 : public:
1075 : StoreBufferOverflowStub(Isolate* isolate, SaveFPRegsMode save_fp)
1076 109758 : : PlatformCodeStub(isolate) {
1077 54879 : minor_key_ = SaveDoublesBits::encode(save_fp == kSaveFPRegs);
1078 : }
1079 :
1080 : static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
1081 0 : bool SometimesSetsUpAFrame() override { return false; }
1082 :
1083 : private:
1084 : bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
1085 :
1086 : class SaveDoublesBits : public BitField<bool, 0, 1> {};
1087 :
1088 0 : DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1089 109950 : DEFINE_PLATFORM_CODE_STUB(StoreBufferOverflow, PlatformCodeStub);
1090 : };
1091 :
1092 : #undef DEFINE_CALL_INTERFACE_DESCRIPTOR
1093 : #undef DEFINE_PLATFORM_CODE_STUB
1094 : #undef DEFINE_HANDLER_CODE_STUB
1095 : #undef DEFINE_CODE_STUB
1096 : #undef DEFINE_CODE_STUB_BASE
1097 :
1098 : } // namespace internal
1099 : } // namespace v8
1100 :
1101 : #endif // V8_CODE_STUBS_H_
|