V8  latest master commit
V8 is Google's open source JavaScript engine
v8-fast-api-calls.h
Go to the documentation of this file.
1 // Copyright 2020 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 
162 #ifndef INCLUDE_V8_FAST_API_CALLS_H_
163 #define INCLUDE_V8_FAST_API_CALLS_H_
164 
165 #include <stddef.h>
166 #include <stdint.h>
167 
168 #include "v8config.h" // NOLINT(build/include_directory)
169 
170 namespace v8 {
171 
172 class CTypeInfo {
173  public:
174  enum class Type : char {
175  kVoid,
176  kBool,
177  kInt32,
178  kUint32,
179  kInt64,
180  kUint64,
181  kFloat32,
182  kFloat64,
184  };
185 
186  enum class ArgFlags : uint8_t {
187  kNone = 0,
188  kIsArrayBit = 1 << 0, // This argument is first in an array of values.
189  };
190 
191  static CTypeInfo FromWrapperType(const void* wrapper_type_info,
192  ArgFlags flags = ArgFlags::kNone) {
193  uintptr_t wrapper_type_info_ptr =
194  reinterpret_cast<uintptr_t>(wrapper_type_info);
195  // Check that the lower kIsWrapperTypeBit bits are 0's.
196  CHECK_EQ(
197  wrapper_type_info_ptr & ~(static_cast<uintptr_t>(~0)
198  << static_cast<uintptr_t>(kIsWrapperTypeBit)),
199  0u);
200  // TODO(mslekova): Refactor the manual bit manipulations to use
201  // PointerWithPayload instead.
202  return CTypeInfo(wrapper_type_info_ptr | static_cast<int>(flags) |
203  kIsWrapperTypeBit);
204  }
205 
206  static constexpr CTypeInfo FromCType(Type ctype,
207  ArgFlags flags = ArgFlags::kNone) {
208  // ctype cannot be Type::kUnwrappedApiObject.
209  return CTypeInfo(
210  ((static_cast<uintptr_t>(ctype) << kTypeOffset) & kTypeMask) |
211  static_cast<int>(flags));
212  }
213 
214  const void* GetWrapperInfo() const;
215 
216  constexpr Type GetType() const {
217  if (payload_ & kIsWrapperTypeBit) {
219  }
220  return static_cast<Type>((payload_ & kTypeMask) >> kTypeOffset);
221  }
222 
223  constexpr bool IsArray() const {
224  return payload_ & static_cast<int>(ArgFlags::kIsArrayBit);
225  }
226 
227  private:
228  explicit constexpr CTypeInfo(uintptr_t payload) : payload_(payload) {}
229 
230  // That must be the last bit after ArgFlags.
231  static constexpr uintptr_t kIsWrapperTypeBit = 1 << 1;
232  static constexpr uintptr_t kWrapperTypeInfoMask = static_cast<uintptr_t>(~0)
233  << 2;
234 
235  static constexpr unsigned int kTypeOffset = kIsWrapperTypeBit;
236  static constexpr unsigned int kTypeSize = 8 - kTypeOffset;
237  static constexpr uintptr_t kTypeMask =
238  (~(static_cast<uintptr_t>(~0) << kTypeSize)) << kTypeOffset;
239 
240  const uintptr_t payload_;
241 };
242 
244  public:
245  virtual const CTypeInfo& ReturnInfo() const = 0;
246  virtual unsigned int ArgumentCount() const = 0;
247  virtual const CTypeInfo& ArgumentInfo(unsigned int index) const = 0;
248 };
249 
250 template <typename T>
252  public:
253  static const void* GetTypeInfo() {
254  static_assert(sizeof(T) != sizeof(T),
255  "WrapperTraits must be specialized for this type.");
256  return nullptr;
257  }
258 };
259 
260 namespace internal {
261 
262 template <typename T>
263 struct GetCType {
264  static_assert(sizeof(T) != sizeof(T), "Unsupported CType");
265 };
266 
267 #define SPECIALIZE_GET_C_TYPE_FOR(ctype, ctypeinfo) \
268  template <> \
269  struct GetCType<ctype> { \
270  static constexpr CTypeInfo Get() { \
271  return CTypeInfo::FromCType(CTypeInfo::Type::ctypeinfo); \
272  } \
273  };
274 
275 #define SUPPORTED_C_TYPES(V) \
276  V(void, kVoid) \
277  V(bool, kBool) \
278  V(int32_t, kInt32) \
279  V(uint32_t, kUint32) \
280  V(int64_t, kInt64) \
281  V(uint64_t, kUint64) \
282  V(float, kFloat32) \
283  V(double, kFloat64)
284 
286 
287 template <typename T, typename = void>
289 
290 template <typename T>
291 struct EnableIfHasWrapperTypeInfo<T, decltype(WrapperTraits<T>::GetTypeInfo(),
292  void())> {
293  typedef void type;
294 };
295 
296 // T* where T is a primitive (array of primitives).
297 template <typename T, typename = void>
299  static constexpr CTypeInfo Get() {
300  return CTypeInfo::FromCType(GetCType<T>::Get().GetType(),
302  }
303 };
304 
305 // T* where T is an API object.
306 template <typename T>
307 struct GetCTypePointerImpl<T, typename EnableIfHasWrapperTypeInfo<T>::type> {
308  static constexpr CTypeInfo Get() {
310  }
311 };
312 
313 // T** where T is a primitive. Not allowed.
314 template <typename T, typename = void>
316  static_assert(sizeof(T**) != sizeof(T**), "Unsupported type");
317 };
318 
319 // T** where T is an API object (array of API objects).
320 template <typename T>
322  T, typename EnableIfHasWrapperTypeInfo<T>::type> {
323  static constexpr CTypeInfo Get() {
326  }
327 };
328 
329 template <typename T>
330 struct GetCType<T**> : public GetCTypePointerPointerImpl<T> {};
331 
332 template <typename T>
333 struct GetCType<T*> : public GetCTypePointerImpl<T> {};
334 
335 template <typename R, typename... Args>
337  public:
339  : return_info_(internal::GetCType<R>::Get()),
340  arg_count_(sizeof...(Args)),
341  arg_info_{internal::GetCType<Args>::Get()...} {
342  static_assert(
344  "Only void return types are currently supported.");
345  }
346 
347  const CTypeInfo& ReturnInfo() const override { return return_info_; }
348  unsigned int ArgumentCount() const override { return arg_count_; }
349  const CTypeInfo& ArgumentInfo(unsigned int index) const override {
350  CHECK_LT(index, ArgumentCount());
351  return arg_info_[index];
352  }
353 
354  private:
355  CTypeInfo return_info_;
356  const unsigned int arg_count_;
357  CTypeInfo arg_info_[sizeof...(Args)];
358 };
359 
360 } // namespace internal
361 
363  public:
364  constexpr CFunction() : address_(nullptr), type_info_(nullptr) {}
365 
366  const CTypeInfo& ReturnInfo() const { return type_info_->ReturnInfo(); }
367 
368  const CTypeInfo& ArgumentInfo(unsigned int index) const {
369  return type_info_->ArgumentInfo(index);
370  }
371 
372  unsigned int ArgumentCount() const { return type_info_->ArgumentCount(); }
373 
374  const void* GetAddress() const { return address_; }
375  const CFunctionInfo* GetTypeInfo() const { return type_info_; }
376 
377  template <typename F>
378  static CFunction Make(F* func) {
379  return ArgUnwrap<F*>::Make(func);
380  }
381 
382  private:
383  const void* address_;
384  const CFunctionInfo* type_info_;
385 
386  CFunction(const void* address, const CFunctionInfo* type_info);
387 
388  template <typename R, typename... Args>
389  static CFunctionInfo* GetCFunctionInfo() {
390  static internal::CFunctionInfoImpl<R, Args...> instance;
391  return &instance;
392  }
393 
394  template <typename F>
395  class ArgUnwrap {
396  static_assert(sizeof(F) != sizeof(F),
397  "CFunction must be created from a function pointer.");
398  };
399 
400  template <typename R, typename... Args>
401  class ArgUnwrap<R (*)(Args...)> {
402  public:
403  static CFunction Make(R (*func)(Args...)) {
404  return CFunction(reinterpret_cast<const void*>(func),
405  GetCFunctionInfo<R, Args...>());
406  }
407  };
408 };
409 
410 } // namespace v8
411 
412 #endif // INCLUDE_V8_FAST_API_CALLS_H_
v8::CTypeInfo::IsArray
constexpr bool IsArray() const
Definition: v8-fast-api-calls.h:223
v8::CTypeInfo::Type::kFloat32
@ kFloat32
v8::CFunction::CFunction
constexpr CFunction()
Definition: v8-fast-api-calls.h:364
v8::CFunctionInfo::ArgumentInfo
virtual const CTypeInfo & ArgumentInfo(unsigned int index) const =0
SUPPORTED_C_TYPES
#define SUPPORTED_C_TYPES(V)
Definition: v8-fast-api-calls.h:275
v8::CTypeInfo::Type::kBool
@ kBool
v8::CFunction::ArgumentCount
unsigned int ArgumentCount() const
Definition: v8-fast-api-calls.h:372
v8::internal::EnableIfHasWrapperTypeInfo
Definition: v8-fast-api-calls.h:288
v8::internal::GetCType
Definition: v8-fast-api-calls.h:263
v8::CFunction::Make
static CFunction Make(F *func)
Definition: v8-fast-api-calls.h:378
v8::internal::CFunctionInfoImpl
Definition: v8-fast-api-calls.h:336
v8::CTypeInfo::FromCType
static constexpr CTypeInfo FromCType(Type ctype, ArgFlags flags=ArgFlags::kNone)
Definition: v8-fast-api-calls.h:206
v8::CFunctionInfo::ArgumentCount
virtual unsigned int ArgumentCount() const =0
v8::internal::GetCTypePointerPointerImpl< T, typename EnableIfHasWrapperTypeInfo< T >::type >::Get
static constexpr CTypeInfo Get()
Definition: v8-fast-api-calls.h:323
v8::CTypeInfo::Type::kUint64
@ kUint64
v8::CTypeInfo::Type::kInt64
@ kInt64
v8::CTypeInfo::Type::kUint32
@ kUint32
v8::WrapperTraits::GetTypeInfo
static const void * GetTypeInfo()
Definition: v8-fast-api-calls.h:253
v8::CTypeInfo::Type::kVoid
@ kVoid
v8config.h
v8::CFunction::GetAddress
const void * GetAddress() const
Definition: v8-fast-api-calls.h:374
v8::internal::CFunctionInfoImpl::ArgumentInfo
const CTypeInfo & ArgumentInfo(unsigned int index) const override
Definition: v8-fast-api-calls.h:349
v8::internal::CFunctionInfoImpl::CFunctionInfoImpl
CFunctionInfoImpl()
Definition: v8-fast-api-calls.h:338
V8_EXPORT
#define V8_EXPORT
Definition: v8config.h:467
v8::internal::CFunctionInfoImpl::ReturnInfo
const CTypeInfo & ReturnInfo() const override
Definition: v8-fast-api-calls.h:347
v8::CTypeInfo::ArgFlags
ArgFlags
Definition: v8-fast-api-calls.h:186
v8::internal::EnableIfHasWrapperTypeInfo< T, decltype(WrapperTraits< T >::GetTypeInfo(), void())>::type
void type
Definition: v8-fast-api-calls.h:293
v8::CTypeInfo::Type::kInt32
@ kInt32
v8::internal::GetCTypePointerImpl::Get
static constexpr CTypeInfo Get()
Definition: v8-fast-api-calls.h:299
v8::internal::CFunctionInfoImpl::ArgumentCount
unsigned int ArgumentCount() const override
Definition: v8-fast-api-calls.h:348
v8
Definition: libplatform.h:15
v8::CTypeInfo::Type
Type
Definition: v8-fast-api-calls.h:174
v8::CTypeInfo::GetWrapperInfo
const void * GetWrapperInfo() const
v8::CFunction::ReturnInfo
const CTypeInfo & ReturnInfo() const
Definition: v8-fast-api-calls.h:366
v8::internal::GetCTypePointerImpl
Definition: v8-fast-api-calls.h:298
v8::internal::GetCTypePointerImpl< T, typename EnableIfHasWrapperTypeInfo< T >::type >::Get
static constexpr CTypeInfo Get()
Definition: v8-fast-api-calls.h:308
SPECIALIZE_GET_C_TYPE_FOR
#define SPECIALIZE_GET_C_TYPE_FOR(ctype, ctypeinfo)
Definition: v8-fast-api-calls.h:267
v8::CTypeInfo::Type::kFloat64
@ kFloat64
v8::WrapperTraits
Definition: v8-fast-api-calls.h:251
v8::CTypeInfo::FromWrapperType
static CTypeInfo FromWrapperType(const void *wrapper_type_info, ArgFlags flags=ArgFlags::kNone)
Definition: v8-fast-api-calls.h:191
v8::CFunctionInfo::ReturnInfo
virtual const CTypeInfo & ReturnInfo() const =0
v8::CTypeInfo::ArgFlags::kNone
@ kNone
v8::CFunction::GetTypeInfo
const CFunctionInfo * GetTypeInfo() const
Definition: v8-fast-api-calls.h:375
v8::CTypeInfo::GetType
constexpr Type GetType() const
Definition: v8-fast-api-calls.h:216
v8::CTypeInfo::Type::kUnwrappedApiObject
@ kUnwrappedApiObject
v8::CFunction::ArgumentInfo
const CTypeInfo & ArgumentInfo(unsigned int index) const
Definition: v8-fast-api-calls.h:368
v8::CFunctionInfo
Definition: v8-fast-api-calls.h:243
v8::CFunction
Definition: v8-fast-api-calls.h:362
v8::CTypeInfo::ArgFlags::kIsArrayBit
@ kIsArrayBit
v8::CTypeInfo
Definition: v8-fast-api-calls.h:172
v8::internal::GetCTypePointerPointerImpl
Definition: v8-fast-api-calls.h:315