1 // Copyright 2021 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_CODEGEN_INTERFACE_DESCRIPTORS_INL_H_
6 #define V8_CODEGEN_INTERFACE_DESCRIPTORS_INL_H_
7 
8 #include <utility>
9 
10 #include "src/base/logging.h"
11 #include "src/codegen/interface-descriptors.h"
12 #include "src/codegen/register.h"
13 
14 #if V8_TARGET_ARCH_X64
15 #include "src/codegen/x64/interface-descriptors-x64-inl.h"
16 #elif V8_TARGET_ARCH_ARM64
17 #include "src/codegen/arm64/interface-descriptors-arm64-inl.h"
18 #elif V8_TARGET_ARCH_IA32
19 #include "src/codegen/ia32/interface-descriptors-ia32-inl.h"
20 #elif V8_TARGET_ARCH_ARM
21 #include "src/codegen/arm/interface-descriptors-arm-inl.h"
22 #elif V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64
23 #include "src/codegen/ppc/interface-descriptors-ppc-inl.h"
24 #elif V8_TARGET_ARCH_S390
25 #include "src/codegen/s390/interface-descriptors-s390-inl.h"
26 #elif V8_TARGET_ARCH_MIPS64
27 #include "src/codegen/mips64/interface-descriptors-mips64-inl.h"
28 #elif V8_TARGET_ARCH_MIPS
29 #include "src/codegen/mips/interface-descriptors-mips-inl.h"
30 #elif V8_TARGET_ARCH_LOONG64
31 #include "src/codegen/loong64/interface-descriptors-loong64-inl.h"
32 #elif V8_TARGET_ARCH_RISCV64
33 #include "src/codegen/riscv64/interface-descriptors-riscv64-inl.h"
34 #else
35 #error Unsupported target architecture.
36 #endif
37 
38 namespace v8 {
39 namespace internal {
40 
41 // static
42 constexpr std::array<Register, kJSBuiltinRegisterParams>
DefaultJSRegisterArray()43 CallInterfaceDescriptor::DefaultJSRegisterArray() {
44   return RegisterArray(
45       kJavaScriptCallTargetRegister, kJavaScriptCallNewTargetRegister,
46       kJavaScriptCallArgCountRegister, kJavaScriptCallExtraArg1Register);
47 }
48 
49 // static
50 template <typename DerivedDescriptor>
registers()51 constexpr auto StaticCallInterfaceDescriptor<DerivedDescriptor>::registers() {
52   return CallInterfaceDescriptor::DefaultRegisterArray();
53 }
54 
55 // static
56 template <typename DerivedDescriptor>
registers()57 constexpr auto StaticJSCallInterfaceDescriptor<DerivedDescriptor>::registers() {
58   return CallInterfaceDescriptor::DefaultJSRegisterArray();
59 }
60 
61 template <typename DerivedDescriptor>
Initialize( CallInterfaceDescriptorData* data)62 void StaticCallInterfaceDescriptor<DerivedDescriptor>::Initialize(
63     CallInterfaceDescriptorData* data) {
64   // Static local copy of the Registers array, for platform-specific
65   // initialization
66   static auto registers = DerivedDescriptor::registers();
67 
68   // The passed pointer should be a modifiable pointer to our own data.
69   DCHECK_EQ(data, this->data());
70   DCHECK(!data->IsInitialized());
71 
72   if (DerivedDescriptor::kRestrictAllocatableRegisters) {
73     data->RestrictAllocatableRegisters(registers.data(), registers.size());
74   } else {
75     DCHECK(!DerivedDescriptor::kCalleeSaveRegisters);
76   }
77 
78   data->InitializeRegisters(
79       DerivedDescriptor::flags(), DerivedDescriptor::kReturnCount,
80       DerivedDescriptor::GetParameterCount(),
81       DerivedDescriptor::kStackArgumentOrder,
82       DerivedDescriptor::GetRegisterParameterCount(), registers.data());
83 
84   // InitializeTypes is customizable by the DerivedDescriptor subclass.
85   DerivedDescriptor::InitializeTypes(data);
86 
87   DCHECK(data->IsInitialized());
88   DCHECK(this->CheckFloatingPointParameters(data));
89 #if DEBUG
90   DerivedDescriptor::Verify(data);
91 #endif
92 }
93 // static
94 template <typename DerivedDescriptor>
95 constexpr int
GetReturnCount()96 StaticCallInterfaceDescriptor<DerivedDescriptor>::GetReturnCount() {
97   static_assert(
98       DerivedDescriptor::kReturnCount >= 0,
99       "DerivedDescriptor subclass should override return count with a value "
100       "that is greater than 0");
101 
102   return DerivedDescriptor::kReturnCount;
103 }
104 
105 // static
106 template <typename DerivedDescriptor>
107 constexpr int
GetParameterCount()108 StaticCallInterfaceDescriptor<DerivedDescriptor>::GetParameterCount() {
109   static_assert(
110       DerivedDescriptor::kParameterCount >= 0,
111       "DerivedDescriptor subclass should override parameter count with a "
112       "value that is greater than 0");
113 
114   return DerivedDescriptor::kParameterCount;
115 }
116 
117 namespace detail {
118 
119 // Helper trait for statically checking if a type is a std::array<Register,N>.
120 template <typename T>
121 struct IsRegisterArray : public std::false_type {};
122 template <size_t N>
123 struct IsRegisterArray<std::array<Register, N>> : public std::true_type {};
124 template <>
125 struct IsRegisterArray<EmptyRegisterArray> : public std::true_type {};
126 
127 // Helper for finding the index of the first invalid register in a register
128 // array.
129 template <size_t N, size_t Index>
130 struct FirstInvalidRegisterHelper {
Callv8::internal::detail::FirstInvalidRegisterHelper131   static constexpr int Call(std::array<Register, N> regs) {
132     if (!std::get<Index>(regs).is_valid()) {
133       // All registers after the first invalid one have to also be invalid (this
134       // DCHECK will be checked recursively).
135       DCHECK_EQ((FirstInvalidRegisterHelper<N, Index + 1>::Call(regs)),
136                 Index + 1);
137       return Index;
138     }
139     return FirstInvalidRegisterHelper<N, Index + 1>::Call(regs);
140   }
141 };
142 template <size_t N>
143 struct FirstInvalidRegisterHelper<N, N> {
Callv8::internal::detail::FirstInvalidRegisterHelper144   static constexpr int Call(std::array<Register, N> regs) { return N; }
145 };
146 template <size_t N, size_t Index = 0>
FirstInvalidRegister(std::array<Register, N> regs)147 constexpr size_t FirstInvalidRegister(std::array<Register, N> regs) {
148   return FirstInvalidRegisterHelper<N, 0>::Call(regs);
149 }
FirstInvalidRegister(EmptyRegisterArray regs)150 constexpr size_t FirstInvalidRegister(EmptyRegisterArray regs) { return 0; }
151 
152 }  // namespace detail
153 
154 // static
155 template <typename DerivedDescriptor>
156 constexpr int
GetRegisterParameterCount()157 StaticCallInterfaceDescriptor<DerivedDescriptor>::GetRegisterParameterCount() {
158   static_assert(
159       detail::IsRegisterArray<decltype(DerivedDescriptor::registers())>::value,
160       "DerivedDescriptor subclass should define a registers() function "
161       "returning a std::array<Register>");
162 
163   // The register parameter count is the minimum of:
164   //   1. The number of named parameters in the descriptor, and
165   //   2. The number of valid registers the descriptor provides with its
166   //      registers() function, e.g. for {rax, rbx, no_reg} this number is 2.
167   //   3. The maximum number of register parameters allowed (
168   //      kMaxBuiltinRegisterParams for most builtins,
169   //      kMaxTFSBuiltinRegisterParams for TFS builtins, customizable by the
170   //      subclass otherwise).
171   return std::min<int>({DerivedDescriptor::GetParameterCount(),
172                         static_cast<int>(detail::FirstInvalidRegister(
173                             DerivedDescriptor::registers())),
174                         DerivedDescriptor::kMaxRegisterParams});
175 }
176 
177 // static
178 template <typename DerivedDescriptor>
179 constexpr int
GetStackParameterCount()180 StaticCallInterfaceDescriptor<DerivedDescriptor>::GetStackParameterCount() {
181   return DerivedDescriptor::GetParameterCount() -
182          DerivedDescriptor::GetRegisterParameterCount();
183 }
184 
185 // static
186 template <typename DerivedDescriptor>
187 constexpr Register
GetRegisterParameter(int i)188 StaticCallInterfaceDescriptor<DerivedDescriptor>::GetRegisterParameter(int i) {
189   return DerivedDescriptor::registers()[i];
190 }
191 
192 // static
TargetRegister()193 constexpr Register FastNewObjectDescriptor::TargetRegister() {
194   return kJSFunctionRegister;
195 }
196 
197 // static
NewTargetRegister()198 constexpr Register FastNewObjectDescriptor::NewTargetRegister() {
199   return kJavaScriptCallNewTargetRegister;
200 }
201 
202 // static
ObjectRegister()203 constexpr Register WriteBarrierDescriptor::ObjectRegister() {
204   return std::get<kObject>(registers());
205 }
206 // static
SlotAddressRegister()207 constexpr Register WriteBarrierDescriptor::SlotAddressRegister() {
208   return std::get<kSlotAddress>(registers());
209 }
210 
211 // static
ValueRegister()212 constexpr Register WriteBarrierDescriptor::ValueRegister() {
213   return std::get<kSlotAddress + 1>(registers());
214 }
215 
216 // static
ComputeSavedRegisters( Register object, Register slot_address)217 constexpr RegList WriteBarrierDescriptor::ComputeSavedRegisters(
218     Register object, Register slot_address) {
219   DCHECK(!AreAliased(object, slot_address));
220   RegList saved_registers;
221 #if V8_TARGET_ARCH_X64
222   // Only push clobbered registers.
223   if (object != ObjectRegister()) saved_registers.set(ObjectRegister());
224   if (slot_address != no_reg && slot_address != SlotAddressRegister()) {
225     saved_registers.set(SlotAddressRegister());
226   }
227 #elif V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_LOONG64 || \
228     V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_MIPS
229   if (object != ObjectRegister()) saved_registers.set(ObjectRegister());
230   // The slot address is always clobbered.
231   saved_registers.set(SlotAddressRegister());
232 #else
233   // TODO(cbruni): Enable callee-saved registers for other platforms.
234   // This is a temporary workaround to prepare code for callee-saved registers.
235   constexpr auto allocated_registers = registers();
236   for (size_t i = 0; i < allocated_registers.size(); ++i) {
237     saved_registers.set(allocated_registers[i]);
238   }
239 #endif
240   return saved_registers;
241 }
242 
243 // static
ReceiverRegister()244 constexpr Register ApiGetterDescriptor::ReceiverRegister() {
245   return LoadDescriptor::ReceiverRegister();
246 }
247 
248 // static
ICKindRegister()249 constexpr Register LoadGlobalNoFeedbackDescriptor::ICKindRegister() {
250   return LoadDescriptor::SlotRegister();
251 }
252 
253 // static
ICKindRegister()254 constexpr Register LoadNoFeedbackDescriptor::ICKindRegister() {
255   return LoadGlobalNoFeedbackDescriptor::ICKindRegister();
256 }
257 
258 #if V8_TARGET_ARCH_IA32
259 // On ia32, LoadWithVectorDescriptor passes vector on the stack and thus we
260 // need to choose a new register here.
261 // static
VectorRegister()262 constexpr Register LoadGlobalWithVectorDescriptor::VectorRegister() {
263   STATIC_ASSERT(!LoadWithVectorDescriptor::VectorRegister().is_valid());
264   return LoadDescriptor::ReceiverRegister();
265 }
266 #else
267 // static
VectorRegister()268 constexpr Register LoadGlobalWithVectorDescriptor::VectorRegister() {
269   return LoadWithVectorDescriptor::VectorRegister();
270 }
271 #endif
272 
273 // static
registers()274 constexpr auto LoadDescriptor::registers() {
275   return RegisterArray(ReceiverRegister(), NameRegister(), SlotRegister());
276 }
277 
278 // static
registers()279 constexpr auto LoadBaselineDescriptor::registers() {
280   return LoadDescriptor::registers();
281 }
282 
283 // static
registers()284 constexpr auto LoadGlobalDescriptor::registers() {
285   return RegisterArray(LoadDescriptor::NameRegister(),
286                        LoadDescriptor::SlotRegister());
287 }
288 
289 // static
registers()290 constexpr auto LoadGlobalBaselineDescriptor::registers() {
291   return LoadGlobalDescriptor::registers();
292 }
293 
294 // static
registers()295 constexpr auto StoreDescriptor::registers() {
296   return RegisterArray(ReceiverRegister(), NameRegister(), ValueRegister(),
297                        SlotRegister());
298 }
299 
300 // static
registers()301 constexpr auto StoreBaselineDescriptor::registers() {
302   return StoreDescriptor::registers();
303 }
304 
305 // static
registers()306 constexpr auto StoreGlobalDescriptor::registers() {
307   return RegisterArray(StoreDescriptor::NameRegister(),
308                        StoreDescriptor::ValueRegister(),
309                        StoreDescriptor::SlotRegister());
310 }
311 
312 // static
registers()313 constexpr auto StoreGlobalBaselineDescriptor::registers() {
314   return StoreGlobalDescriptor::registers();
315 }
316 
317 // static
registers()318 constexpr auto LoadWithReceiverBaselineDescriptor::registers() {
319   return RegisterArray(
320       LoadDescriptor::ReceiverRegister(),
321       LoadWithReceiverAndVectorDescriptor::LookupStartObjectRegister(),
322       LoadDescriptor::NameRegister(), LoadDescriptor::SlotRegister());
323 }
324 
325 // static
registers()326 constexpr auto BaselineOutOfLinePrologueDescriptor::registers() {
327   // TODO(v8:11421): Implement on other platforms.
328 #if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_ARM ||       \
329     V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64 || V8_TARGET_ARCH_S390 ||      \
330     V8_TARGET_ARCH_RISCV64 || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_MIPS || \
331     V8_TARGET_ARCH_LOONG64
332   return RegisterArray(
333       kContextRegister, kJSFunctionRegister, kJavaScriptCallArgCountRegister,
334       kJavaScriptCallExtraArg1Register, kJavaScriptCallNewTargetRegister,
335       kInterpreterBytecodeArrayRegister);
336 #elif V8_TARGET_ARCH_IA32
337   STATIC_ASSERT(kJSFunctionRegister == kInterpreterBytecodeArrayRegister);
338   return RegisterArray(
339       kContextRegister, kJSFunctionRegister, kJavaScriptCallArgCountRegister,
340       kJavaScriptCallExtraArg1Register, kJavaScriptCallNewTargetRegister);
341 #else
342   return DefaultRegisterArray();
343 #endif
344 }
345 
346 // static
registers()347 constexpr auto BaselineLeaveFrameDescriptor::registers() {
348   // TODO(v8:11421): Implement on other platforms.
349 #if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 ||      \
350     V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64 ||       \
351     V8_TARGET_ARCH_S390 || V8_TARGET_ARCH_RISCV64 || V8_TARGET_ARCH_MIPS64 || \
352     V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_LOONG64
353   return RegisterArray(ParamsSizeRegister(), WeightRegister());
354 #else
355   return DefaultRegisterArray();
356 #endif
357 }
358 
359 // static
registers()360 constexpr auto VoidDescriptor::registers() { return RegisterArray(); }
361 
362 // static
registers()363 constexpr auto AllocateDescriptor::registers() {
364   return RegisterArray(kAllocateSizeRegister);
365 }
366 
367 // static
registers()368 constexpr auto CEntry1ArgvOnStackDescriptor::registers() {
369   return RegisterArray(kRuntimeCallArgCountRegister,
370                        kRuntimeCallFunctionRegister);
371 }
372 
373 // static
registers()374 constexpr auto InterpreterCEntry1Descriptor::registers() {
375   return RegisterArray(kRuntimeCallArgCountRegister, kRuntimeCallArgvRegister,
376                        kRuntimeCallFunctionRegister);
377 }
378 
379 // static
registers()380 constexpr auto InterpreterCEntry2Descriptor::registers() {
381   return RegisterArray(kRuntimeCallArgCountRegister, kRuntimeCallArgvRegister,
382                        kRuntimeCallFunctionRegister);
383 }
384 
385 // static
registers()386 constexpr auto FastNewObjectDescriptor::registers() {
387   return RegisterArray(TargetRegister(), NewTargetRegister());
388 }
389 
390 // static
registers()391 constexpr auto LoadNoFeedbackDescriptor::registers() {
392   return RegisterArray(LoadDescriptor::ReceiverRegister(),
393                        LoadDescriptor::NameRegister(), ICKindRegister());
394 }
395 
396 // static
registers()397 constexpr auto LoadGlobalNoFeedbackDescriptor::registers() {
398   return RegisterArray(LoadDescriptor::NameRegister(), ICKindRegister());
399 }
400 
401 // static
registers()402 constexpr auto LoadGlobalWithVectorDescriptor::registers() {
403   return RegisterArray(LoadDescriptor::NameRegister(),
404                        LoadDescriptor::SlotRegister(), VectorRegister());
405 }
406 
407 // static
registers()408 constexpr auto LoadWithReceiverAndVectorDescriptor::registers() {
409   return RegisterArray(
410       LoadDescriptor::ReceiverRegister(), LookupStartObjectRegister(),
411       LoadDescriptor::NameRegister(), LoadDescriptor::SlotRegister(),
412       LoadWithVectorDescriptor::VectorRegister());
413 }
414 
415 // static
registers()416 constexpr auto StoreGlobalWithVectorDescriptor::registers() {
417   return RegisterArray(StoreDescriptor::NameRegister(),
418                        StoreDescriptor::ValueRegister(),
419                        StoreDescriptor::SlotRegister(),
420                        StoreWithVectorDescriptor::VectorRegister());
421 }
422 
423 // static
registers()424 constexpr auto StoreTransitionDescriptor::registers() {
425   return RegisterArray(StoreDescriptor::ReceiverRegister(),
426                        StoreDescriptor::NameRegister(), MapRegister(),
427                        StoreDescriptor::ValueRegister(),
428                        StoreDescriptor::SlotRegister(),
429                        StoreWithVectorDescriptor::VectorRegister());
430 }
431 
432 // static
registers()433 constexpr auto TypeConversionDescriptor::registers() {
434   return RegisterArray(ArgumentRegister());
435 }
436 
437 // static
registers()438 constexpr auto TypeConversionNoContextDescriptor::registers() {
439   return RegisterArray(TypeConversionDescriptor::ArgumentRegister());
440 }
441 
442 // static
registers()443 constexpr auto SingleParameterOnStackDescriptor::registers() {
444   return RegisterArray();
445 }
446 
447 // static
registers()448 constexpr auto AsyncFunctionStackParameterDescriptor::registers() {
449   return RegisterArray();
450 }
451 
452 // static
registers()453 constexpr auto GetIteratorStackParameterDescriptor::registers() {
454   return RegisterArray();
455 }
456 
457 // static
registers()458 constexpr auto LoadWithVectorDescriptor::registers() {
459   return RegisterArray(LoadDescriptor::ReceiverRegister(),
460                        LoadDescriptor::NameRegister(),
461                        LoadDescriptor::SlotRegister(), VectorRegister());
462 }
463 
464 // static
registers()465 constexpr auto KeyedLoadBaselineDescriptor::registers() {
466   return RegisterArray(ReceiverRegister(), NameRegister(), SlotRegister());
467 }
468 
469 // static
registers()470 constexpr auto KeyedLoadDescriptor::registers() {
471   return KeyedLoadBaselineDescriptor::registers();
472 }
473 
474 // static
registers()475 constexpr auto KeyedLoadWithVectorDescriptor::registers() {
476   return RegisterArray(KeyedLoadBaselineDescriptor::ReceiverRegister(),
477                        KeyedLoadBaselineDescriptor::NameRegister(),
478                        KeyedLoadBaselineDescriptor::SlotRegister(),
479                        VectorRegister());
480 }
481 
482 // static
registers()483 constexpr auto KeyedHasICBaselineDescriptor::registers() {
484   return RegisterArray(ReceiverRegister(), NameRegister(), SlotRegister());
485 }
486 
487 // static
registers()488 constexpr auto KeyedHasICWithVectorDescriptor::registers() {
489   return RegisterArray(KeyedHasICBaselineDescriptor::ReceiverRegister(),
490                        KeyedHasICBaselineDescriptor::NameRegister(),
491                        KeyedHasICBaselineDescriptor::SlotRegister(),
492                        VectorRegister());
493 }
494 
495 // static
registers()496 constexpr auto StoreWithVectorDescriptor::registers() {
497   return RegisterArray(StoreDescriptor::ReceiverRegister(),
498                        StoreDescriptor::NameRegister(),
499                        StoreDescriptor::ValueRegister(),
500                        StoreDescriptor::SlotRegister(), VectorRegister());
501 }
502 
503 // static
registers()504 constexpr auto ApiGetterDescriptor::registers() {
505   return RegisterArray(ReceiverRegister(), HolderRegister(),
506                        CallbackRegister());
507 }
508 
509 // static
registers()510 constexpr auto ContextOnlyDescriptor::registers() { return RegisterArray(); }
511 
512 // static
registers()513 constexpr auto NoContextDescriptor::registers() { return RegisterArray(); }
514 
515 // static
registers()516 constexpr auto GrowArrayElementsDescriptor::registers() {
517   return RegisterArray(ObjectRegister(), KeyRegister());
518 }
519 
520 // static
registers()521 constexpr auto ArrayNArgumentsConstructorDescriptor::registers() {
522   // Keep the arguments on the same registers as they were in
523   // ArrayConstructorDescriptor to avoid unnecessary register moves.
524   // kFunction, kAllocationSite, kActualArgumentsCount
525   return RegisterArray(kJavaScriptCallTargetRegister,
526                        kJavaScriptCallExtraArg1Register,
527                        kJavaScriptCallArgCountRegister);
528 }
529 
530 // static
registers()531 constexpr auto ArrayNoArgumentConstructorDescriptor::registers() {
532   // This descriptor must use the same set of registers as the
533   // ArrayNArgumentsConstructorDescriptor.
534   return ArrayNArgumentsConstructorDescriptor::registers();
535 }
536 
537 // static
registers()538 constexpr auto ArraySingleArgumentConstructorDescriptor::registers() {
539   // This descriptor must use the same set of registers as the
540   // ArrayNArgumentsConstructorDescriptor.
541   return ArrayNArgumentsConstructorDescriptor::registers();
542 }
543 
544 // static
545 // static
MicrotaskQueueRegister()546 constexpr Register RunMicrotasksDescriptor::MicrotaskQueueRegister() {
547   return GetRegisterParameter(0);
548 }
549 
550 #define DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER(Name, DescriptorName) \
551   template <>                                                         \
552   struct CallInterfaceDescriptorFor<Builtin::k##Name> {               \
553     using type = DescriptorName##Descriptor;                          \
554   };
555 BUILTIN_LIST(IGNORE_BUILTIN, IGNORE_BUILTIN,
556              /*TFC*/ DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER, IGNORE_BUILTIN,
557              /*TFH*/ DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER, IGNORE_BUILTIN,
558              /*ASM*/ DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER)
559 #undef DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER
560 #define DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER(Name, ...) \
561   template <>                                              \
562   struct CallInterfaceDescriptorFor<Builtin::k##Name> {    \
563     using type = Name##Descriptor;                         \
564   };
565 BUILTIN_LIST_TFS(DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER)
566 #undef DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER
567 
568 }  // namespace internal
569 }  // namespace v8
570 
571 #endif  // V8_CODEGEN_INTERFACE_DESCRIPTORS_INL_H_
572