add v8 prebuilt libs for mac (#60)
* add v8 prebuilt for mac * add uv and part v8 libs for mac
This commit is contained in:
parent
0884b4fb1b
commit
3fc472687e
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,32 @@
|
|||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UV_AIX_H
|
||||
#define UV_AIX_H
|
||||
|
||||
#define UV_PLATFORM_LOOP_FIELDS \
|
||||
int fs_fd; \
|
||||
|
||||
#define UV_PLATFORM_FS_EVENT_FIELDS \
|
||||
uv__io_t event_watcher; \
|
||||
char *dir_filename; \
|
||||
|
||||
#endif /* UV_AIX_H */
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (c) 1995, 1999
|
||||
* Berkeley Software Design, Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp
|
||||
*/
|
||||
|
||||
#ifndef _IFADDRS_H_
|
||||
#define _IFADDRS_H_
|
||||
|
||||
struct ifaddrs {
|
||||
struct ifaddrs *ifa_next;
|
||||
char *ifa_name;
|
||||
unsigned int ifa_flags;
|
||||
struct sockaddr *ifa_addr;
|
||||
struct sockaddr *ifa_netmask;
|
||||
struct sockaddr *ifa_dstaddr;
|
||||
void *ifa_data;
|
||||
};
|
||||
|
||||
/*
|
||||
* This may have been defined in <net/if.h>. Note that if <net/if.h> is
|
||||
* to be included it must be included before this header file.
|
||||
*/
|
||||
#ifndef ifa_broadaddr
|
||||
#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
extern int getifaddrs(struct ifaddrs **ifap);
|
||||
extern void freeifaddrs(struct ifaddrs *ifa);
|
||||
__END_DECLS
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UV_BSD_H
|
||||
#define UV_BSD_H
|
||||
|
||||
#define UV_PLATFORM_FS_EVENT_FIELDS \
|
||||
uv__io_t event_watcher; \
|
||||
|
||||
#define UV_IO_PRIVATE_PLATFORM_FIELDS \
|
||||
int rcount; \
|
||||
int wcount; \
|
||||
|
||||
#define UV_HAVE_KQUEUE 1
|
||||
|
||||
#endif /* UV_BSD_H */
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UV_DARWIN_H
|
||||
#define UV_DARWIN_H
|
||||
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
# include <mach/mach.h>
|
||||
# include <mach/task.h>
|
||||
# include <mach/semaphore.h>
|
||||
# include <TargetConditionals.h>
|
||||
# define UV_PLATFORM_SEM_T semaphore_t
|
||||
#endif
|
||||
|
||||
#define UV_IO_PRIVATE_PLATFORM_FIELDS \
|
||||
int rcount; \
|
||||
int wcount; \
|
||||
|
||||
#define UV_PLATFORM_LOOP_FIELDS \
|
||||
uv_thread_t cf_thread; \
|
||||
void* _cf_reserved; \
|
||||
void* cf_state; \
|
||||
uv_mutex_t cf_mutex; \
|
||||
uv_sem_t cf_sem; \
|
||||
void* cf_signals[2]; \
|
||||
|
||||
#define UV_PLATFORM_FS_EVENT_FIELDS \
|
||||
uv__io_t event_watcher; \
|
||||
char* realpath; \
|
||||
int realpath_len; \
|
||||
int cf_flags; \
|
||||
uv_async_t* cf_cb; \
|
||||
void* cf_events[2]; \
|
||||
void* cf_member[2]; \
|
||||
int cf_error; \
|
||||
uv_mutex_t cf_mutex; \
|
||||
|
||||
#define UV_STREAM_PRIVATE_PLATFORM_FIELDS \
|
||||
void* select; \
|
||||
|
||||
#define UV_HAVE_KQUEUE 1
|
||||
|
||||
#endif /* UV_DARWIN_H */
|
||||
|
|
@ -0,0 +1,443 @@
|
|||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UV_ERRNO_H_
|
||||
#define UV_ERRNO_H_
|
||||
|
||||
#include <errno.h>
|
||||
#if EDOM > 0
|
||||
# define UV__ERR(x) (-(x))
|
||||
#else
|
||||
# define UV__ERR(x) (x)
|
||||
#endif
|
||||
|
||||
#define UV__EOF (-4095)
|
||||
#define UV__UNKNOWN (-4094)
|
||||
|
||||
#define UV__EAI_ADDRFAMILY (-3000)
|
||||
#define UV__EAI_AGAIN (-3001)
|
||||
#define UV__EAI_BADFLAGS (-3002)
|
||||
#define UV__EAI_CANCELED (-3003)
|
||||
#define UV__EAI_FAIL (-3004)
|
||||
#define UV__EAI_FAMILY (-3005)
|
||||
#define UV__EAI_MEMORY (-3006)
|
||||
#define UV__EAI_NODATA (-3007)
|
||||
#define UV__EAI_NONAME (-3008)
|
||||
#define UV__EAI_OVERFLOW (-3009)
|
||||
#define UV__EAI_SERVICE (-3010)
|
||||
#define UV__EAI_SOCKTYPE (-3011)
|
||||
#define UV__EAI_BADHINTS (-3013)
|
||||
#define UV__EAI_PROTOCOL (-3014)
|
||||
|
||||
/* Only map to the system errno on non-Windows platforms. It's apparently
|
||||
* a fairly common practice for Windows programmers to redefine errno codes.
|
||||
*/
|
||||
#if defined(E2BIG) && !defined(_WIN32)
|
||||
# define UV__E2BIG UV__ERR(E2BIG)
|
||||
#else
|
||||
# define UV__E2BIG (-4093)
|
||||
#endif
|
||||
|
||||
#if defined(EACCES) && !defined(_WIN32)
|
||||
# define UV__EACCES UV__ERR(EACCES)
|
||||
#else
|
||||
# define UV__EACCES (-4092)
|
||||
#endif
|
||||
|
||||
#if defined(EADDRINUSE) && !defined(_WIN32)
|
||||
# define UV__EADDRINUSE UV__ERR(EADDRINUSE)
|
||||
#else
|
||||
# define UV__EADDRINUSE (-4091)
|
||||
#endif
|
||||
|
||||
#if defined(EADDRNOTAVAIL) && !defined(_WIN32)
|
||||
# define UV__EADDRNOTAVAIL UV__ERR(EADDRNOTAVAIL)
|
||||
#else
|
||||
# define UV__EADDRNOTAVAIL (-4090)
|
||||
#endif
|
||||
|
||||
#if defined(EAFNOSUPPORT) && !defined(_WIN32)
|
||||
# define UV__EAFNOSUPPORT UV__ERR(EAFNOSUPPORT)
|
||||
#else
|
||||
# define UV__EAFNOSUPPORT (-4089)
|
||||
#endif
|
||||
|
||||
#if defined(EAGAIN) && !defined(_WIN32)
|
||||
# define UV__EAGAIN UV__ERR(EAGAIN)
|
||||
#else
|
||||
# define UV__EAGAIN (-4088)
|
||||
#endif
|
||||
|
||||
#if defined(EALREADY) && !defined(_WIN32)
|
||||
# define UV__EALREADY UV__ERR(EALREADY)
|
||||
#else
|
||||
# define UV__EALREADY (-4084)
|
||||
#endif
|
||||
|
||||
#if defined(EBADF) && !defined(_WIN32)
|
||||
# define UV__EBADF UV__ERR(EBADF)
|
||||
#else
|
||||
# define UV__EBADF (-4083)
|
||||
#endif
|
||||
|
||||
#if defined(EBUSY) && !defined(_WIN32)
|
||||
# define UV__EBUSY UV__ERR(EBUSY)
|
||||
#else
|
||||
# define UV__EBUSY (-4082)
|
||||
#endif
|
||||
|
||||
#if defined(ECANCELED) && !defined(_WIN32)
|
||||
# define UV__ECANCELED UV__ERR(ECANCELED)
|
||||
#else
|
||||
# define UV__ECANCELED (-4081)
|
||||
#endif
|
||||
|
||||
#if defined(ECHARSET) && !defined(_WIN32)
|
||||
# define UV__ECHARSET UV__ERR(ECHARSET)
|
||||
#else
|
||||
# define UV__ECHARSET (-4080)
|
||||
#endif
|
||||
|
||||
#if defined(ECONNABORTED) && !defined(_WIN32)
|
||||
# define UV__ECONNABORTED UV__ERR(ECONNABORTED)
|
||||
#else
|
||||
# define UV__ECONNABORTED (-4079)
|
||||
#endif
|
||||
|
||||
#if defined(ECONNREFUSED) && !defined(_WIN32)
|
||||
# define UV__ECONNREFUSED UV__ERR(ECONNREFUSED)
|
||||
#else
|
||||
# define UV__ECONNREFUSED (-4078)
|
||||
#endif
|
||||
|
||||
#if defined(ECONNRESET) && !defined(_WIN32)
|
||||
# define UV__ECONNRESET UV__ERR(ECONNRESET)
|
||||
#else
|
||||
# define UV__ECONNRESET (-4077)
|
||||
#endif
|
||||
|
||||
#if defined(EDESTADDRREQ) && !defined(_WIN32)
|
||||
# define UV__EDESTADDRREQ UV__ERR(EDESTADDRREQ)
|
||||
#else
|
||||
# define UV__EDESTADDRREQ (-4076)
|
||||
#endif
|
||||
|
||||
#if defined(EEXIST) && !defined(_WIN32)
|
||||
# define UV__EEXIST UV__ERR(EEXIST)
|
||||
#else
|
||||
# define UV__EEXIST (-4075)
|
||||
#endif
|
||||
|
||||
#if defined(EFAULT) && !defined(_WIN32)
|
||||
# define UV__EFAULT UV__ERR(EFAULT)
|
||||
#else
|
||||
# define UV__EFAULT (-4074)
|
||||
#endif
|
||||
|
||||
#if defined(EHOSTUNREACH) && !defined(_WIN32)
|
||||
# define UV__EHOSTUNREACH UV__ERR(EHOSTUNREACH)
|
||||
#else
|
||||
# define UV__EHOSTUNREACH (-4073)
|
||||
#endif
|
||||
|
||||
#if defined(EINTR) && !defined(_WIN32)
|
||||
# define UV__EINTR UV__ERR(EINTR)
|
||||
#else
|
||||
# define UV__EINTR (-4072)
|
||||
#endif
|
||||
|
||||
#if defined(EINVAL) && !defined(_WIN32)
|
||||
# define UV__EINVAL UV__ERR(EINVAL)
|
||||
#else
|
||||
# define UV__EINVAL (-4071)
|
||||
#endif
|
||||
|
||||
#if defined(EIO) && !defined(_WIN32)
|
||||
# define UV__EIO UV__ERR(EIO)
|
||||
#else
|
||||
# define UV__EIO (-4070)
|
||||
#endif
|
||||
|
||||
#if defined(EISCONN) && !defined(_WIN32)
|
||||
# define UV__EISCONN UV__ERR(EISCONN)
|
||||
#else
|
||||
# define UV__EISCONN (-4069)
|
||||
#endif
|
||||
|
||||
#if defined(EISDIR) && !defined(_WIN32)
|
||||
# define UV__EISDIR UV__ERR(EISDIR)
|
||||
#else
|
||||
# define UV__EISDIR (-4068)
|
||||
#endif
|
||||
|
||||
#if defined(ELOOP) && !defined(_WIN32)
|
||||
# define UV__ELOOP UV__ERR(ELOOP)
|
||||
#else
|
||||
# define UV__ELOOP (-4067)
|
||||
#endif
|
||||
|
||||
#if defined(EMFILE) && !defined(_WIN32)
|
||||
# define UV__EMFILE UV__ERR(EMFILE)
|
||||
#else
|
||||
# define UV__EMFILE (-4066)
|
||||
#endif
|
||||
|
||||
#if defined(EMSGSIZE) && !defined(_WIN32)
|
||||
# define UV__EMSGSIZE UV__ERR(EMSGSIZE)
|
||||
#else
|
||||
# define UV__EMSGSIZE (-4065)
|
||||
#endif
|
||||
|
||||
#if defined(ENAMETOOLONG) && !defined(_WIN32)
|
||||
# define UV__ENAMETOOLONG UV__ERR(ENAMETOOLONG)
|
||||
#else
|
||||
# define UV__ENAMETOOLONG (-4064)
|
||||
#endif
|
||||
|
||||
#if defined(ENETDOWN) && !defined(_WIN32)
|
||||
# define UV__ENETDOWN UV__ERR(ENETDOWN)
|
||||
#else
|
||||
# define UV__ENETDOWN (-4063)
|
||||
#endif
|
||||
|
||||
#if defined(ENETUNREACH) && !defined(_WIN32)
|
||||
# define UV__ENETUNREACH UV__ERR(ENETUNREACH)
|
||||
#else
|
||||
# define UV__ENETUNREACH (-4062)
|
||||
#endif
|
||||
|
||||
#if defined(ENFILE) && !defined(_WIN32)
|
||||
# define UV__ENFILE UV__ERR(ENFILE)
|
||||
#else
|
||||
# define UV__ENFILE (-4061)
|
||||
#endif
|
||||
|
||||
#if defined(ENOBUFS) && !defined(_WIN32)
|
||||
# define UV__ENOBUFS UV__ERR(ENOBUFS)
|
||||
#else
|
||||
# define UV__ENOBUFS (-4060)
|
||||
#endif
|
||||
|
||||
#if defined(ENODEV) && !defined(_WIN32)
|
||||
# define UV__ENODEV UV__ERR(ENODEV)
|
||||
#else
|
||||
# define UV__ENODEV (-4059)
|
||||
#endif
|
||||
|
||||
#if defined(ENOENT) && !defined(_WIN32)
|
||||
# define UV__ENOENT UV__ERR(ENOENT)
|
||||
#else
|
||||
# define UV__ENOENT (-4058)
|
||||
#endif
|
||||
|
||||
#if defined(ENOMEM) && !defined(_WIN32)
|
||||
# define UV__ENOMEM UV__ERR(ENOMEM)
|
||||
#else
|
||||
# define UV__ENOMEM (-4057)
|
||||
#endif
|
||||
|
||||
#if defined(ENONET) && !defined(_WIN32)
|
||||
# define UV__ENONET UV__ERR(ENONET)
|
||||
#else
|
||||
# define UV__ENONET (-4056)
|
||||
#endif
|
||||
|
||||
#if defined(ENOSPC) && !defined(_WIN32)
|
||||
# define UV__ENOSPC UV__ERR(ENOSPC)
|
||||
#else
|
||||
# define UV__ENOSPC (-4055)
|
||||
#endif
|
||||
|
||||
#if defined(ENOSYS) && !defined(_WIN32)
|
||||
# define UV__ENOSYS UV__ERR(ENOSYS)
|
||||
#else
|
||||
# define UV__ENOSYS (-4054)
|
||||
#endif
|
||||
|
||||
#if defined(ENOTCONN) && !defined(_WIN32)
|
||||
# define UV__ENOTCONN UV__ERR(ENOTCONN)
|
||||
#else
|
||||
# define UV__ENOTCONN (-4053)
|
||||
#endif
|
||||
|
||||
#if defined(ENOTDIR) && !defined(_WIN32)
|
||||
# define UV__ENOTDIR UV__ERR(ENOTDIR)
|
||||
#else
|
||||
# define UV__ENOTDIR (-4052)
|
||||
#endif
|
||||
|
||||
#if defined(ENOTEMPTY) && !defined(_WIN32)
|
||||
# define UV__ENOTEMPTY UV__ERR(ENOTEMPTY)
|
||||
#else
|
||||
# define UV__ENOTEMPTY (-4051)
|
||||
#endif
|
||||
|
||||
#if defined(ENOTSOCK) && !defined(_WIN32)
|
||||
# define UV__ENOTSOCK UV__ERR(ENOTSOCK)
|
||||
#else
|
||||
# define UV__ENOTSOCK (-4050)
|
||||
#endif
|
||||
|
||||
#if defined(ENOTSUP) && !defined(_WIN32)
|
||||
# define UV__ENOTSUP UV__ERR(ENOTSUP)
|
||||
#else
|
||||
# define UV__ENOTSUP (-4049)
|
||||
#endif
|
||||
|
||||
#if defined(EPERM) && !defined(_WIN32)
|
||||
# define UV__EPERM UV__ERR(EPERM)
|
||||
#else
|
||||
# define UV__EPERM (-4048)
|
||||
#endif
|
||||
|
||||
#if defined(EPIPE) && !defined(_WIN32)
|
||||
# define UV__EPIPE UV__ERR(EPIPE)
|
||||
#else
|
||||
# define UV__EPIPE (-4047)
|
||||
#endif
|
||||
|
||||
#if defined(EPROTO) && !defined(_WIN32)
|
||||
# define UV__EPROTO UV__ERR(EPROTO)
|
||||
#else
|
||||
# define UV__EPROTO UV__ERR(4046)
|
||||
#endif
|
||||
|
||||
#if defined(EPROTONOSUPPORT) && !defined(_WIN32)
|
||||
# define UV__EPROTONOSUPPORT UV__ERR(EPROTONOSUPPORT)
|
||||
#else
|
||||
# define UV__EPROTONOSUPPORT (-4045)
|
||||
#endif
|
||||
|
||||
#if defined(EPROTOTYPE) && !defined(_WIN32)
|
||||
# define UV__EPROTOTYPE UV__ERR(EPROTOTYPE)
|
||||
#else
|
||||
# define UV__EPROTOTYPE (-4044)
|
||||
#endif
|
||||
|
||||
#if defined(EROFS) && !defined(_WIN32)
|
||||
# define UV__EROFS UV__ERR(EROFS)
|
||||
#else
|
||||
# define UV__EROFS (-4043)
|
||||
#endif
|
||||
|
||||
#if defined(ESHUTDOWN) && !defined(_WIN32)
|
||||
# define UV__ESHUTDOWN UV__ERR(ESHUTDOWN)
|
||||
#else
|
||||
# define UV__ESHUTDOWN (-4042)
|
||||
#endif
|
||||
|
||||
#if defined(ESPIPE) && !defined(_WIN32)
|
||||
# define UV__ESPIPE UV__ERR(ESPIPE)
|
||||
#else
|
||||
# define UV__ESPIPE (-4041)
|
||||
#endif
|
||||
|
||||
#if defined(ESRCH) && !defined(_WIN32)
|
||||
# define UV__ESRCH UV__ERR(ESRCH)
|
||||
#else
|
||||
# define UV__ESRCH (-4040)
|
||||
#endif
|
||||
|
||||
#if defined(ETIMEDOUT) && !defined(_WIN32)
|
||||
# define UV__ETIMEDOUT UV__ERR(ETIMEDOUT)
|
||||
#else
|
||||
# define UV__ETIMEDOUT (-4039)
|
||||
#endif
|
||||
|
||||
#if defined(ETXTBSY) && !defined(_WIN32)
|
||||
# define UV__ETXTBSY UV__ERR(ETXTBSY)
|
||||
#else
|
||||
# define UV__ETXTBSY (-4038)
|
||||
#endif
|
||||
|
||||
#if defined(EXDEV) && !defined(_WIN32)
|
||||
# define UV__EXDEV UV__ERR(EXDEV)
|
||||
#else
|
||||
# define UV__EXDEV (-4037)
|
||||
#endif
|
||||
|
||||
#if defined(EFBIG) && !defined(_WIN32)
|
||||
# define UV__EFBIG UV__ERR(EFBIG)
|
||||
#else
|
||||
# define UV__EFBIG (-4036)
|
||||
#endif
|
||||
|
||||
#if defined(ENOPROTOOPT) && !defined(_WIN32)
|
||||
# define UV__ENOPROTOOPT UV__ERR(ENOPROTOOPT)
|
||||
#else
|
||||
# define UV__ENOPROTOOPT (-4035)
|
||||
#endif
|
||||
|
||||
#if defined(ERANGE) && !defined(_WIN32)
|
||||
# define UV__ERANGE UV__ERR(ERANGE)
|
||||
#else
|
||||
# define UV__ERANGE (-4034)
|
||||
#endif
|
||||
|
||||
#if defined(ENXIO) && !defined(_WIN32)
|
||||
# define UV__ENXIO UV__ERR(ENXIO)
|
||||
#else
|
||||
# define UV__ENXIO (-4033)
|
||||
#endif
|
||||
|
||||
#if defined(EMLINK) && !defined(_WIN32)
|
||||
# define UV__EMLINK UV__ERR(EMLINK)
|
||||
#else
|
||||
# define UV__EMLINK (-4032)
|
||||
#endif
|
||||
|
||||
/* EHOSTDOWN is not visible on BSD-like systems when _POSIX_C_SOURCE is
|
||||
* defined. Fortunately, its value is always 64 so it's possible albeit
|
||||
* icky to hard-code it.
|
||||
*/
|
||||
#if defined(EHOSTDOWN) && !defined(_WIN32)
|
||||
# define UV__EHOSTDOWN UV__ERR(EHOSTDOWN)
|
||||
#elif defined(__APPLE__) || \
|
||||
defined(__DragonFly__) || \
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__FreeBSD_kernel__) || \
|
||||
defined(__NetBSD__) || \
|
||||
defined(__OpenBSD__)
|
||||
# define UV__EHOSTDOWN (-64)
|
||||
#else
|
||||
# define UV__EHOSTDOWN (-4031)
|
||||
#endif
|
||||
|
||||
#if defined(EREMOTEIO) && !defined(_WIN32)
|
||||
# define UV__EREMOTEIO UV__ERR(EREMOTEIO)
|
||||
#else
|
||||
# define UV__EREMOTEIO (-4030)
|
||||
#endif
|
||||
|
||||
#if defined(ENOTTY) && !defined(_WIN32)
|
||||
# define UV__ENOTTY UV__ERR(ENOTTY)
|
||||
#else
|
||||
# define UV__ENOTTY (-4029)
|
||||
#endif
|
||||
|
||||
#if defined(EFTYPE) && !defined(_WIN32)
|
||||
# define UV__EFTYPE UV__ERR(EFTYPE)
|
||||
#else
|
||||
# define UV__EFTYPE (-4028)
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* UV_ERRNO_H_ */
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UV_LINUX_H
|
||||
#define UV_LINUX_H
|
||||
|
||||
#define UV_PLATFORM_LOOP_FIELDS \
|
||||
uv__io_t inotify_read_watcher; \
|
||||
void* inotify_watchers; \
|
||||
int inotify_fd; \
|
||||
|
||||
#define UV_PLATFORM_FS_EVENT_FIELDS \
|
||||
void* watchers[2]; \
|
||||
int wd; \
|
||||
|
||||
#endif /* UV_LINUX_H */
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/* Copyright libuv project contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UV_MVS_H
|
||||
#define UV_MVS_H
|
||||
|
||||
#define UV_PLATFORM_SEM_T long
|
||||
|
||||
#define UV_PLATFORM_LOOP_FIELDS \
|
||||
void* ep; \
|
||||
|
||||
#define UV_PLATFORM_FS_EVENT_FIELDS \
|
||||
char rfis_rftok[8]; \
|
||||
|
||||
#endif /* UV_MVS_H */
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/* Copyright libuv project contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UV_POSIX_H
|
||||
#define UV_POSIX_H
|
||||
|
||||
#define UV_PLATFORM_LOOP_FIELDS \
|
||||
struct pollfd* poll_fds; \
|
||||
size_t poll_fds_used; \
|
||||
size_t poll_fds_size; \
|
||||
unsigned char poll_fds_iterating; \
|
||||
|
||||
#endif /* UV_POSIX_H */
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
Copyright (c) 2016, Kari Tristan Helgason <kthelgason@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _UV_PTHREAD_BARRIER_
|
||||
#define _UV_PTHREAD_BARRIER_
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#if !defined(__MVS__)
|
||||
#include <semaphore.h> /* sem_t */
|
||||
#endif
|
||||
|
||||
#define PTHREAD_BARRIER_SERIAL_THREAD 0x12345
|
||||
#define UV__PTHREAD_BARRIER_FALLBACK 1
|
||||
|
||||
/*
|
||||
* To maintain ABI compatibility with
|
||||
* libuv v1.x struct is padded according
|
||||
* to target platform
|
||||
*/
|
||||
#if defined(__ANDROID__)
|
||||
# define UV_BARRIER_STRUCT_PADDING \
|
||||
sizeof(pthread_mutex_t) + \
|
||||
sizeof(pthread_cond_t) + \
|
||||
sizeof(unsigned int) - \
|
||||
sizeof(void *)
|
||||
#elif defined(__APPLE__)
|
||||
# define UV_BARRIER_STRUCT_PADDING \
|
||||
sizeof(pthread_mutex_t) + \
|
||||
2 * sizeof(sem_t) + \
|
||||
2 * sizeof(unsigned int) - \
|
||||
sizeof(void *)
|
||||
#else
|
||||
# define UV_BARRIER_STRUCT_PADDING 0
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
unsigned threshold;
|
||||
unsigned in;
|
||||
unsigned out;
|
||||
} _uv_barrier;
|
||||
|
||||
typedef struct {
|
||||
_uv_barrier* b;
|
||||
char _pad[UV_BARRIER_STRUCT_PADDING];
|
||||
} pthread_barrier_t;
|
||||
|
||||
int pthread_barrier_init(pthread_barrier_t* barrier,
|
||||
const void* barrier_attr,
|
||||
unsigned count);
|
||||
|
||||
int pthread_barrier_wait(pthread_barrier_t* barrier);
|
||||
int pthread_barrier_destroy(pthread_barrier_t *barrier);
|
||||
|
||||
#endif /* _UV_PTHREAD_BARRIER_ */
|
||||
|
|
@ -0,0 +1,247 @@
|
|||
// ISO C9x compliant stdint.h for Microsoft Visual Studio
|
||||
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
|
||||
//
|
||||
// Copyright (c) 2006-2008 Alexander Chemeris
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. The name of the author may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _MSC_VER // [
|
||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif // _MSC_VER ]
|
||||
|
||||
#ifndef _MSC_STDINT_H_ // [
|
||||
#define _MSC_STDINT_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
|
||||
// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
|
||||
// or compiler give many errors like this:
|
||||
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
# include <wchar.h>
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// Define _W64 macros to mark types changing their size, like intptr_t.
|
||||
#ifndef _W64
|
||||
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
|
||||
# define _W64 __w64
|
||||
# else
|
||||
# define _W64
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
// 7.18.1 Integer types
|
||||
|
||||
// 7.18.1.1 Exact-width integer types
|
||||
|
||||
// Visual Studio 6 and Embedded Visual C++ 4 doesn't
|
||||
// realize that, e.g. char has the same size as __int8
|
||||
// so we give up on __intX for them.
|
||||
#if (_MSC_VER < 1300)
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#else
|
||||
typedef signed __int8 int8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
#endif
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
|
||||
// 7.18.1.2 Minimum-width integer types
|
||||
typedef int8_t int_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
typedef int64_t int_least64_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
typedef uint64_t uint_least64_t;
|
||||
|
||||
// 7.18.1.3 Fastest minimum-width integer types
|
||||
typedef int8_t int_fast8_t;
|
||||
typedef int16_t int_fast16_t;
|
||||
typedef int32_t int_fast32_t;
|
||||
typedef int64_t int_fast64_t;
|
||||
typedef uint8_t uint_fast8_t;
|
||||
typedef uint16_t uint_fast16_t;
|
||||
typedef uint32_t uint_fast32_t;
|
||||
typedef uint64_t uint_fast64_t;
|
||||
|
||||
// 7.18.1.4 Integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
typedef signed __int64 intptr_t;
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
#else // _WIN64 ][
|
||||
typedef _W64 signed int intptr_t;
|
||||
typedef _W64 unsigned int uintptr_t;
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.1.5 Greatest-width integer types
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
|
||||
|
||||
// 7.18.2 Limits of specified-width integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
|
||||
|
||||
// 7.18.2.1 Limits of exact-width integer types
|
||||
#define INT8_MIN ((int8_t)_I8_MIN)
|
||||
#define INT8_MAX _I8_MAX
|
||||
#define INT16_MIN ((int16_t)_I16_MIN)
|
||||
#define INT16_MAX _I16_MAX
|
||||
#define INT32_MIN ((int32_t)_I32_MIN)
|
||||
#define INT32_MAX _I32_MAX
|
||||
#define INT64_MIN ((int64_t)_I64_MIN)
|
||||
#define INT64_MAX _I64_MAX
|
||||
#define UINT8_MAX _UI8_MAX
|
||||
#define UINT16_MAX _UI16_MAX
|
||||
#define UINT32_MAX _UI32_MAX
|
||||
#define UINT64_MAX _UI64_MAX
|
||||
|
||||
// 7.18.2.2 Limits of minimum-width integer types
|
||||
#define INT_LEAST8_MIN INT8_MIN
|
||||
#define INT_LEAST8_MAX INT8_MAX
|
||||
#define INT_LEAST16_MIN INT16_MIN
|
||||
#define INT_LEAST16_MAX INT16_MAX
|
||||
#define INT_LEAST32_MIN INT32_MIN
|
||||
#define INT_LEAST32_MAX INT32_MAX
|
||||
#define INT_LEAST64_MIN INT64_MIN
|
||||
#define INT_LEAST64_MAX INT64_MAX
|
||||
#define UINT_LEAST8_MAX UINT8_MAX
|
||||
#define UINT_LEAST16_MAX UINT16_MAX
|
||||
#define UINT_LEAST32_MAX UINT32_MAX
|
||||
#define UINT_LEAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.3 Limits of fastest minimum-width integer types
|
||||
#define INT_FAST8_MIN INT8_MIN
|
||||
#define INT_FAST8_MAX INT8_MAX
|
||||
#define INT_FAST16_MIN INT16_MIN
|
||||
#define INT_FAST16_MAX INT16_MAX
|
||||
#define INT_FAST32_MIN INT32_MIN
|
||||
#define INT_FAST32_MAX INT32_MAX
|
||||
#define INT_FAST64_MIN INT64_MIN
|
||||
#define INT_FAST64_MAX INT64_MAX
|
||||
#define UINT_FAST8_MAX UINT8_MAX
|
||||
#define UINT_FAST16_MAX UINT16_MAX
|
||||
#define UINT_FAST32_MAX UINT32_MAX
|
||||
#define UINT_FAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.4 Limits of integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
# define INTPTR_MIN INT64_MIN
|
||||
# define INTPTR_MAX INT64_MAX
|
||||
# define UINTPTR_MAX UINT64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define INTPTR_MIN INT32_MIN
|
||||
# define INTPTR_MAX INT32_MAX
|
||||
# define UINTPTR_MAX UINT32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.2.5 Limits of greatest-width integer types
|
||||
#define INTMAX_MIN INT64_MIN
|
||||
#define INTMAX_MAX INT64_MAX
|
||||
#define UINTMAX_MAX UINT64_MAX
|
||||
|
||||
// 7.18.3 Limits of other integer types
|
||||
|
||||
#ifdef _WIN64 // [
|
||||
# define PTRDIFF_MIN _I64_MIN
|
||||
# define PTRDIFF_MAX _I64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define PTRDIFF_MIN _I32_MIN
|
||||
# define PTRDIFF_MAX _I32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
#define SIG_ATOMIC_MIN INT_MIN
|
||||
#define SIG_ATOMIC_MAX INT_MAX
|
||||
|
||||
#ifndef SIZE_MAX // [
|
||||
# ifdef _WIN64 // [
|
||||
# define SIZE_MAX _UI64_MAX
|
||||
# else // _WIN64 ][
|
||||
# define SIZE_MAX _UI32_MAX
|
||||
# endif // _WIN64 ]
|
||||
#endif // SIZE_MAX ]
|
||||
|
||||
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
|
||||
#ifndef WCHAR_MIN // [
|
||||
# define WCHAR_MIN 0
|
||||
#endif // WCHAR_MIN ]
|
||||
#ifndef WCHAR_MAX // [
|
||||
# define WCHAR_MAX _UI16_MAX
|
||||
#endif // WCHAR_MAX ]
|
||||
|
||||
#define WINT_MIN 0
|
||||
#define WINT_MAX _UI16_MAX
|
||||
|
||||
#endif // __STDC_LIMIT_MACROS ]
|
||||
|
||||
|
||||
// 7.18.4 Limits of other integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
|
||||
|
||||
// 7.18.4.1 Macros for minimum-width integer constants
|
||||
|
||||
#define INT8_C(val) val##i8
|
||||
#define INT16_C(val) val##i16
|
||||
#define INT32_C(val) val##i32
|
||||
#define INT64_C(val) val##i64
|
||||
|
||||
#define UINT8_C(val) val##ui8
|
||||
#define UINT16_C(val) val##ui16
|
||||
#define UINT32_C(val) val##ui32
|
||||
#define UINT64_C(val) val##ui64
|
||||
|
||||
// 7.18.4.2 Macros for greatest-width integer constants
|
||||
#define INTMAX_C INT64_C
|
||||
#define UINTMAX_C UINT64_C
|
||||
|
||||
#endif // __STDC_CONSTANT_MACROS ]
|
||||
|
||||
|
||||
#endif // _MSC_STDINT_H_ ]
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UV_SUNOS_H
|
||||
#define UV_SUNOS_H
|
||||
|
||||
#include <sys/port.h>
|
||||
#include <port.h>
|
||||
|
||||
/* For the sake of convenience and reduced #ifdef-ery in src/unix/sunos.c,
|
||||
* add the fs_event fields even when this version of SunOS doesn't support
|
||||
* file watching.
|
||||
*/
|
||||
#define UV_PLATFORM_LOOP_FIELDS \
|
||||
uv__io_t fs_event_watcher; \
|
||||
int fs_fd; \
|
||||
|
||||
#if defined(PORT_SOURCE_FILE)
|
||||
|
||||
# define UV_PLATFORM_FS_EVENT_FIELDS \
|
||||
file_obj_t fo; \
|
||||
int fd; \
|
||||
|
||||
#endif /* defined(PORT_SOURCE_FILE) */
|
||||
|
||||
#endif /* UV_SUNOS_H */
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is private to libuv. It provides common functionality to both
|
||||
* Windows and Unix backends.
|
||||
*/
|
||||
|
||||
#ifndef UV_THREADPOOL_H_
|
||||
#define UV_THREADPOOL_H_
|
||||
|
||||
struct uv__work {
|
||||
void (*work)(struct uv__work *w);
|
||||
void (*done)(struct uv__work *w, int status);
|
||||
struct uv_loop_s* loop;
|
||||
void* wq[2];
|
||||
};
|
||||
|
||||
#endif /* UV_THREADPOOL_H_ */
|
||||
|
|
@ -0,0 +1,768 @@
|
|||
/*-
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef UV_TREE_H_
|
||||
#define UV_TREE_H_
|
||||
|
||||
#ifndef UV__UNUSED
|
||||
# if __GNUC__
|
||||
# define UV__UNUSED __attribute__((unused))
|
||||
# else
|
||||
# define UV__UNUSED
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This file defines data structures for different types of trees:
|
||||
* splay trees and red-black trees.
|
||||
*
|
||||
* A splay tree is a self-organizing data structure. Every operation
|
||||
* on the tree causes a splay to happen. The splay moves the requested
|
||||
* node to the root of the tree and partly rebalances it.
|
||||
*
|
||||
* This has the benefit that request locality causes faster lookups as
|
||||
* the requested nodes move to the top of the tree. On the other hand,
|
||||
* every lookup causes memory writes.
|
||||
*
|
||||
* The Balance Theorem bounds the total access time for m operations
|
||||
* and n inserts on an initially empty tree as O((m + n)lg n). The
|
||||
* amortized cost for a sequence of m accesses to a splay tree is O(lg n);
|
||||
*
|
||||
* A red-black tree is a binary search tree with the node color as an
|
||||
* extra attribute. It fulfills a set of conditions:
|
||||
* - every search path from the root to a leaf consists of the
|
||||
* same number of black nodes,
|
||||
* - each red node (except for the root) has a black parent,
|
||||
* - each leaf node is black.
|
||||
*
|
||||
* Every operation on a red-black tree is bounded as O(lg n).
|
||||
* The maximum height of a red-black tree is 2lg (n+1).
|
||||
*/
|
||||
|
||||
#define SPLAY_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *sph_root; /* root of the tree */ \
|
||||
}
|
||||
|
||||
#define SPLAY_INITIALIZER(root) \
|
||||
{ NULL }
|
||||
|
||||
#define SPLAY_INIT(root) do { \
|
||||
(root)->sph_root = NULL; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *spe_left; /* left element */ \
|
||||
struct type *spe_right; /* right element */ \
|
||||
}
|
||||
|
||||
#define SPLAY_LEFT(elm, field) (elm)->field.spe_left
|
||||
#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right
|
||||
#define SPLAY_ROOT(head) (head)->sph_root
|
||||
#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
|
||||
|
||||
/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
|
||||
#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \
|
||||
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
|
||||
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
|
||||
(head)->sph_root = tmp; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
|
||||
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
|
||||
(head)->sph_root = tmp; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_LINKLEFT(head, tmp, field) do { \
|
||||
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
|
||||
tmp = (head)->sph_root; \
|
||||
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_LINKRIGHT(head, tmp, field) do { \
|
||||
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
|
||||
tmp = (head)->sph_root; \
|
||||
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
|
||||
SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
|
||||
SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
/* Generates prototypes and inline functions */
|
||||
|
||||
#define SPLAY_PROTOTYPE(name, type, field, cmp) \
|
||||
void name##_SPLAY(struct name *, struct type *); \
|
||||
void name##_SPLAY_MINMAX(struct name *, int); \
|
||||
struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
|
||||
struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
|
||||
\
|
||||
/* Finds the node with the same key as elm */ \
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_FIND(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
if (SPLAY_EMPTY(head)) \
|
||||
return(NULL); \
|
||||
name##_SPLAY(head, elm); \
|
||||
if ((cmp)(elm, (head)->sph_root) == 0) \
|
||||
return (head->sph_root); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_NEXT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
name##_SPLAY(head, elm); \
|
||||
if (SPLAY_RIGHT(elm, field) != NULL) { \
|
||||
elm = SPLAY_RIGHT(elm, field); \
|
||||
while (SPLAY_LEFT(elm, field) != NULL) { \
|
||||
elm = SPLAY_LEFT(elm, field); \
|
||||
} \
|
||||
} else \
|
||||
elm = NULL; \
|
||||
return (elm); \
|
||||
} \
|
||||
\
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_MIN_MAX(struct name *head, int val) \
|
||||
{ \
|
||||
name##_SPLAY_MINMAX(head, val); \
|
||||
return (SPLAY_ROOT(head)); \
|
||||
}
|
||||
|
||||
/* Main splay operation.
|
||||
* Moves node close to the key of elm to top
|
||||
*/
|
||||
#define SPLAY_GENERATE(name, type, field, cmp) \
|
||||
struct type * \
|
||||
name##_SPLAY_INSERT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
if (SPLAY_EMPTY(head)) { \
|
||||
SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \
|
||||
} else { \
|
||||
int __comp; \
|
||||
name##_SPLAY(head, elm); \
|
||||
__comp = (cmp)(elm, (head)->sph_root); \
|
||||
if(__comp < 0) { \
|
||||
SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field); \
|
||||
SPLAY_RIGHT(elm, field) = (head)->sph_root; \
|
||||
SPLAY_LEFT((head)->sph_root, field) = NULL; \
|
||||
} else if (__comp > 0) { \
|
||||
SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
SPLAY_LEFT(elm, field) = (head)->sph_root; \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = NULL; \
|
||||
} else \
|
||||
return ((head)->sph_root); \
|
||||
} \
|
||||
(head)->sph_root = (elm); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
struct type * \
|
||||
name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *__tmp; \
|
||||
if (SPLAY_EMPTY(head)) \
|
||||
return (NULL); \
|
||||
name##_SPLAY(head, elm); \
|
||||
if ((cmp)(elm, (head)->sph_root) == 0) { \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
|
||||
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
} else { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
|
||||
name##_SPLAY(head, elm); \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
|
||||
} \
|
||||
return (elm); \
|
||||
} \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
name##_SPLAY(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type __node, *__left, *__right, *__tmp; \
|
||||
int __comp; \
|
||||
\
|
||||
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL; \
|
||||
__left = __right = &__node; \
|
||||
\
|
||||
while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \
|
||||
if (__comp < 0) { \
|
||||
__tmp = SPLAY_LEFT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if ((cmp)(elm, __tmp) < 0){ \
|
||||
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL) \
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKLEFT(head, __right, field); \
|
||||
} else if (__comp > 0) { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if ((cmp)(elm, __tmp) > 0){ \
|
||||
SPLAY_ROTATE_LEFT(head, __tmp, field); \
|
||||
if (SPLAY_RIGHT((head)->sph_root, field) == NULL) \
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKRIGHT(head, __left, field); \
|
||||
} \
|
||||
} \
|
||||
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
|
||||
} \
|
||||
\
|
||||
/* Splay with either the minimum or the maximum element \
|
||||
* Used to find minimum or maximum element in tree. \
|
||||
*/ \
|
||||
void name##_SPLAY_MINMAX(struct name *head, int __comp) \
|
||||
{ \
|
||||
struct type __node, *__left, *__right, *__tmp; \
|
||||
\
|
||||
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL; \
|
||||
__left = __right = &__node; \
|
||||
\
|
||||
while (1) { \
|
||||
if (__comp < 0) { \
|
||||
__tmp = SPLAY_LEFT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if (__comp < 0){ \
|
||||
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL) \
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKLEFT(head, __right, field); \
|
||||
} else if (__comp > 0) { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if (__comp > 0) { \
|
||||
SPLAY_ROTATE_LEFT(head, __tmp, field); \
|
||||
if (SPLAY_RIGHT((head)->sph_root, field) == NULL) \
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKRIGHT(head, __left, field); \
|
||||
} \
|
||||
} \
|
||||
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
|
||||
}
|
||||
|
||||
#define SPLAY_NEGINF -1
|
||||
#define SPLAY_INF 1
|
||||
|
||||
#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y)
|
||||
#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y)
|
||||
#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y)
|
||||
#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y)
|
||||
#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \
|
||||
: name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
|
||||
#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \
|
||||
: name##_SPLAY_MIN_MAX(x, SPLAY_INF))
|
||||
|
||||
#define SPLAY_FOREACH(x, name, head) \
|
||||
for ((x) = SPLAY_MIN(name, head); \
|
||||
(x) != NULL; \
|
||||
(x) = SPLAY_NEXT(name, head, x))
|
||||
|
||||
/* Macros that define a red-black tree */
|
||||
#define RB_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *rbh_root; /* root of the tree */ \
|
||||
}
|
||||
|
||||
#define RB_INITIALIZER(root) \
|
||||
{ NULL }
|
||||
|
||||
#define RB_INIT(root) do { \
|
||||
(root)->rbh_root = NULL; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define RB_BLACK 0
|
||||
#define RB_RED 1
|
||||
#define RB_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *rbe_left; /* left element */ \
|
||||
struct type *rbe_right; /* right element */ \
|
||||
struct type *rbe_parent; /* parent element */ \
|
||||
int rbe_color; /* node color */ \
|
||||
}
|
||||
|
||||
#define RB_LEFT(elm, field) (elm)->field.rbe_left
|
||||
#define RB_RIGHT(elm, field) (elm)->field.rbe_right
|
||||
#define RB_PARENT(elm, field) (elm)->field.rbe_parent
|
||||
#define RB_COLOR(elm, field) (elm)->field.rbe_color
|
||||
#define RB_ROOT(head) (head)->rbh_root
|
||||
#define RB_EMPTY(head) (RB_ROOT(head) == NULL)
|
||||
|
||||
#define RB_SET(elm, parent, field) do { \
|
||||
RB_PARENT(elm, field) = parent; \
|
||||
RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
|
||||
RB_COLOR(elm, field) = RB_RED; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define RB_SET_BLACKRED(black, red, field) do { \
|
||||
RB_COLOR(black, field) = RB_BLACK; \
|
||||
RB_COLOR(red, field) = RB_RED; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#ifndef RB_AUGMENT
|
||||
#define RB_AUGMENT(x) do {} while (0)
|
||||
#endif
|
||||
|
||||
#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
|
||||
(tmp) = RB_RIGHT(elm, field); \
|
||||
if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \
|
||||
RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \
|
||||
} \
|
||||
RB_AUGMENT(elm); \
|
||||
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
|
||||
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
|
||||
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
|
||||
else \
|
||||
RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
|
||||
} else \
|
||||
(head)->rbh_root = (tmp); \
|
||||
RB_LEFT(tmp, field) = (elm); \
|
||||
RB_PARENT(elm, field) = (tmp); \
|
||||
RB_AUGMENT(tmp); \
|
||||
if ((RB_PARENT(tmp, field))) \
|
||||
RB_AUGMENT(RB_PARENT(tmp, field)); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
|
||||
(tmp) = RB_LEFT(elm, field); \
|
||||
if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \
|
||||
RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \
|
||||
} \
|
||||
RB_AUGMENT(elm); \
|
||||
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
|
||||
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
|
||||
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
|
||||
else \
|
||||
RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
|
||||
} else \
|
||||
(head)->rbh_root = (tmp); \
|
||||
RB_RIGHT(tmp, field) = (elm); \
|
||||
RB_PARENT(elm, field) = (tmp); \
|
||||
RB_AUGMENT(tmp); \
|
||||
if ((RB_PARENT(tmp, field))) \
|
||||
RB_AUGMENT(RB_PARENT(tmp, field)); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
/* Generates prototypes and inline functions */
|
||||
#define RB_PROTOTYPE(name, type, field, cmp) \
|
||||
RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
|
||||
#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \
|
||||
RB_PROTOTYPE_INTERNAL(name, type, field, cmp, UV__UNUSED static)
|
||||
#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \
|
||||
attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \
|
||||
attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
|
||||
attr struct type *name##_RB_REMOVE(struct name *, struct type *); \
|
||||
attr struct type *name##_RB_INSERT(struct name *, struct type *); \
|
||||
attr struct type *name##_RB_FIND(struct name *, struct type *); \
|
||||
attr struct type *name##_RB_NFIND(struct name *, struct type *); \
|
||||
attr struct type *name##_RB_NEXT(struct type *); \
|
||||
attr struct type *name##_RB_PREV(struct type *); \
|
||||
attr struct type *name##_RB_MINMAX(struct name *, int); \
|
||||
\
|
||||
|
||||
/* Main rb operation.
|
||||
* Moves node close to the key of elm to top
|
||||
*/
|
||||
#define RB_GENERATE(name, type, field, cmp) \
|
||||
RB_GENERATE_INTERNAL(name, type, field, cmp,)
|
||||
#define RB_GENERATE_STATIC(name, type, field, cmp) \
|
||||
RB_GENERATE_INTERNAL(name, type, field, cmp, UV__UNUSED static)
|
||||
#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \
|
||||
attr void \
|
||||
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *parent, *gparent, *tmp; \
|
||||
while ((parent = RB_PARENT(elm, field)) != NULL && \
|
||||
RB_COLOR(parent, field) == RB_RED) { \
|
||||
gparent = RB_PARENT(parent, field); \
|
||||
if (parent == RB_LEFT(gparent, field)) { \
|
||||
tmp = RB_RIGHT(gparent, field); \
|
||||
if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
|
||||
RB_COLOR(tmp, field) = RB_BLACK; \
|
||||
RB_SET_BLACKRED(parent, gparent, field); \
|
||||
elm = gparent; \
|
||||
continue; \
|
||||
} \
|
||||
if (RB_RIGHT(parent, field) == elm) { \
|
||||
RB_ROTATE_LEFT(head, parent, tmp, field); \
|
||||
tmp = parent; \
|
||||
parent = elm; \
|
||||
elm = tmp; \
|
||||
} \
|
||||
RB_SET_BLACKRED(parent, gparent, field); \
|
||||
RB_ROTATE_RIGHT(head, gparent, tmp, field); \
|
||||
} else { \
|
||||
tmp = RB_LEFT(gparent, field); \
|
||||
if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
|
||||
RB_COLOR(tmp, field) = RB_BLACK; \
|
||||
RB_SET_BLACKRED(parent, gparent, field); \
|
||||
elm = gparent; \
|
||||
continue; \
|
||||
} \
|
||||
if (RB_LEFT(parent, field) == elm) { \
|
||||
RB_ROTATE_RIGHT(head, parent, tmp, field); \
|
||||
tmp = parent; \
|
||||
parent = elm; \
|
||||
elm = tmp; \
|
||||
} \
|
||||
RB_SET_BLACKRED(parent, gparent, field); \
|
||||
RB_ROTATE_LEFT(head, gparent, tmp, field); \
|
||||
} \
|
||||
} \
|
||||
RB_COLOR(head->rbh_root, field) = RB_BLACK; \
|
||||
} \
|
||||
\
|
||||
attr void \
|
||||
name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, \
|
||||
struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp; \
|
||||
while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \
|
||||
elm != RB_ROOT(head)) { \
|
||||
if (RB_LEFT(parent, field) == elm) { \
|
||||
tmp = RB_RIGHT(parent, field); \
|
||||
if (RB_COLOR(tmp, field) == RB_RED) { \
|
||||
RB_SET_BLACKRED(tmp, parent, field); \
|
||||
RB_ROTATE_LEFT(head, parent, tmp, field); \
|
||||
tmp = RB_RIGHT(parent, field); \
|
||||
} \
|
||||
if ((RB_LEFT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) && \
|
||||
(RB_RIGHT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) { \
|
||||
RB_COLOR(tmp, field) = RB_RED; \
|
||||
elm = parent; \
|
||||
parent = RB_PARENT(elm, field); \
|
||||
} else { \
|
||||
if (RB_RIGHT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) { \
|
||||
struct type *oleft; \
|
||||
if ((oleft = RB_LEFT(tmp, field)) \
|
||||
!= NULL) \
|
||||
RB_COLOR(oleft, field) = RB_BLACK; \
|
||||
RB_COLOR(tmp, field) = RB_RED; \
|
||||
RB_ROTATE_RIGHT(head, tmp, oleft, field); \
|
||||
tmp = RB_RIGHT(parent, field); \
|
||||
} \
|
||||
RB_COLOR(tmp, field) = RB_COLOR(parent, field); \
|
||||
RB_COLOR(parent, field) = RB_BLACK; \
|
||||
if (RB_RIGHT(tmp, field)) \
|
||||
RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK; \
|
||||
RB_ROTATE_LEFT(head, parent, tmp, field); \
|
||||
elm = RB_ROOT(head); \
|
||||
break; \
|
||||
} \
|
||||
} else { \
|
||||
tmp = RB_LEFT(parent, field); \
|
||||
if (RB_COLOR(tmp, field) == RB_RED) { \
|
||||
RB_SET_BLACKRED(tmp, parent, field); \
|
||||
RB_ROTATE_RIGHT(head, parent, tmp, field); \
|
||||
tmp = RB_LEFT(parent, field); \
|
||||
} \
|
||||
if ((RB_LEFT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) && \
|
||||
(RB_RIGHT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) { \
|
||||
RB_COLOR(tmp, field) = RB_RED; \
|
||||
elm = parent; \
|
||||
parent = RB_PARENT(elm, field); \
|
||||
} else { \
|
||||
if (RB_LEFT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) { \
|
||||
struct type *oright; \
|
||||
if ((oright = RB_RIGHT(tmp, field)) \
|
||||
!= NULL) \
|
||||
RB_COLOR(oright, field) = RB_BLACK; \
|
||||
RB_COLOR(tmp, field) = RB_RED; \
|
||||
RB_ROTATE_LEFT(head, tmp, oright, field); \
|
||||
tmp = RB_LEFT(parent, field); \
|
||||
} \
|
||||
RB_COLOR(tmp, field) = RB_COLOR(parent, field); \
|
||||
RB_COLOR(parent, field) = RB_BLACK; \
|
||||
if (RB_LEFT(tmp, field)) \
|
||||
RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK; \
|
||||
RB_ROTATE_RIGHT(head, parent, tmp, field); \
|
||||
elm = RB_ROOT(head); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
if (elm) \
|
||||
RB_COLOR(elm, field) = RB_BLACK; \
|
||||
} \
|
||||
\
|
||||
attr struct type * \
|
||||
name##_RB_REMOVE(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *child, *parent, *old = elm; \
|
||||
int color; \
|
||||
if (RB_LEFT(elm, field) == NULL) \
|
||||
child = RB_RIGHT(elm, field); \
|
||||
else if (RB_RIGHT(elm, field) == NULL) \
|
||||
child = RB_LEFT(elm, field); \
|
||||
else { \
|
||||
struct type *left; \
|
||||
elm = RB_RIGHT(elm, field); \
|
||||
while ((left = RB_LEFT(elm, field)) != NULL) \
|
||||
elm = left; \
|
||||
child = RB_RIGHT(elm, field); \
|
||||
parent = RB_PARENT(elm, field); \
|
||||
color = RB_COLOR(elm, field); \
|
||||
if (child) \
|
||||
RB_PARENT(child, field) = parent; \
|
||||
if (parent) { \
|
||||
if (RB_LEFT(parent, field) == elm) \
|
||||
RB_LEFT(parent, field) = child; \
|
||||
else \
|
||||
RB_RIGHT(parent, field) = child; \
|
||||
RB_AUGMENT(parent); \
|
||||
} else \
|
||||
RB_ROOT(head) = child; \
|
||||
if (RB_PARENT(elm, field) == old) \
|
||||
parent = elm; \
|
||||
(elm)->field = (old)->field; \
|
||||
if (RB_PARENT(old, field)) { \
|
||||
if (RB_LEFT(RB_PARENT(old, field), field) == old) \
|
||||
RB_LEFT(RB_PARENT(old, field), field) = elm; \
|
||||
else \
|
||||
RB_RIGHT(RB_PARENT(old, field), field) = elm; \
|
||||
RB_AUGMENT(RB_PARENT(old, field)); \
|
||||
} else \
|
||||
RB_ROOT(head) = elm; \
|
||||
RB_PARENT(RB_LEFT(old, field), field) = elm; \
|
||||
if (RB_RIGHT(old, field)) \
|
||||
RB_PARENT(RB_RIGHT(old, field), field) = elm; \
|
||||
if (parent) { \
|
||||
left = parent; \
|
||||
do { \
|
||||
RB_AUGMENT(left); \
|
||||
} while ((left = RB_PARENT(left, field)) != NULL); \
|
||||
} \
|
||||
goto color; \
|
||||
} \
|
||||
parent = RB_PARENT(elm, field); \
|
||||
color = RB_COLOR(elm, field); \
|
||||
if (child) \
|
||||
RB_PARENT(child, field) = parent; \
|
||||
if (parent) { \
|
||||
if (RB_LEFT(parent, field) == elm) \
|
||||
RB_LEFT(parent, field) = child; \
|
||||
else \
|
||||
RB_RIGHT(parent, field) = child; \
|
||||
RB_AUGMENT(parent); \
|
||||
} else \
|
||||
RB_ROOT(head) = child; \
|
||||
color: \
|
||||
if (color == RB_BLACK) \
|
||||
name##_RB_REMOVE_COLOR(head, parent, child); \
|
||||
return (old); \
|
||||
} \
|
||||
\
|
||||
/* Inserts a node into the RB tree */ \
|
||||
attr struct type * \
|
||||
name##_RB_INSERT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp; \
|
||||
struct type *parent = NULL; \
|
||||
int comp = 0; \
|
||||
tmp = RB_ROOT(head); \
|
||||
while (tmp) { \
|
||||
parent = tmp; \
|
||||
comp = (cmp)(elm, parent); \
|
||||
if (comp < 0) \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
else if (comp > 0) \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
else \
|
||||
return (tmp); \
|
||||
} \
|
||||
RB_SET(elm, parent, field); \
|
||||
if (parent != NULL) { \
|
||||
if (comp < 0) \
|
||||
RB_LEFT(parent, field) = elm; \
|
||||
else \
|
||||
RB_RIGHT(parent, field) = elm; \
|
||||
RB_AUGMENT(parent); \
|
||||
} else \
|
||||
RB_ROOT(head) = elm; \
|
||||
name##_RB_INSERT_COLOR(head, elm); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
/* Finds the node with the same key as elm */ \
|
||||
attr struct type * \
|
||||
name##_RB_FIND(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp = RB_ROOT(head); \
|
||||
int comp; \
|
||||
while (tmp) { \
|
||||
comp = cmp(elm, tmp); \
|
||||
if (comp < 0) \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
else if (comp > 0) \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
else \
|
||||
return (tmp); \
|
||||
} \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
/* Finds the first node greater than or equal to the search key */ \
|
||||
attr struct type * \
|
||||
name##_RB_NFIND(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp = RB_ROOT(head); \
|
||||
struct type *res = NULL; \
|
||||
int comp; \
|
||||
while (tmp) { \
|
||||
comp = cmp(elm, tmp); \
|
||||
if (comp < 0) { \
|
||||
res = tmp; \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
} \
|
||||
else if (comp > 0) \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
else \
|
||||
return (tmp); \
|
||||
} \
|
||||
return (res); \
|
||||
} \
|
||||
\
|
||||
/* ARGSUSED */ \
|
||||
attr struct type * \
|
||||
name##_RB_NEXT(struct type *elm) \
|
||||
{ \
|
||||
if (RB_RIGHT(elm, field)) { \
|
||||
elm = RB_RIGHT(elm, field); \
|
||||
while (RB_LEFT(elm, field)) \
|
||||
elm = RB_LEFT(elm, field); \
|
||||
} else { \
|
||||
if (RB_PARENT(elm, field) && \
|
||||
(elm == RB_LEFT(RB_PARENT(elm, field), field))) \
|
||||
elm = RB_PARENT(elm, field); \
|
||||
else { \
|
||||
while (RB_PARENT(elm, field) && \
|
||||
(elm == RB_RIGHT(RB_PARENT(elm, field), field))) \
|
||||
elm = RB_PARENT(elm, field); \
|
||||
elm = RB_PARENT(elm, field); \
|
||||
} \
|
||||
} \
|
||||
return (elm); \
|
||||
} \
|
||||
\
|
||||
/* ARGSUSED */ \
|
||||
attr struct type * \
|
||||
name##_RB_PREV(struct type *elm) \
|
||||
{ \
|
||||
if (RB_LEFT(elm, field)) { \
|
||||
elm = RB_LEFT(elm, field); \
|
||||
while (RB_RIGHT(elm, field)) \
|
||||
elm = RB_RIGHT(elm, field); \
|
||||
} else { \
|
||||
if (RB_PARENT(elm, field) && \
|
||||
(elm == RB_RIGHT(RB_PARENT(elm, field), field))) \
|
||||
elm = RB_PARENT(elm, field); \
|
||||
else { \
|
||||
while (RB_PARENT(elm, field) && \
|
||||
(elm == RB_LEFT(RB_PARENT(elm, field), field))) \
|
||||
elm = RB_PARENT(elm, field); \
|
||||
elm = RB_PARENT(elm, field); \
|
||||
} \
|
||||
} \
|
||||
return (elm); \
|
||||
} \
|
||||
\
|
||||
attr struct type * \
|
||||
name##_RB_MINMAX(struct name *head, int val) \
|
||||
{ \
|
||||
struct type *tmp = RB_ROOT(head); \
|
||||
struct type *parent = NULL; \
|
||||
while (tmp) { \
|
||||
parent = tmp; \
|
||||
if (val < 0) \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
else \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
} \
|
||||
return (parent); \
|
||||
}
|
||||
|
||||
#define RB_NEGINF -1
|
||||
#define RB_INF 1
|
||||
|
||||
#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
|
||||
#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
|
||||
#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
|
||||
#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y)
|
||||
#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
|
||||
#define RB_PREV(name, x, y) name##_RB_PREV(y)
|
||||
#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
|
||||
#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
|
||||
|
||||
#define RB_FOREACH(x, name, head) \
|
||||
for ((x) = RB_MIN(name, head); \
|
||||
(x) != NULL; \
|
||||
(x) = name##_RB_NEXT(x))
|
||||
|
||||
#define RB_FOREACH_FROM(x, name, y) \
|
||||
for ((x) = (y); \
|
||||
((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
|
||||
(x) = (y))
|
||||
|
||||
#define RB_FOREACH_SAFE(x, name, head, y) \
|
||||
for ((x) = RB_MIN(name, head); \
|
||||
((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
|
||||
(x) = (y))
|
||||
|
||||
#define RB_FOREACH_REVERSE(x, name, head) \
|
||||
for ((x) = RB_MAX(name, head); \
|
||||
(x) != NULL; \
|
||||
(x) = name##_RB_PREV(x))
|
||||
|
||||
#define RB_FOREACH_REVERSE_FROM(x, name, y) \
|
||||
for ((x) = (y); \
|
||||
((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
|
||||
(x) = (y))
|
||||
|
||||
#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \
|
||||
for ((x) = RB_MAX(name, head); \
|
||||
((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
|
||||
(x) = (y))
|
||||
|
||||
#endif /* UV_TREE_H_ */
|
||||
|
|
@ -0,0 +1,464 @@
|
|||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UV_UNIX_H
|
||||
#define UV_UNIX_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <termios.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#if !defined(__MVS__)
|
||||
#include <semaphore.h>
|
||||
#endif
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "uv/threadpool.h"
|
||||
|
||||
#if defined(__linux__)
|
||||
# include "uv/linux.h"
|
||||
#elif defined (__MVS__)
|
||||
# include "uv/os390.h"
|
||||
#elif defined(__PASE__)
|
||||
# include "uv/posix.h"
|
||||
#elif defined(_AIX)
|
||||
# include "uv/aix.h"
|
||||
#elif defined(__sun)
|
||||
# include "uv/sunos.h"
|
||||
#elif defined(__APPLE__)
|
||||
# include "uv/darwin.h"
|
||||
#elif defined(__DragonFly__) || \
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__FreeBSD_kernel__) || \
|
||||
defined(__OpenBSD__) || \
|
||||
defined(__NetBSD__)
|
||||
# include "uv/bsd.h"
|
||||
#elif defined(__CYGWIN__) || defined(__MSYS__)
|
||||
# include "uv/posix.h"
|
||||
#endif
|
||||
|
||||
#ifndef PTHREAD_BARRIER_SERIAL_THREAD
|
||||
# include "uv/pthread-barrier.h"
|
||||
#endif
|
||||
|
||||
#ifndef NI_MAXHOST
|
||||
# define NI_MAXHOST 1025
|
||||
#endif
|
||||
|
||||
#ifndef NI_MAXSERV
|
||||
# define NI_MAXSERV 32
|
||||
#endif
|
||||
|
||||
#ifndef UV_IO_PRIVATE_PLATFORM_FIELDS
|
||||
# define UV_IO_PRIVATE_PLATFORM_FIELDS /* empty */
|
||||
#endif
|
||||
|
||||
struct uv__io_s;
|
||||
struct uv_loop_s;
|
||||
|
||||
typedef void (*uv__io_cb)(struct uv_loop_s* loop,
|
||||
struct uv__io_s* w,
|
||||
unsigned int events);
|
||||
typedef struct uv__io_s uv__io_t;
|
||||
|
||||
struct uv__io_s {
|
||||
uv__io_cb cb;
|
||||
void* pending_queue[2];
|
||||
void* watcher_queue[2];
|
||||
unsigned int pevents; /* Pending event mask i.e. mask at next tick. */
|
||||
unsigned int events; /* Current event mask. */
|
||||
int fd;
|
||||
UV_IO_PRIVATE_PLATFORM_FIELDS
|
||||
};
|
||||
|
||||
#ifndef UV_PLATFORM_SEM_T
|
||||
# define UV_PLATFORM_SEM_T sem_t
|
||||
#endif
|
||||
|
||||
#ifndef UV_PLATFORM_LOOP_FIELDS
|
||||
# define UV_PLATFORM_LOOP_FIELDS /* empty */
|
||||
#endif
|
||||
|
||||
#ifndef UV_PLATFORM_FS_EVENT_FIELDS
|
||||
# define UV_PLATFORM_FS_EVENT_FIELDS /* empty */
|
||||
#endif
|
||||
|
||||
#ifndef UV_STREAM_PRIVATE_PLATFORM_FIELDS
|
||||
# define UV_STREAM_PRIVATE_PLATFORM_FIELDS /* empty */
|
||||
#endif
|
||||
|
||||
/* Note: May be cast to struct iovec. See writev(2). */
|
||||
typedef struct uv_buf_t {
|
||||
char* base;
|
||||
size_t len;
|
||||
} uv_buf_t;
|
||||
|
||||
typedef int uv_file;
|
||||
typedef int uv_os_sock_t;
|
||||
typedef int uv_os_fd_t;
|
||||
typedef pid_t uv_pid_t;
|
||||
|
||||
#define UV_ONCE_INIT PTHREAD_ONCE_INIT
|
||||
|
||||
typedef pthread_once_t uv_once_t;
|
||||
typedef pthread_t uv_thread_t;
|
||||
typedef pthread_mutex_t uv_mutex_t;
|
||||
typedef pthread_rwlock_t uv_rwlock_t;
|
||||
typedef UV_PLATFORM_SEM_T uv_sem_t;
|
||||
typedef pthread_cond_t uv_cond_t;
|
||||
typedef pthread_key_t uv_key_t;
|
||||
typedef pthread_barrier_t uv_barrier_t;
|
||||
|
||||
|
||||
/* Platform-specific definitions for uv_spawn support. */
|
||||
typedef gid_t uv_gid_t;
|
||||
typedef uid_t uv_uid_t;
|
||||
|
||||
typedef struct dirent uv__dirent_t;
|
||||
|
||||
#if defined(DT_UNKNOWN)
|
||||
# define HAVE_DIRENT_TYPES
|
||||
# if defined(DT_REG)
|
||||
# define UV__DT_FILE DT_REG
|
||||
# else
|
||||
# define UV__DT_FILE -1
|
||||
# endif
|
||||
# if defined(DT_DIR)
|
||||
# define UV__DT_DIR DT_DIR
|
||||
# else
|
||||
# define UV__DT_DIR -2
|
||||
# endif
|
||||
# if defined(DT_LNK)
|
||||
# define UV__DT_LINK DT_LNK
|
||||
# else
|
||||
# define UV__DT_LINK -3
|
||||
# endif
|
||||
# if defined(DT_FIFO)
|
||||
# define UV__DT_FIFO DT_FIFO
|
||||
# else
|
||||
# define UV__DT_FIFO -4
|
||||
# endif
|
||||
# if defined(DT_SOCK)
|
||||
# define UV__DT_SOCKET DT_SOCK
|
||||
# else
|
||||
# define UV__DT_SOCKET -5
|
||||
# endif
|
||||
# if defined(DT_CHR)
|
||||
# define UV__DT_CHAR DT_CHR
|
||||
# else
|
||||
# define UV__DT_CHAR -6
|
||||
# endif
|
||||
# if defined(DT_BLK)
|
||||
# define UV__DT_BLOCK DT_BLK
|
||||
# else
|
||||
# define UV__DT_BLOCK -7
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Platform-specific definitions for uv_dlopen support. */
|
||||
#define UV_DYNAMIC /* empty */
|
||||
|
||||
typedef struct {
|
||||
void* handle;
|
||||
char* errmsg;
|
||||
} uv_lib_t;
|
||||
|
||||
#define UV_LOOP_PRIVATE_FIELDS \
|
||||
unsigned long flags; \
|
||||
int backend_fd; \
|
||||
void* pending_queue[2]; \
|
||||
void* watcher_queue[2]; \
|
||||
uv__io_t** watchers; \
|
||||
unsigned int nwatchers; \
|
||||
unsigned int nfds; \
|
||||
void* wq[2]; \
|
||||
uv_mutex_t wq_mutex; \
|
||||
uv_async_t wq_async; \
|
||||
uv_rwlock_t cloexec_lock; \
|
||||
uv_handle_t* closing_handles; \
|
||||
void* process_handles[2]; \
|
||||
void* prepare_handles[2]; \
|
||||
void* check_handles[2]; \
|
||||
void* idle_handles[2]; \
|
||||
void* async_handles[2]; \
|
||||
void (*async_unused)(void); /* TODO(bnoordhuis) Remove in libuv v2. */ \
|
||||
uv__io_t async_io_watcher; \
|
||||
int async_wfd; \
|
||||
struct { \
|
||||
void* min; \
|
||||
unsigned int nelts; \
|
||||
} timer_heap; \
|
||||
uint64_t timer_counter; \
|
||||
uint64_t time; \
|
||||
int signal_pipefd[2]; \
|
||||
uv__io_t signal_io_watcher; \
|
||||
uv_signal_t child_watcher; \
|
||||
int emfile_fd; \
|
||||
UV_PLATFORM_LOOP_FIELDS \
|
||||
|
||||
#define UV_REQ_TYPE_PRIVATE /* empty */
|
||||
|
||||
#define UV_REQ_PRIVATE_FIELDS /* empty */
|
||||
|
||||
#define UV_PRIVATE_REQ_TYPES /* empty */
|
||||
|
||||
#define UV_WRITE_PRIVATE_FIELDS \
|
||||
void* queue[2]; \
|
||||
unsigned int write_index; \
|
||||
uv_buf_t* bufs; \
|
||||
unsigned int nbufs; \
|
||||
int error; \
|
||||
uv_buf_t bufsml[4]; \
|
||||
|
||||
#define UV_CONNECT_PRIVATE_FIELDS \
|
||||
void* queue[2]; \
|
||||
|
||||
#define UV_SHUTDOWN_PRIVATE_FIELDS /* empty */
|
||||
|
||||
#define UV_UDP_SEND_PRIVATE_FIELDS \
|
||||
void* queue[2]; \
|
||||
struct sockaddr_storage addr; \
|
||||
unsigned int nbufs; \
|
||||
uv_buf_t* bufs; \
|
||||
ssize_t status; \
|
||||
uv_udp_send_cb send_cb; \
|
||||
uv_buf_t bufsml[4]; \
|
||||
|
||||
#define UV_HANDLE_PRIVATE_FIELDS \
|
||||
uv_handle_t* next_closing; \
|
||||
unsigned int flags; \
|
||||
|
||||
#define UV_STREAM_PRIVATE_FIELDS \
|
||||
uv_connect_t *connect_req; \
|
||||
uv_shutdown_t *shutdown_req; \
|
||||
uv__io_t io_watcher; \
|
||||
void* write_queue[2]; \
|
||||
void* write_completed_queue[2]; \
|
||||
uv_connection_cb connection_cb; \
|
||||
int delayed_error; \
|
||||
int accepted_fd; \
|
||||
void* queued_fds; \
|
||||
UV_STREAM_PRIVATE_PLATFORM_FIELDS \
|
||||
|
||||
#define UV_TCP_PRIVATE_FIELDS /* empty */
|
||||
|
||||
#define UV_UDP_PRIVATE_FIELDS \
|
||||
uv_alloc_cb alloc_cb; \
|
||||
uv_udp_recv_cb recv_cb; \
|
||||
uv__io_t io_watcher; \
|
||||
void* write_queue[2]; \
|
||||
void* write_completed_queue[2]; \
|
||||
|
||||
#define UV_PIPE_PRIVATE_FIELDS \
|
||||
const char* pipe_fname; /* strdup'ed */
|
||||
|
||||
#define UV_POLL_PRIVATE_FIELDS \
|
||||
uv__io_t io_watcher;
|
||||
|
||||
#define UV_PREPARE_PRIVATE_FIELDS \
|
||||
uv_prepare_cb prepare_cb; \
|
||||
void* queue[2]; \
|
||||
|
||||
#define UV_CHECK_PRIVATE_FIELDS \
|
||||
uv_check_cb check_cb; \
|
||||
void* queue[2]; \
|
||||
|
||||
#define UV_IDLE_PRIVATE_FIELDS \
|
||||
uv_idle_cb idle_cb; \
|
||||
void* queue[2]; \
|
||||
|
||||
#define UV_ASYNC_PRIVATE_FIELDS \
|
||||
uv_async_cb async_cb; \
|
||||
void* queue[2]; \
|
||||
int pending; \
|
||||
|
||||
#define UV_TIMER_PRIVATE_FIELDS \
|
||||
uv_timer_cb timer_cb; \
|
||||
void* heap_node[3]; \
|
||||
uint64_t timeout; \
|
||||
uint64_t repeat; \
|
||||
uint64_t start_id;
|
||||
|
||||
#define UV_GETADDRINFO_PRIVATE_FIELDS \
|
||||
struct uv__work work_req; \
|
||||
uv_getaddrinfo_cb cb; \
|
||||
struct addrinfo* hints; \
|
||||
char* hostname; \
|
||||
char* service; \
|
||||
struct addrinfo* addrinfo; \
|
||||
int retcode;
|
||||
|
||||
#define UV_GETNAMEINFO_PRIVATE_FIELDS \
|
||||
struct uv__work work_req; \
|
||||
uv_getnameinfo_cb getnameinfo_cb; \
|
||||
struct sockaddr_storage storage; \
|
||||
int flags; \
|
||||
char host[NI_MAXHOST]; \
|
||||
char service[NI_MAXSERV]; \
|
||||
int retcode;
|
||||
|
||||
#define UV_PROCESS_PRIVATE_FIELDS \
|
||||
void* queue[2]; \
|
||||
int status; \
|
||||
|
||||
#define UV_FS_PRIVATE_FIELDS \
|
||||
const char *new_path; \
|
||||
uv_file file; \
|
||||
int flags; \
|
||||
mode_t mode; \
|
||||
unsigned int nbufs; \
|
||||
uv_buf_t* bufs; \
|
||||
off_t off; \
|
||||
uv_uid_t uid; \
|
||||
uv_gid_t gid; \
|
||||
double atime; \
|
||||
double mtime; \
|
||||
struct uv__work work_req; \
|
||||
uv_buf_t bufsml[4]; \
|
||||
|
||||
#define UV_WORK_PRIVATE_FIELDS \
|
||||
struct uv__work work_req;
|
||||
|
||||
#define UV_TTY_PRIVATE_FIELDS \
|
||||
struct termios orig_termios; \
|
||||
int mode;
|
||||
|
||||
#define UV_SIGNAL_PRIVATE_FIELDS \
|
||||
/* RB_ENTRY(uv_signal_s) tree_entry; */ \
|
||||
struct { \
|
||||
struct uv_signal_s* rbe_left; \
|
||||
struct uv_signal_s* rbe_right; \
|
||||
struct uv_signal_s* rbe_parent; \
|
||||
int rbe_color; \
|
||||
} tree_entry; \
|
||||
/* Use two counters here so we don have to fiddle with atomics. */ \
|
||||
unsigned int caught_signals; \
|
||||
unsigned int dispatched_signals;
|
||||
|
||||
#define UV_FS_EVENT_PRIVATE_FIELDS \
|
||||
uv_fs_event_cb cb; \
|
||||
UV_PLATFORM_FS_EVENT_FIELDS \
|
||||
|
||||
/* fs open() flags supported on this platform: */
|
||||
#if defined(O_APPEND)
|
||||
# define UV_FS_O_APPEND O_APPEND
|
||||
#else
|
||||
# define UV_FS_O_APPEND 0
|
||||
#endif
|
||||
#if defined(O_CREAT)
|
||||
# define UV_FS_O_CREAT O_CREAT
|
||||
#else
|
||||
# define UV_FS_O_CREAT 0
|
||||
#endif
|
||||
#if defined(O_DIRECT)
|
||||
# define UV_FS_O_DIRECT O_DIRECT
|
||||
#else
|
||||
# define UV_FS_O_DIRECT 0
|
||||
#endif
|
||||
#if defined(O_DIRECTORY)
|
||||
# define UV_FS_O_DIRECTORY O_DIRECTORY
|
||||
#else
|
||||
# define UV_FS_O_DIRECTORY 0
|
||||
#endif
|
||||
#if defined(O_DSYNC)
|
||||
# define UV_FS_O_DSYNC O_DSYNC
|
||||
#else
|
||||
# define UV_FS_O_DSYNC 0
|
||||
#endif
|
||||
#if defined(O_EXCL)
|
||||
# define UV_FS_O_EXCL O_EXCL
|
||||
#else
|
||||
# define UV_FS_O_EXCL 0
|
||||
#endif
|
||||
#if defined(O_EXLOCK)
|
||||
# define UV_FS_O_EXLOCK O_EXLOCK
|
||||
#else
|
||||
# define UV_FS_O_EXLOCK 0
|
||||
#endif
|
||||
#if defined(O_NOATIME)
|
||||
# define UV_FS_O_NOATIME O_NOATIME
|
||||
#else
|
||||
# define UV_FS_O_NOATIME 0
|
||||
#endif
|
||||
#if defined(O_NOCTTY)
|
||||
# define UV_FS_O_NOCTTY O_NOCTTY
|
||||
#else
|
||||
# define UV_FS_O_NOCTTY 0
|
||||
#endif
|
||||
#if defined(O_NOFOLLOW)
|
||||
# define UV_FS_O_NOFOLLOW O_NOFOLLOW
|
||||
#else
|
||||
# define UV_FS_O_NOFOLLOW 0
|
||||
#endif
|
||||
#if defined(O_NONBLOCK)
|
||||
# define UV_FS_O_NONBLOCK O_NONBLOCK
|
||||
#else
|
||||
# define UV_FS_O_NONBLOCK 0
|
||||
#endif
|
||||
#if defined(O_RDONLY)
|
||||
# define UV_FS_O_RDONLY O_RDONLY
|
||||
#else
|
||||
# define UV_FS_O_RDONLY 0
|
||||
#endif
|
||||
#if defined(O_RDWR)
|
||||
# define UV_FS_O_RDWR O_RDWR
|
||||
#else
|
||||
# define UV_FS_O_RDWR 0
|
||||
#endif
|
||||
#if defined(O_SYMLINK)
|
||||
# define UV_FS_O_SYMLINK O_SYMLINK
|
||||
#else
|
||||
# define UV_FS_O_SYMLINK 0
|
||||
#endif
|
||||
#if defined(O_SYNC)
|
||||
# define UV_FS_O_SYNC O_SYNC
|
||||
#else
|
||||
# define UV_FS_O_SYNC 0
|
||||
#endif
|
||||
#if defined(O_TRUNC)
|
||||
# define UV_FS_O_TRUNC O_TRUNC
|
||||
#else
|
||||
# define UV_FS_O_TRUNC 0
|
||||
#endif
|
||||
#if defined(O_WRONLY)
|
||||
# define UV_FS_O_WRONLY O_WRONLY
|
||||
#else
|
||||
# define UV_FS_O_WRONLY 0
|
||||
#endif
|
||||
|
||||
/* fs open() flags supported on other platforms: */
|
||||
#define UV_FS_O_RANDOM 0
|
||||
#define UV_FS_O_SHORT_LIVED 0
|
||||
#define UV_FS_O_SEQUENTIAL 0
|
||||
#define UV_FS_O_TEMPORARY 0
|
||||
|
||||
#endif /* UV_UNIX_H */
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UV_VERSION_H
|
||||
#define UV_VERSION_H
|
||||
|
||||
/*
|
||||
* Versions with the same major number are ABI stable. API is allowed to
|
||||
* evolve between minor releases, but only in a backwards compatible way.
|
||||
* Make sure you update the -soname directives in configure.ac
|
||||
* and uv.gyp whenever you bump UV_VERSION_MAJOR or UV_VERSION_MINOR (but
|
||||
* not UV_VERSION_PATCH.)
|
||||
*/
|
||||
|
||||
#define UV_VERSION_MAJOR 1
|
||||
#define UV_VERSION_MINOR 23
|
||||
#define UV_VERSION_PATCH 1
|
||||
#define UV_VERSION_IS_RELEASE 0
|
||||
#define UV_VERSION_SUFFIX "dev"
|
||||
|
||||
#define UV_VERSION_HEX ((UV_VERSION_MAJOR << 16) | \
|
||||
(UV_VERSION_MINOR << 8) | \
|
||||
(UV_VERSION_PATCH))
|
||||
|
||||
#endif /* UV_VERSION_H */
|
||||
|
|
@ -0,0 +1,676 @@
|
|||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _WIN32_WINNT
|
||||
# define _WIN32_WINNT 0x0600
|
||||
#endif
|
||||
|
||||
#if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED) && !defined(__SSIZE_T)
|
||||
typedef intptr_t ssize_t;
|
||||
# define _SSIZE_T_
|
||||
# define _SSIZE_T_DEFINED
|
||||
#endif
|
||||
|
||||
#include <winsock2.h>
|
||||
|
||||
#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
|
||||
typedef struct pollfd {
|
||||
SOCKET fd;
|
||||
short events;
|
||||
short revents;
|
||||
} WSAPOLLFD, *PWSAPOLLFD, *LPWSAPOLLFD;
|
||||
#endif
|
||||
|
||||
#ifndef LOCALE_INVARIANT
|
||||
# define LOCALE_INVARIANT 0x007f
|
||||
#endif
|
||||
|
||||
#include <mswsock.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <process.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1600
|
||||
# include "uv/stdint-msvc2008.h"
|
||||
#else
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include "uv/tree.h"
|
||||
#include "uv/threadpool.h"
|
||||
|
||||
#define MAX_PIPENAME_LEN 256
|
||||
|
||||
#ifndef S_IFLNK
|
||||
# define S_IFLNK 0xA000
|
||||
#endif
|
||||
|
||||
/* Additional signals supported by uv_signal and or uv_kill. The CRT defines
|
||||
* the following signals already:
|
||||
*
|
||||
* #define SIGINT 2
|
||||
* #define SIGILL 4
|
||||
* #define SIGABRT_COMPAT 6
|
||||
* #define SIGFPE 8
|
||||
* #define SIGSEGV 11
|
||||
* #define SIGTERM 15
|
||||
* #define SIGBREAK 21
|
||||
* #define SIGABRT 22
|
||||
*
|
||||
* The additional signals have values that are common on other Unix
|
||||
* variants (Linux and Darwin)
|
||||
*/
|
||||
#define SIGHUP 1
|
||||
#define SIGKILL 9
|
||||
#define SIGWINCH 28
|
||||
|
||||
/* The CRT defines SIGABRT_COMPAT as 6, which equals SIGABRT on many unix-like
|
||||
* platforms. However MinGW doesn't define it, so we do. */
|
||||
#ifndef SIGABRT_COMPAT
|
||||
# define SIGABRT_COMPAT 6
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Guids and typedefs for winsock extension functions
|
||||
* Mingw32 doesn't have these :-(
|
||||
*/
|
||||
#ifndef WSAID_ACCEPTEX
|
||||
# define WSAID_ACCEPTEX \
|
||||
{0xb5367df1, 0xcbac, 0x11cf, \
|
||||
{0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}}
|
||||
|
||||
# define WSAID_CONNECTEX \
|
||||
{0x25a207b9, 0xddf3, 0x4660, \
|
||||
{0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e}}
|
||||
|
||||
# define WSAID_GETACCEPTEXSOCKADDRS \
|
||||
{0xb5367df2, 0xcbac, 0x11cf, \
|
||||
{0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}}
|
||||
|
||||
# define WSAID_DISCONNECTEX \
|
||||
{0x7fda2e11, 0x8630, 0x436f, \
|
||||
{0xa0, 0x31, 0xf5, 0x36, 0xa6, 0xee, 0xc1, 0x57}}
|
||||
|
||||
# define WSAID_TRANSMITFILE \
|
||||
{0xb5367df0, 0xcbac, 0x11cf, \
|
||||
{0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}}
|
||||
|
||||
typedef BOOL (PASCAL *LPFN_ACCEPTEX)
|
||||
(SOCKET sListenSocket,
|
||||
SOCKET sAcceptSocket,
|
||||
PVOID lpOutputBuffer,
|
||||
DWORD dwReceiveDataLength,
|
||||
DWORD dwLocalAddressLength,
|
||||
DWORD dwRemoteAddressLength,
|
||||
LPDWORD lpdwBytesReceived,
|
||||
LPOVERLAPPED lpOverlapped);
|
||||
|
||||
typedef BOOL (PASCAL *LPFN_CONNECTEX)
|
||||
(SOCKET s,
|
||||
const struct sockaddr* name,
|
||||
int namelen,
|
||||
PVOID lpSendBuffer,
|
||||
DWORD dwSendDataLength,
|
||||
LPDWORD lpdwBytesSent,
|
||||
LPOVERLAPPED lpOverlapped);
|
||||
|
||||
typedef void (PASCAL *LPFN_GETACCEPTEXSOCKADDRS)
|
||||
(PVOID lpOutputBuffer,
|
||||
DWORD dwReceiveDataLength,
|
||||
DWORD dwLocalAddressLength,
|
||||
DWORD dwRemoteAddressLength,
|
||||
LPSOCKADDR* LocalSockaddr,
|
||||
LPINT LocalSockaddrLength,
|
||||
LPSOCKADDR* RemoteSockaddr,
|
||||
LPINT RemoteSockaddrLength);
|
||||
|
||||
typedef BOOL (PASCAL *LPFN_DISCONNECTEX)
|
||||
(SOCKET hSocket,
|
||||
LPOVERLAPPED lpOverlapped,
|
||||
DWORD dwFlags,
|
||||
DWORD reserved);
|
||||
|
||||
typedef BOOL (PASCAL *LPFN_TRANSMITFILE)
|
||||
(SOCKET hSocket,
|
||||
HANDLE hFile,
|
||||
DWORD nNumberOfBytesToWrite,
|
||||
DWORD nNumberOfBytesPerSend,
|
||||
LPOVERLAPPED lpOverlapped,
|
||||
LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers,
|
||||
DWORD dwFlags);
|
||||
|
||||
typedef PVOID RTL_SRWLOCK;
|
||||
typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK;
|
||||
#endif
|
||||
|
||||
typedef int (WSAAPI* LPFN_WSARECV)
|
||||
(SOCKET socket,
|
||||
LPWSABUF buffers,
|
||||
DWORD buffer_count,
|
||||
LPDWORD bytes,
|
||||
LPDWORD flags,
|
||||
LPWSAOVERLAPPED overlapped,
|
||||
LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine);
|
||||
|
||||
typedef int (WSAAPI* LPFN_WSARECVFROM)
|
||||
(SOCKET socket,
|
||||
LPWSABUF buffers,
|
||||
DWORD buffer_count,
|
||||
LPDWORD bytes,
|
||||
LPDWORD flags,
|
||||
struct sockaddr* addr,
|
||||
LPINT addr_len,
|
||||
LPWSAOVERLAPPED overlapped,
|
||||
LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine);
|
||||
|
||||
#ifndef _NTDEF_
|
||||
typedef LONG NTSTATUS;
|
||||
typedef NTSTATUS *PNTSTATUS;
|
||||
#endif
|
||||
|
||||
#ifndef RTL_CONDITION_VARIABLE_INIT
|
||||
typedef PVOID CONDITION_VARIABLE, *PCONDITION_VARIABLE;
|
||||
#endif
|
||||
|
||||
typedef struct _AFD_POLL_HANDLE_INFO {
|
||||
HANDLE Handle;
|
||||
ULONG Events;
|
||||
NTSTATUS Status;
|
||||
} AFD_POLL_HANDLE_INFO, *PAFD_POLL_HANDLE_INFO;
|
||||
|
||||
typedef struct _AFD_POLL_INFO {
|
||||
LARGE_INTEGER Timeout;
|
||||
ULONG NumberOfHandles;
|
||||
ULONG Exclusive;
|
||||
AFD_POLL_HANDLE_INFO Handles[1];
|
||||
} AFD_POLL_INFO, *PAFD_POLL_INFO;
|
||||
|
||||
#define UV_MSAFD_PROVIDER_COUNT 3
|
||||
|
||||
|
||||
/**
|
||||
* It should be possible to cast uv_buf_t[] to WSABUF[]
|
||||
* see http://msdn.microsoft.com/en-us/library/ms741542(v=vs.85).aspx
|
||||
*/
|
||||
typedef struct uv_buf_t {
|
||||
ULONG len;
|
||||
char* base;
|
||||
} uv_buf_t;
|
||||
|
||||
typedef int uv_file;
|
||||
typedef SOCKET uv_os_sock_t;
|
||||
typedef HANDLE uv_os_fd_t;
|
||||
typedef int uv_pid_t;
|
||||
|
||||
typedef HANDLE uv_thread_t;
|
||||
|
||||
typedef HANDLE uv_sem_t;
|
||||
|
||||
typedef CRITICAL_SECTION uv_mutex_t;
|
||||
|
||||
/* This condition variable implementation is based on the SetEvent solution
|
||||
* (section 3.2) at http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
|
||||
* We could not use the SignalObjectAndWait solution (section 3.4) because
|
||||
* it want the 2nd argument (type uv_mutex_t) of uv_cond_wait() and
|
||||
* uv_cond_timedwait() to be HANDLEs, but we use CRITICAL_SECTIONs.
|
||||
*/
|
||||
|
||||
typedef union {
|
||||
CONDITION_VARIABLE cond_var;
|
||||
struct {
|
||||
unsigned int waiters_count;
|
||||
CRITICAL_SECTION waiters_count_lock;
|
||||
HANDLE signal_event;
|
||||
HANDLE broadcast_event;
|
||||
} unused_; /* TODO: retained for ABI compatibility; remove me in v2.x. */
|
||||
} uv_cond_t;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
unsigned int num_readers_;
|
||||
CRITICAL_SECTION num_readers_lock_;
|
||||
HANDLE write_semaphore_;
|
||||
} state_;
|
||||
/* TODO: remove me in v2.x. */
|
||||
struct {
|
||||
SRWLOCK unused_;
|
||||
} unused1_;
|
||||
/* TODO: remove me in v2.x. */
|
||||
struct {
|
||||
uv_mutex_t unused1_;
|
||||
uv_mutex_t unused2_;
|
||||
} unused2_;
|
||||
} uv_rwlock_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned int n;
|
||||
unsigned int count;
|
||||
uv_mutex_t mutex;
|
||||
uv_sem_t turnstile1;
|
||||
uv_sem_t turnstile2;
|
||||
} uv_barrier_t;
|
||||
|
||||
typedef struct {
|
||||
DWORD tls_index;
|
||||
} uv_key_t;
|
||||
|
||||
#define UV_ONCE_INIT { 0, NULL }
|
||||
|
||||
typedef struct uv_once_s {
|
||||
unsigned char ran;
|
||||
HANDLE event;
|
||||
} uv_once_t;
|
||||
|
||||
/* Platform-specific definitions for uv_spawn support. */
|
||||
typedef unsigned char uv_uid_t;
|
||||
typedef unsigned char uv_gid_t;
|
||||
|
||||
typedef struct uv__dirent_s {
|
||||
int d_type;
|
||||
char d_name[1];
|
||||
} uv__dirent_t;
|
||||
|
||||
#define HAVE_DIRENT_TYPES
|
||||
#define UV__DT_DIR UV_DIRENT_DIR
|
||||
#define UV__DT_FILE UV_DIRENT_FILE
|
||||
#define UV__DT_LINK UV_DIRENT_LINK
|
||||
#define UV__DT_FIFO UV_DIRENT_FIFO
|
||||
#define UV__DT_SOCKET UV_DIRENT_SOCKET
|
||||
#define UV__DT_CHAR UV_DIRENT_CHAR
|
||||
#define UV__DT_BLOCK UV_DIRENT_BLOCK
|
||||
|
||||
/* Platform-specific definitions for uv_dlopen support. */
|
||||
#define UV_DYNAMIC FAR WINAPI
|
||||
typedef struct {
|
||||
HMODULE handle;
|
||||
char* errmsg;
|
||||
} uv_lib_t;
|
||||
|
||||
#define UV_LOOP_PRIVATE_FIELDS \
|
||||
/* The loop's I/O completion port */ \
|
||||
HANDLE iocp; \
|
||||
/* The current time according to the event loop. in msecs. */ \
|
||||
uint64_t time; \
|
||||
/* Tail of a single-linked circular queue of pending reqs. If the queue */ \
|
||||
/* is empty, tail_ is NULL. If there is only one item, */ \
|
||||
/* tail_->next_req == tail_ */ \
|
||||
uv_req_t* pending_reqs_tail; \
|
||||
/* Head of a single-linked list of closed handles */ \
|
||||
uv_handle_t* endgame_handles; \
|
||||
/* TODO(bnoordhuis) Stop heap-allocating |timer_heap| in libuv v2.x. */ \
|
||||
void* timer_heap; \
|
||||
/* Lists of active loop (prepare / check / idle) watchers */ \
|
||||
uv_prepare_t* prepare_handles; \
|
||||
uv_check_t* check_handles; \
|
||||
uv_idle_t* idle_handles; \
|
||||
/* This pointer will refer to the prepare/check/idle handle whose */ \
|
||||
/* callback is scheduled to be called next. This is needed to allow */ \
|
||||
/* safe removal from one of the lists above while that list being */ \
|
||||
/* iterated over. */ \
|
||||
uv_prepare_t* next_prepare_handle; \
|
||||
uv_check_t* next_check_handle; \
|
||||
uv_idle_t* next_idle_handle; \
|
||||
/* This handle holds the peer sockets for the fast variant of uv_poll_t */ \
|
||||
SOCKET poll_peer_sockets[UV_MSAFD_PROVIDER_COUNT]; \
|
||||
/* Counter to keep track of active tcp streams */ \
|
||||
unsigned int active_tcp_streams; \
|
||||
/* Counter to keep track of active udp streams */ \
|
||||
unsigned int active_udp_streams; \
|
||||
/* Counter to started timer */ \
|
||||
uint64_t timer_counter; \
|
||||
/* Threadpool */ \
|
||||
void* wq[2]; \
|
||||
uv_mutex_t wq_mutex; \
|
||||
uv_async_t wq_async;
|
||||
|
||||
#define UV_REQ_TYPE_PRIVATE \
|
||||
/* TODO: remove the req suffix */ \
|
||||
UV_ACCEPT, \
|
||||
UV_FS_EVENT_REQ, \
|
||||
UV_POLL_REQ, \
|
||||
UV_PROCESS_EXIT, \
|
||||
UV_READ, \
|
||||
UV_UDP_RECV, \
|
||||
UV_WAKEUP, \
|
||||
UV_SIGNAL_REQ,
|
||||
|
||||
#define UV_REQ_PRIVATE_FIELDS \
|
||||
union { \
|
||||
/* Used by I/O operations */ \
|
||||
struct { \
|
||||
OVERLAPPED overlapped; \
|
||||
size_t queued_bytes; \
|
||||
} io; \
|
||||
} u; \
|
||||
struct uv_req_s* next_req;
|
||||
|
||||
#define UV_WRITE_PRIVATE_FIELDS \
|
||||
int coalesced; \
|
||||
uv_buf_t write_buffer; \
|
||||
HANDLE event_handle; \
|
||||
HANDLE wait_handle;
|
||||
|
||||
#define UV_CONNECT_PRIVATE_FIELDS \
|
||||
/* empty */
|
||||
|
||||
#define UV_SHUTDOWN_PRIVATE_FIELDS \
|
||||
/* empty */
|
||||
|
||||
#define UV_UDP_SEND_PRIVATE_FIELDS \
|
||||
/* empty */
|
||||
|
||||
#define UV_PRIVATE_REQ_TYPES \
|
||||
typedef struct uv_pipe_accept_s { \
|
||||
UV_REQ_FIELDS \
|
||||
HANDLE pipeHandle; \
|
||||
struct uv_pipe_accept_s* next_pending; \
|
||||
} uv_pipe_accept_t; \
|
||||
\
|
||||
typedef struct uv_tcp_accept_s { \
|
||||
UV_REQ_FIELDS \
|
||||
SOCKET accept_socket; \
|
||||
char accept_buffer[sizeof(struct sockaddr_storage) * 2 + 32]; \
|
||||
HANDLE event_handle; \
|
||||
HANDLE wait_handle; \
|
||||
struct uv_tcp_accept_s* next_pending; \
|
||||
} uv_tcp_accept_t; \
|
||||
\
|
||||
typedef struct uv_read_s { \
|
||||
UV_REQ_FIELDS \
|
||||
HANDLE event_handle; \
|
||||
HANDLE wait_handle; \
|
||||
} uv_read_t;
|
||||
|
||||
#define uv_stream_connection_fields \
|
||||
unsigned int write_reqs_pending; \
|
||||
uv_shutdown_t* shutdown_req;
|
||||
|
||||
#define uv_stream_server_fields \
|
||||
uv_connection_cb connection_cb;
|
||||
|
||||
#define UV_STREAM_PRIVATE_FIELDS \
|
||||
unsigned int reqs_pending; \
|
||||
int activecnt; \
|
||||
uv_read_t read_req; \
|
||||
union { \
|
||||
struct { uv_stream_connection_fields } conn; \
|
||||
struct { uv_stream_server_fields } serv; \
|
||||
} stream;
|
||||
|
||||
#define uv_tcp_server_fields \
|
||||
uv_tcp_accept_t* accept_reqs; \
|
||||
unsigned int processed_accepts; \
|
||||
uv_tcp_accept_t* pending_accepts; \
|
||||
LPFN_ACCEPTEX func_acceptex;
|
||||
|
||||
#define uv_tcp_connection_fields \
|
||||
uv_buf_t read_buffer; \
|
||||
LPFN_CONNECTEX func_connectex;
|
||||
|
||||
#define UV_TCP_PRIVATE_FIELDS \
|
||||
SOCKET socket; \
|
||||
int delayed_error; \
|
||||
union { \
|
||||
struct { uv_tcp_server_fields } serv; \
|
||||
struct { uv_tcp_connection_fields } conn; \
|
||||
} tcp;
|
||||
|
||||
#define UV_UDP_PRIVATE_FIELDS \
|
||||
SOCKET socket; \
|
||||
unsigned int reqs_pending; \
|
||||
int activecnt; \
|
||||
uv_req_t recv_req; \
|
||||
uv_buf_t recv_buffer; \
|
||||
struct sockaddr_storage recv_from; \
|
||||
int recv_from_len; \
|
||||
uv_udp_recv_cb recv_cb; \
|
||||
uv_alloc_cb alloc_cb; \
|
||||
LPFN_WSARECV func_wsarecv; \
|
||||
LPFN_WSARECVFROM func_wsarecvfrom;
|
||||
|
||||
#define uv_pipe_server_fields \
|
||||
int pending_instances; \
|
||||
uv_pipe_accept_t* accept_reqs; \
|
||||
uv_pipe_accept_t* pending_accepts;
|
||||
|
||||
#define uv_pipe_connection_fields \
|
||||
uv_timer_t* eof_timer; \
|
||||
uv_write_t dummy; /* TODO: retained for ABI compat; remove this in v2.x. */ \
|
||||
DWORD ipc_remote_pid; \
|
||||
union { \
|
||||
uint32_t payload_remaining; \
|
||||
uint64_t dummy; /* TODO: retained for ABI compat; remove this in v2.x. */ \
|
||||
} ipc_data_frame; \
|
||||
void* ipc_xfer_queue[2]; \
|
||||
int ipc_xfer_queue_length; \
|
||||
uv_write_t* non_overlapped_writes_tail; \
|
||||
CRITICAL_SECTION readfile_thread_lock; \
|
||||
volatile HANDLE readfile_thread_handle;
|
||||
|
||||
#define UV_PIPE_PRIVATE_FIELDS \
|
||||
HANDLE handle; \
|
||||
WCHAR* name; \
|
||||
union { \
|
||||
struct { uv_pipe_server_fields } serv; \
|
||||
struct { uv_pipe_connection_fields } conn; \
|
||||
} pipe;
|
||||
|
||||
/* TODO: put the parser states in an union - TTY handles are always half-duplex
|
||||
* so read-state can safely overlap write-state. */
|
||||
#define UV_TTY_PRIVATE_FIELDS \
|
||||
HANDLE handle; \
|
||||
union { \
|
||||
struct { \
|
||||
/* Used for readable TTY handles */ \
|
||||
/* TODO: remove me in v2.x. */ \
|
||||
HANDLE unused_; \
|
||||
uv_buf_t read_line_buffer; \
|
||||
HANDLE read_raw_wait; \
|
||||
/* Fields used for translating win keystrokes into vt100 characters */ \
|
||||
char last_key[8]; \
|
||||
unsigned char last_key_offset; \
|
||||
unsigned char last_key_len; \
|
||||
WCHAR last_utf16_high_surrogate; \
|
||||
INPUT_RECORD last_input_record; \
|
||||
} rd; \
|
||||
struct { \
|
||||
/* Used for writable TTY handles */ \
|
||||
/* utf8-to-utf16 conversion state */ \
|
||||
unsigned int utf8_codepoint; \
|
||||
unsigned char utf8_bytes_left; \
|
||||
/* eol conversion state */ \
|
||||
unsigned char previous_eol; \
|
||||
/* ansi parser state */ \
|
||||
unsigned char ansi_parser_state; \
|
||||
unsigned char ansi_csi_argc; \
|
||||
unsigned short ansi_csi_argv[4]; \
|
||||
COORD saved_position; \
|
||||
WORD saved_attributes; \
|
||||
} wr; \
|
||||
} tty;
|
||||
|
||||
#define UV_POLL_PRIVATE_FIELDS \
|
||||
SOCKET socket; \
|
||||
/* Used in fast mode */ \
|
||||
SOCKET peer_socket; \
|
||||
AFD_POLL_INFO afd_poll_info_1; \
|
||||
AFD_POLL_INFO afd_poll_info_2; \
|
||||
/* Used in fast and slow mode. */ \
|
||||
uv_req_t poll_req_1; \
|
||||
uv_req_t poll_req_2; \
|
||||
unsigned char submitted_events_1; \
|
||||
unsigned char submitted_events_2; \
|
||||
unsigned char mask_events_1; \
|
||||
unsigned char mask_events_2; \
|
||||
unsigned char events;
|
||||
|
||||
#define UV_TIMER_PRIVATE_FIELDS \
|
||||
void* heap_node[3]; \
|
||||
int unused; \
|
||||
uint64_t timeout; \
|
||||
uint64_t repeat; \
|
||||
uint64_t start_id; \
|
||||
uv_timer_cb timer_cb;
|
||||
|
||||
#define UV_ASYNC_PRIVATE_FIELDS \
|
||||
struct uv_req_s async_req; \
|
||||
uv_async_cb async_cb; \
|
||||
/* char to avoid alignment issues */ \
|
||||
char volatile async_sent;
|
||||
|
||||
#define UV_PREPARE_PRIVATE_FIELDS \
|
||||
uv_prepare_t* prepare_prev; \
|
||||
uv_prepare_t* prepare_next; \
|
||||
uv_prepare_cb prepare_cb;
|
||||
|
||||
#define UV_CHECK_PRIVATE_FIELDS \
|
||||
uv_check_t* check_prev; \
|
||||
uv_check_t* check_next; \
|
||||
uv_check_cb check_cb;
|
||||
|
||||
#define UV_IDLE_PRIVATE_FIELDS \
|
||||
uv_idle_t* idle_prev; \
|
||||
uv_idle_t* idle_next; \
|
||||
uv_idle_cb idle_cb;
|
||||
|
||||
#define UV_HANDLE_PRIVATE_FIELDS \
|
||||
uv_handle_t* endgame_next; \
|
||||
unsigned int flags;
|
||||
|
||||
#define UV_GETADDRINFO_PRIVATE_FIELDS \
|
||||
struct uv__work work_req; \
|
||||
uv_getaddrinfo_cb getaddrinfo_cb; \
|
||||
void* alloc; \
|
||||
WCHAR* node; \
|
||||
WCHAR* service; \
|
||||
/* The addrinfoW field is used to store a pointer to the hints, and */ \
|
||||
/* later on to store the result of GetAddrInfoW. The final result will */ \
|
||||
/* be converted to struct addrinfo* and stored in the addrinfo field. */ \
|
||||
struct addrinfoW* addrinfow; \
|
||||
struct addrinfo* addrinfo; \
|
||||
int retcode;
|
||||
|
||||
#define UV_GETNAMEINFO_PRIVATE_FIELDS \
|
||||
struct uv__work work_req; \
|
||||
uv_getnameinfo_cb getnameinfo_cb; \
|
||||
struct sockaddr_storage storage; \
|
||||
int flags; \
|
||||
char host[NI_MAXHOST]; \
|
||||
char service[NI_MAXSERV]; \
|
||||
int retcode;
|
||||
|
||||
#define UV_PROCESS_PRIVATE_FIELDS \
|
||||
struct uv_process_exit_s { \
|
||||
UV_REQ_FIELDS \
|
||||
} exit_req; \
|
||||
BYTE* child_stdio_buffer; \
|
||||
int exit_signal; \
|
||||
HANDLE wait_handle; \
|
||||
HANDLE process_handle; \
|
||||
volatile char exit_cb_pending;
|
||||
|
||||
#define UV_FS_PRIVATE_FIELDS \
|
||||
struct uv__work work_req; \
|
||||
int flags; \
|
||||
DWORD sys_errno_; \
|
||||
union { \
|
||||
/* TODO: remove me in 0.9. */ \
|
||||
WCHAR* pathw; \
|
||||
int fd; \
|
||||
} file; \
|
||||
union { \
|
||||
struct { \
|
||||
int mode; \
|
||||
WCHAR* new_pathw; \
|
||||
int file_flags; \
|
||||
int fd_out; \
|
||||
unsigned int nbufs; \
|
||||
uv_buf_t* bufs; \
|
||||
int64_t offset; \
|
||||
uv_buf_t bufsml[4]; \
|
||||
} info; \
|
||||
struct { \
|
||||
double atime; \
|
||||
double mtime; \
|
||||
} time; \
|
||||
} fs;
|
||||
|
||||
#define UV_WORK_PRIVATE_FIELDS \
|
||||
struct uv__work work_req;
|
||||
|
||||
#define UV_FS_EVENT_PRIVATE_FIELDS \
|
||||
struct uv_fs_event_req_s { \
|
||||
UV_REQ_FIELDS \
|
||||
} req; \
|
||||
HANDLE dir_handle; \
|
||||
int req_pending; \
|
||||
uv_fs_event_cb cb; \
|
||||
WCHAR* filew; \
|
||||
WCHAR* short_filew; \
|
||||
WCHAR* dirw; \
|
||||
char* buffer;
|
||||
|
||||
#define UV_SIGNAL_PRIVATE_FIELDS \
|
||||
RB_ENTRY(uv_signal_s) tree_entry; \
|
||||
struct uv_req_s signal_req; \
|
||||
unsigned long pending_signum;
|
||||
|
||||
#ifndef F_OK
|
||||
#define F_OK 0
|
||||
#endif
|
||||
#ifndef R_OK
|
||||
#define R_OK 4
|
||||
#endif
|
||||
#ifndef W_OK
|
||||
#define W_OK 2
|
||||
#endif
|
||||
#ifndef X_OK
|
||||
#define X_OK 1
|
||||
#endif
|
||||
|
||||
/* fs open() flags supported on this platform: */
|
||||
#define UV_FS_O_APPEND _O_APPEND
|
||||
#define UV_FS_O_CREAT _O_CREAT
|
||||
#define UV_FS_O_EXCL _O_EXCL
|
||||
#define UV_FS_O_RANDOM _O_RANDOM
|
||||
#define UV_FS_O_RDONLY _O_RDONLY
|
||||
#define UV_FS_O_RDWR _O_RDWR
|
||||
#define UV_FS_O_SEQUENTIAL _O_SEQUENTIAL
|
||||
#define UV_FS_O_SHORT_LIVED _O_SHORT_LIVED
|
||||
#define UV_FS_O_TEMPORARY _O_TEMPORARY
|
||||
#define UV_FS_O_TRUNC _O_TRUNC
|
||||
#define UV_FS_O_WRONLY _O_WRONLY
|
||||
|
||||
/* fs open() flags supported on other platforms (or mapped on this platform): */
|
||||
#define UV_FS_O_DIRECT 0x02000000 /* FILE_FLAG_NO_BUFFERING */
|
||||
#define UV_FS_O_DIRECTORY 0
|
||||
#define UV_FS_O_DSYNC 0x04000000 /* FILE_FLAG_WRITE_THROUGH */
|
||||
#define UV_FS_O_EXLOCK 0x10000000 /* EXCLUSIVE SHARING MODE */
|
||||
#define UV_FS_O_NOATIME 0
|
||||
#define UV_FS_O_NOCTTY 0
|
||||
#define UV_FS_O_NOFOLLOW 0
|
||||
#define UV_FS_O_NONBLOCK 0
|
||||
#define UV_FS_O_SYMLINK 0
|
||||
#define UV_FS_O_SYNC 0x08000000 /* FILE_FLAG_WRITE_THROUGH */
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_LIBPLATFORM_LIBPLATFORM_EXPORT_H_
|
||||
#define V8_LIBPLATFORM_LIBPLATFORM_EXPORT_H_
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#ifdef BUILDING_V8_PLATFORM_SHARED
|
||||
#define V8_PLATFORM_EXPORT __declspec(dllexport)
|
||||
#elif USING_V8_PLATFORM_SHARED
|
||||
#define V8_PLATFORM_EXPORT __declspec(dllimport)
|
||||
#else
|
||||
#define V8_PLATFORM_EXPORT
|
||||
#endif // BUILDING_V8_PLATFORM_SHARED
|
||||
|
||||
#else // defined(_WIN32)
|
||||
|
||||
// Setup for Linux shared library export.
|
||||
#ifdef BUILDING_V8_PLATFORM_SHARED
|
||||
#define V8_PLATFORM_EXPORT __attribute__((visibility("default")))
|
||||
#else
|
||||
#define V8_PLATFORM_EXPORT
|
||||
#endif
|
||||
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
#endif // V8_LIBPLATFORM_LIBPLATFORM_EXPORT_H_
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_LIBPLATFORM_LIBPLATFORM_H_
|
||||
#define V8_LIBPLATFORM_LIBPLATFORM_H_
|
||||
|
||||
#include "libplatform/libplatform-export.h"
|
||||
#include "libplatform/v8-tracing.h"
|
||||
#include "v8-platform.h" // NOLINT(build/include)
|
||||
|
||||
namespace v8 {
|
||||
namespace platform {
|
||||
|
||||
enum class IdleTaskSupport { kDisabled, kEnabled };
|
||||
enum class InProcessStackDumping { kDisabled, kEnabled };
|
||||
|
||||
enum class MessageLoopBehavior : bool {
|
||||
kDoNotWait = false,
|
||||
kWaitForWork = true
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a new instance of the default v8::Platform implementation.
|
||||
*
|
||||
* The caller will take ownership of the returned pointer. |thread_pool_size|
|
||||
* is the number of worker threads to allocate for background jobs. If a value
|
||||
* of zero is passed, a suitable default based on the current number of
|
||||
* processors online will be chosen.
|
||||
* If |idle_task_support| is enabled then the platform will accept idle
|
||||
* tasks (IdleTasksEnabled will return true) and will rely on the embedder
|
||||
* calling v8::platform::RunIdleTasks to process the idle tasks.
|
||||
*/
|
||||
V8_PLATFORM_EXPORT v8::Platform* CreateDefaultPlatform(
|
||||
int thread_pool_size = 0,
|
||||
IdleTaskSupport idle_task_support = IdleTaskSupport::kDisabled,
|
||||
InProcessStackDumping in_process_stack_dumping =
|
||||
InProcessStackDumping::kEnabled);
|
||||
|
||||
/**
|
||||
* Pumps the message loop for the given isolate.
|
||||
*
|
||||
* The caller has to make sure that this is called from the right thread.
|
||||
* Returns true if a task was executed, and false otherwise. Unless requested
|
||||
* through the |behavior| parameter, this call does not block if no task is
|
||||
* pending. The |platform| has to be created using |CreateDefaultPlatform|.
|
||||
*/
|
||||
V8_PLATFORM_EXPORT bool PumpMessageLoop(
|
||||
v8::Platform* platform, v8::Isolate* isolate,
|
||||
MessageLoopBehavior behavior = MessageLoopBehavior::kDoNotWait);
|
||||
|
||||
V8_PLATFORM_EXPORT void EnsureEventLoopInitialized(v8::Platform* platform,
|
||||
v8::Isolate* isolate);
|
||||
|
||||
/**
|
||||
* Runs pending idle tasks for at most |idle_time_in_seconds| seconds.
|
||||
*
|
||||
* The caller has to make sure that this is called from the right thread.
|
||||
* This call does not block if no task is pending. The |platform| has to be
|
||||
* created using |CreateDefaultPlatform|.
|
||||
*/
|
||||
V8_PLATFORM_EXPORT void RunIdleTasks(v8::Platform* platform,
|
||||
v8::Isolate* isolate,
|
||||
double idle_time_in_seconds);
|
||||
|
||||
/**
|
||||
* Attempts to set the tracing controller for the given platform.
|
||||
*
|
||||
* The |platform| has to be created using |CreateDefaultPlatform|.
|
||||
*/
|
||||
V8_PLATFORM_EXPORT void SetTracingController(
|
||||
v8::Platform* platform,
|
||||
v8::platform::tracing::TracingController* tracing_controller);
|
||||
|
||||
} // namespace platform
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_LIBPLATFORM_LIBPLATFORM_H_
|
||||
|
|
@ -0,0 +1,270 @@
|
|||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_LIBPLATFORM_V8_TRACING_H_
|
||||
#define V8_LIBPLATFORM_V8_TRACING_H_
|
||||
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "libplatform/libplatform-export.h"
|
||||
#include "v8-platform.h" // NOLINT(build/include)
|
||||
|
||||
namespace v8 {
|
||||
|
||||
namespace base {
|
||||
class Mutex;
|
||||
} // namespace base
|
||||
|
||||
namespace platform {
|
||||
namespace tracing {
|
||||
|
||||
const int kTraceMaxNumArgs = 2;
|
||||
|
||||
class V8_PLATFORM_EXPORT TraceObject {
|
||||
public:
|
||||
union ArgValue {
|
||||
bool as_bool;
|
||||
uint64_t as_uint;
|
||||
int64_t as_int;
|
||||
double as_double;
|
||||
const void* as_pointer;
|
||||
const char* as_string;
|
||||
};
|
||||
|
||||
TraceObject() {}
|
||||
~TraceObject();
|
||||
void Initialize(
|
||||
char phase, const uint8_t* category_enabled_flag, const char* name,
|
||||
const char* scope, uint64_t id, uint64_t bind_id, int num_args,
|
||||
const char** arg_names, const uint8_t* arg_types,
|
||||
const uint64_t* arg_values,
|
||||
std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables,
|
||||
unsigned int flags);
|
||||
void UpdateDuration();
|
||||
void InitializeForTesting(
|
||||
char phase, const uint8_t* category_enabled_flag, const char* name,
|
||||
const char* scope, uint64_t id, uint64_t bind_id, int num_args,
|
||||
const char** arg_names, const uint8_t* arg_types,
|
||||
const uint64_t* arg_values,
|
||||
std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables,
|
||||
unsigned int flags, int pid, int tid, int64_t ts, int64_t tts,
|
||||
uint64_t duration, uint64_t cpu_duration);
|
||||
|
||||
int pid() const { return pid_; }
|
||||
int tid() const { return tid_; }
|
||||
char phase() const { return phase_; }
|
||||
const uint8_t* category_enabled_flag() const {
|
||||
return category_enabled_flag_;
|
||||
}
|
||||
const char* name() const { return name_; }
|
||||
const char* scope() const { return scope_; }
|
||||
uint64_t id() const { return id_; }
|
||||
uint64_t bind_id() const { return bind_id_; }
|
||||
int num_args() const { return num_args_; }
|
||||
const char** arg_names() { return arg_names_; }
|
||||
uint8_t* arg_types() { return arg_types_; }
|
||||
ArgValue* arg_values() { return arg_values_; }
|
||||
std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables() {
|
||||
return arg_convertables_;
|
||||
}
|
||||
unsigned int flags() const { return flags_; }
|
||||
int64_t ts() { return ts_; }
|
||||
int64_t tts() { return tts_; }
|
||||
uint64_t duration() { return duration_; }
|
||||
uint64_t cpu_duration() { return cpu_duration_; }
|
||||
|
||||
private:
|
||||
int pid_;
|
||||
int tid_;
|
||||
char phase_;
|
||||
const char* name_;
|
||||
const char* scope_;
|
||||
const uint8_t* category_enabled_flag_;
|
||||
uint64_t id_;
|
||||
uint64_t bind_id_;
|
||||
int num_args_ = 0;
|
||||
const char* arg_names_[kTraceMaxNumArgs];
|
||||
uint8_t arg_types_[kTraceMaxNumArgs];
|
||||
ArgValue arg_values_[kTraceMaxNumArgs];
|
||||
std::unique_ptr<v8::ConvertableToTraceFormat>
|
||||
arg_convertables_[kTraceMaxNumArgs];
|
||||
char* parameter_copy_storage_ = nullptr;
|
||||
unsigned int flags_;
|
||||
int64_t ts_;
|
||||
int64_t tts_;
|
||||
uint64_t duration_;
|
||||
uint64_t cpu_duration_;
|
||||
|
||||
// Disallow copy and assign
|
||||
TraceObject(const TraceObject&) = delete;
|
||||
void operator=(const TraceObject&) = delete;
|
||||
};
|
||||
|
||||
class V8_PLATFORM_EXPORT TraceWriter {
|
||||
public:
|
||||
TraceWriter() {}
|
||||
virtual ~TraceWriter() {}
|
||||
virtual void AppendTraceEvent(TraceObject* trace_event) = 0;
|
||||
virtual void Flush() = 0;
|
||||
|
||||
static TraceWriter* CreateJSONTraceWriter(std::ostream& stream);
|
||||
|
||||
private:
|
||||
// Disallow copy and assign
|
||||
TraceWriter(const TraceWriter&) = delete;
|
||||
void operator=(const TraceWriter&) = delete;
|
||||
};
|
||||
|
||||
class V8_PLATFORM_EXPORT TraceBufferChunk {
|
||||
public:
|
||||
explicit TraceBufferChunk(uint32_t seq);
|
||||
|
||||
void Reset(uint32_t new_seq);
|
||||
bool IsFull() const { return next_free_ == kChunkSize; }
|
||||
TraceObject* AddTraceEvent(size_t* event_index);
|
||||
TraceObject* GetEventAt(size_t index) { return &chunk_[index]; }
|
||||
|
||||
uint32_t seq() const { return seq_; }
|
||||
size_t size() const { return next_free_; }
|
||||
|
||||
static const size_t kChunkSize = 64;
|
||||
|
||||
private:
|
||||
size_t next_free_ = 0;
|
||||
TraceObject chunk_[kChunkSize];
|
||||
uint32_t seq_;
|
||||
|
||||
// Disallow copy and assign
|
||||
TraceBufferChunk(const TraceBufferChunk&) = delete;
|
||||
void operator=(const TraceBufferChunk&) = delete;
|
||||
};
|
||||
|
||||
class V8_PLATFORM_EXPORT TraceBuffer {
|
||||
public:
|
||||
TraceBuffer() {}
|
||||
virtual ~TraceBuffer() {}
|
||||
|
||||
virtual TraceObject* AddTraceEvent(uint64_t* handle) = 0;
|
||||
virtual TraceObject* GetEventByHandle(uint64_t handle) = 0;
|
||||
virtual bool Flush() = 0;
|
||||
|
||||
static const size_t kRingBufferChunks = 1024;
|
||||
|
||||
static TraceBuffer* CreateTraceBufferRingBuffer(size_t max_chunks,
|
||||
TraceWriter* trace_writer);
|
||||
|
||||
private:
|
||||
// Disallow copy and assign
|
||||
TraceBuffer(const TraceBuffer&) = delete;
|
||||
void operator=(const TraceBuffer&) = delete;
|
||||
};
|
||||
|
||||
// Options determines how the trace buffer stores data.
|
||||
enum TraceRecordMode {
|
||||
// Record until the trace buffer is full.
|
||||
RECORD_UNTIL_FULL,
|
||||
|
||||
// Record until the user ends the trace. The trace buffer is a fixed size
|
||||
// and we use it as a ring buffer during recording.
|
||||
RECORD_CONTINUOUSLY,
|
||||
|
||||
// Record until the trace buffer is full, but with a huge buffer size.
|
||||
RECORD_AS_MUCH_AS_POSSIBLE,
|
||||
|
||||
// Echo to console. Events are discarded.
|
||||
ECHO_TO_CONSOLE,
|
||||
};
|
||||
|
||||
class V8_PLATFORM_EXPORT TraceConfig {
|
||||
public:
|
||||
typedef std::vector<std::string> StringList;
|
||||
|
||||
static TraceConfig* CreateDefaultTraceConfig();
|
||||
|
||||
TraceConfig() : enable_systrace_(false), enable_argument_filter_(false) {}
|
||||
TraceRecordMode GetTraceRecordMode() const { return record_mode_; }
|
||||
bool IsSystraceEnabled() const { return enable_systrace_; }
|
||||
bool IsArgumentFilterEnabled() const { return enable_argument_filter_; }
|
||||
|
||||
void SetTraceRecordMode(TraceRecordMode mode) { record_mode_ = mode; }
|
||||
void EnableSystrace() { enable_systrace_ = true; }
|
||||
void EnableArgumentFilter() { enable_argument_filter_ = true; }
|
||||
|
||||
void AddIncludedCategory(const char* included_category);
|
||||
|
||||
bool IsCategoryGroupEnabled(const char* category_group) const;
|
||||
|
||||
private:
|
||||
TraceRecordMode record_mode_;
|
||||
bool enable_systrace_ : 1;
|
||||
bool enable_argument_filter_ : 1;
|
||||
StringList included_categories_;
|
||||
|
||||
// Disallow copy and assign
|
||||
TraceConfig(const TraceConfig&) = delete;
|
||||
void operator=(const TraceConfig&) = delete;
|
||||
};
|
||||
|
||||
class V8_PLATFORM_EXPORT TracingController {
|
||||
public:
|
||||
enum Mode { DISABLED = 0, RECORDING_MODE };
|
||||
|
||||
// The pointer returned from GetCategoryGroupEnabledInternal() points to a
|
||||
// value with zero or more of the following bits. Used in this class only.
|
||||
// The TRACE_EVENT macros should only use the value as a bool.
|
||||
// These values must be in sync with macro values in TraceEvent.h in Blink.
|
||||
enum CategoryGroupEnabledFlags {
|
||||
// Category group enabled for the recording mode.
|
||||
ENABLED_FOR_RECORDING = 1 << 0,
|
||||
// Category group enabled by SetEventCallbackEnabled().
|
||||
ENABLED_FOR_EVENT_CALLBACK = 1 << 2,
|
||||
// Category group enabled to export events to ETW.
|
||||
ENABLED_FOR_ETW_EXPORT = 1 << 3
|
||||
};
|
||||
|
||||
TracingController();
|
||||
~TracingController();
|
||||
void Initialize(TraceBuffer* trace_buffer);
|
||||
const uint8_t* GetCategoryGroupEnabled(const char* category_group);
|
||||
static const char* GetCategoryGroupName(const uint8_t* category_enabled_flag);
|
||||
uint64_t AddTraceEvent(
|
||||
char phase, const uint8_t* category_enabled_flag, const char* name,
|
||||
const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args,
|
||||
const char** arg_names, const uint8_t* arg_types,
|
||||
const uint64_t* arg_values,
|
||||
std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables,
|
||||
unsigned int flags);
|
||||
void UpdateTraceEventDuration(const uint8_t* category_enabled_flag,
|
||||
const char* name, uint64_t handle);
|
||||
|
||||
void StartTracing(TraceConfig* trace_config);
|
||||
void StopTracing();
|
||||
|
||||
void AddTraceStateObserver(Platform::TraceStateObserver* observer);
|
||||
void RemoveTraceStateObserver(Platform::TraceStateObserver* observer);
|
||||
|
||||
private:
|
||||
const uint8_t* GetCategoryGroupEnabledInternal(const char* category_group);
|
||||
void UpdateCategoryGroupEnabledFlag(size_t category_index);
|
||||
void UpdateCategoryGroupEnabledFlags();
|
||||
|
||||
std::unique_ptr<TraceBuffer> trace_buffer_;
|
||||
std::unique_ptr<TraceConfig> trace_config_;
|
||||
std::unique_ptr<base::Mutex> mutex_;
|
||||
std::unordered_set<Platform::TraceStateObserver*> observers_;
|
||||
Mode mode_ = DISABLED;
|
||||
|
||||
// Disallow copy and assign
|
||||
TracingController(const TracingController&) = delete;
|
||||
void operator=(const TracingController&) = delete;
|
||||
};
|
||||
|
||||
} // namespace tracing
|
||||
} // namespace platform
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_LIBPLATFORM_V8_TRACING_H_
|
||||
|
|
@ -0,0 +1,255 @@
|
|||
// Copyright 2008 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_V8_DEBUG_H_
|
||||
#define V8_V8_DEBUG_H_
|
||||
|
||||
#include "v8.h" // NOLINT(build/include)
|
||||
|
||||
/**
|
||||
* ATTENTION: The debugger API exposed by this file is deprecated and will be
|
||||
* removed by the end of 2017. Please use the V8 inspector declared
|
||||
* in include/v8-inspector.h instead.
|
||||
*/
|
||||
namespace v8 {
|
||||
|
||||
// Debug events which can occur in the V8 JavaScript engine.
|
||||
enum DebugEvent {
|
||||
Break = 1,
|
||||
Exception = 2,
|
||||
AfterCompile = 3,
|
||||
CompileError = 4,
|
||||
AsyncTaskEvent = 5,
|
||||
};
|
||||
|
||||
class V8_EXPORT Debug {
|
||||
public:
|
||||
/**
|
||||
* A client object passed to the v8 debugger whose ownership will be taken by
|
||||
* it. v8 is always responsible for deleting the object.
|
||||
*/
|
||||
class ClientData {
|
||||
public:
|
||||
virtual ~ClientData() {}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A message object passed to the debug message handler.
|
||||
*/
|
||||
class Message {
|
||||
public:
|
||||
/**
|
||||
* Check type of message.
|
||||
*/
|
||||
virtual bool IsEvent() const = 0;
|
||||
virtual bool IsResponse() const = 0;
|
||||
virtual DebugEvent GetEvent() const = 0;
|
||||
|
||||
/**
|
||||
* Indicate whether this is a response to a continue command which will
|
||||
* start the VM running after this is processed.
|
||||
*/
|
||||
virtual bool WillStartRunning() const = 0;
|
||||
|
||||
/**
|
||||
* Access to execution state and event data. Don't store these cross
|
||||
* callbacks as their content becomes invalid. These objects are from the
|
||||
* debugger event that started the debug message loop.
|
||||
*/
|
||||
virtual Local<Object> GetExecutionState() const = 0;
|
||||
virtual Local<Object> GetEventData() const = 0;
|
||||
|
||||
/**
|
||||
* Get the debugger protocol JSON.
|
||||
*/
|
||||
virtual Local<String> GetJSON() const = 0;
|
||||
|
||||
/**
|
||||
* Get the context active when the debug event happened. Note this is not
|
||||
* the current active context as the JavaScript part of the debugger is
|
||||
* running in its own context which is entered at this point.
|
||||
*/
|
||||
virtual Local<Context> GetEventContext() const = 0;
|
||||
|
||||
/**
|
||||
* Client data passed with the corresponding request if any. This is the
|
||||
* client_data data value passed into Debug::SendCommand along with the
|
||||
* request that led to the message or NULL if the message is an event. The
|
||||
* debugger takes ownership of the data and will delete it even if there is
|
||||
* no message handler.
|
||||
*/
|
||||
virtual ClientData* GetClientData() const = 0;
|
||||
|
||||
virtual Isolate* GetIsolate() const = 0;
|
||||
|
||||
virtual ~Message() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* An event details object passed to the debug event listener.
|
||||
*/
|
||||
class EventDetails {
|
||||
public:
|
||||
/**
|
||||
* Event type.
|
||||
*/
|
||||
virtual DebugEvent GetEvent() const = 0;
|
||||
|
||||
/**
|
||||
* Access to execution state and event data of the debug event. Don't store
|
||||
* these cross callbacks as their content becomes invalid.
|
||||
*/
|
||||
virtual Local<Object> GetExecutionState() const = 0;
|
||||
virtual Local<Object> GetEventData() const = 0;
|
||||
|
||||
/**
|
||||
* Get the context active when the debug event happened. Note this is not
|
||||
* the current active context as the JavaScript part of the debugger is
|
||||
* running in its own context which is entered at this point.
|
||||
*/
|
||||
virtual Local<Context> GetEventContext() const = 0;
|
||||
|
||||
/**
|
||||
* Client data passed with the corresponding callback when it was
|
||||
* registered.
|
||||
*/
|
||||
virtual Local<Value> GetCallbackData() const = 0;
|
||||
|
||||
/**
|
||||
* This is now a dummy that returns nullptr.
|
||||
*/
|
||||
virtual ClientData* GetClientData() const = 0;
|
||||
|
||||
virtual Isolate* GetIsolate() const = 0;
|
||||
|
||||
virtual ~EventDetails() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Debug event callback function.
|
||||
*
|
||||
* \param event_details object providing information about the debug event
|
||||
*
|
||||
* A EventCallback does not take possession of the event data,
|
||||
* and must not rely on the data persisting after the handler returns.
|
||||
*/
|
||||
typedef void (*EventCallback)(const EventDetails& event_details);
|
||||
|
||||
/**
|
||||
* This is now a no-op.
|
||||
*/
|
||||
typedef void (*MessageHandler)(const Message& message);
|
||||
|
||||
V8_DEPRECATED("No longer supported", static bool SetDebugEventListener(
|
||||
Isolate* isolate, EventCallback that,
|
||||
Local<Value> data = Local<Value>()));
|
||||
|
||||
// Schedule a debugger break to happen when JavaScript code is run
|
||||
// in the given isolate.
|
||||
V8_DEPRECATED("No longer supported",
|
||||
static void DebugBreak(Isolate* isolate));
|
||||
|
||||
// Remove scheduled debugger break in given isolate if it has not
|
||||
// happened yet.
|
||||
V8_DEPRECATED("No longer supported",
|
||||
static void CancelDebugBreak(Isolate* isolate));
|
||||
|
||||
// Check if a debugger break is scheduled in the given isolate.
|
||||
V8_DEPRECATED("No longer supported",
|
||||
static bool CheckDebugBreak(Isolate* isolate));
|
||||
|
||||
// This is now a no-op.
|
||||
V8_DEPRECATED("No longer supported",
|
||||
static void SetMessageHandler(Isolate* isolate,
|
||||
MessageHandler handler));
|
||||
|
||||
// This is now a no-op.
|
||||
V8_DEPRECATED("No longer supported",
|
||||
static void SendCommand(Isolate* isolate,
|
||||
const uint16_t* command, int length,
|
||||
ClientData* client_data = NULL));
|
||||
|
||||
/**
|
||||
* Run a JavaScript function in the debugger.
|
||||
* \param fun the function to call
|
||||
* \param data passed as second argument to the function
|
||||
* With this call the debugger is entered and the function specified is called
|
||||
* with the execution state as the first argument. This makes it possible to
|
||||
* get access to information otherwise not available during normal JavaScript
|
||||
* execution e.g. details on stack frames. Receiver of the function call will
|
||||
* be the debugger context global object, however this is a subject to change.
|
||||
* The following example shows a JavaScript function which when passed to
|
||||
* v8::Debug::Call will return the current line of JavaScript execution.
|
||||
*
|
||||
* \code
|
||||
* function frame_source_line(exec_state) {
|
||||
* return exec_state.frame(0).sourceLine();
|
||||
* }
|
||||
* \endcode
|
||||
*/
|
||||
V8_DEPRECATED("No longer supported",
|
||||
static MaybeLocal<Value> Call(
|
||||
Local<Context> context, v8::Local<v8::Function> fun,
|
||||
Local<Value> data = Local<Value>()));
|
||||
|
||||
// This is now a no-op.
|
||||
V8_DEPRECATED("No longer supported",
|
||||
static void ProcessDebugMessages(Isolate* isolate));
|
||||
|
||||
/**
|
||||
* Debugger is running in its own context which is entered while debugger
|
||||
* messages are being dispatched. This is an explicit getter for this
|
||||
* debugger context. Note that the content of the debugger context is subject
|
||||
* to change. The Context exists only when the debugger is active, i.e. at
|
||||
* least one DebugEventListener or MessageHandler is set.
|
||||
*/
|
||||
V8_DEPRECATED("Use v8-inspector",
|
||||
static Local<Context> GetDebugContext(Isolate* isolate));
|
||||
|
||||
/**
|
||||
* While in the debug context, this method returns the top-most non-debug
|
||||
* context, if it exists.
|
||||
*/
|
||||
V8_DEPRECATED(
|
||||
"No longer supported",
|
||||
static MaybeLocal<Context> GetDebuggedContext(Isolate* isolate));
|
||||
|
||||
/**
|
||||
* Enable/disable LiveEdit functionality for the given Isolate
|
||||
* (default Isolate if not provided). V8 will abort if LiveEdit is
|
||||
* unexpectedly used. LiveEdit is enabled by default.
|
||||
*/
|
||||
V8_DEPRECATED("No longer supported",
|
||||
static void SetLiveEditEnabled(Isolate* isolate, bool enable));
|
||||
|
||||
/**
|
||||
* Returns array of internal properties specific to the value type. Result has
|
||||
* the following format: [<name>, <value>,...,<name>, <value>]. Result array
|
||||
* will be allocated in the current context.
|
||||
*/
|
||||
V8_DEPRECATED("No longer supported",
|
||||
static MaybeLocal<Array> GetInternalProperties(
|
||||
Isolate* isolate, Local<Value> value));
|
||||
|
||||
/**
|
||||
* Defines if the ES2015 tail call elimination feature is enabled or not.
|
||||
* The change of this flag triggers deoptimization of all functions that
|
||||
* contain calls at tail position.
|
||||
*/
|
||||
V8_DEPRECATED("No longer supported",
|
||||
static bool IsTailCallEliminationEnabled(Isolate* isolate));
|
||||
V8_DEPRECATED("No longer supported",
|
||||
static void SetTailCallEliminationEnabled(Isolate* isolate,
|
||||
bool enabled));
|
||||
};
|
||||
|
||||
|
||||
} // namespace v8
|
||||
|
||||
|
||||
#undef EXPORT
|
||||
|
||||
|
||||
#endif // V8_V8_DEBUG_H_
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_V8_INSPECTOR_PROTOCOL_H_
|
||||
#define V8_V8_INSPECTOR_PROTOCOL_H_
|
||||
|
||||
#include "inspector/Debugger.h" // NOLINT(build/include)
|
||||
#include "inspector/Runtime.h" // NOLINT(build/include)
|
||||
#include "inspector/Schema.h" // NOLINT(build/include)
|
||||
#include "v8-inspector.h" // NOLINT(build/include)
|
||||
|
||||
#endif // V8_V8_INSPECTOR_PROTOCOL_H_
|
||||
|
|
@ -0,0 +1,267 @@
|
|||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_V8_INSPECTOR_H_
|
||||
#define V8_V8_INSPECTOR_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cctype>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "v8.h" // NOLINT(build/include)
|
||||
|
||||
namespace v8_inspector {
|
||||
|
||||
namespace protocol {
|
||||
namespace Debugger {
|
||||
namespace API {
|
||||
class SearchMatch;
|
||||
}
|
||||
}
|
||||
namespace Runtime {
|
||||
namespace API {
|
||||
class RemoteObject;
|
||||
class StackTrace;
|
||||
}
|
||||
}
|
||||
namespace Schema {
|
||||
namespace API {
|
||||
class Domain;
|
||||
}
|
||||
}
|
||||
} // namespace protocol
|
||||
|
||||
class V8_EXPORT StringView {
|
||||
public:
|
||||
StringView() : m_is8Bit(true), m_length(0), m_characters8(nullptr) {}
|
||||
|
||||
StringView(const uint8_t* characters, size_t length)
|
||||
: m_is8Bit(true), m_length(length), m_characters8(characters) {}
|
||||
|
||||
StringView(const uint16_t* characters, size_t length)
|
||||
: m_is8Bit(false), m_length(length), m_characters16(characters) {}
|
||||
|
||||
bool is8Bit() const { return m_is8Bit; }
|
||||
size_t length() const { return m_length; }
|
||||
|
||||
// TODO(dgozman): add DCHECK(m_is8Bit) to accessors once platform can be used
|
||||
// here.
|
||||
const uint8_t* characters8() const { return m_characters8; }
|
||||
const uint16_t* characters16() const { return m_characters16; }
|
||||
|
||||
private:
|
||||
bool m_is8Bit;
|
||||
size_t m_length;
|
||||
union {
|
||||
const uint8_t* m_characters8;
|
||||
const uint16_t* m_characters16;
|
||||
};
|
||||
};
|
||||
|
||||
class V8_EXPORT StringBuffer {
|
||||
public:
|
||||
virtual ~StringBuffer() {}
|
||||
virtual const StringView& string() = 0;
|
||||
// This method copies contents.
|
||||
static std::unique_ptr<StringBuffer> create(const StringView&);
|
||||
};
|
||||
|
||||
class V8_EXPORT V8ContextInfo {
|
||||
public:
|
||||
V8ContextInfo(v8::Local<v8::Context> context, int contextGroupId,
|
||||
const StringView& humanReadableName)
|
||||
: context(context),
|
||||
contextGroupId(contextGroupId),
|
||||
humanReadableName(humanReadableName),
|
||||
hasMemoryOnConsole(false) {}
|
||||
|
||||
v8::Local<v8::Context> context;
|
||||
// Each v8::Context is a part of a group. The group id must be non-zero.
|
||||
int contextGroupId;
|
||||
StringView humanReadableName;
|
||||
StringView origin;
|
||||
StringView auxData;
|
||||
bool hasMemoryOnConsole;
|
||||
|
||||
static int executionContextId(v8::Local<v8::Context> context);
|
||||
|
||||
private:
|
||||
// Disallow copying and allocating this one.
|
||||
enum NotNullTagEnum { NotNullLiteral };
|
||||
void* operator new(size_t) = delete;
|
||||
void* operator new(size_t, NotNullTagEnum, void*) = delete;
|
||||
void* operator new(size_t, void*) = delete;
|
||||
V8ContextInfo(const V8ContextInfo&) = delete;
|
||||
V8ContextInfo& operator=(const V8ContextInfo&) = delete;
|
||||
};
|
||||
|
||||
class V8_EXPORT V8StackTrace {
|
||||
public:
|
||||
virtual bool isEmpty() const = 0;
|
||||
virtual StringView topSourceURL() const = 0;
|
||||
virtual int topLineNumber() const = 0;
|
||||
virtual int topColumnNumber() const = 0;
|
||||
virtual StringView topScriptId() const = 0;
|
||||
virtual StringView topFunctionName() const = 0;
|
||||
|
||||
virtual ~V8StackTrace() {}
|
||||
virtual std::unique_ptr<protocol::Runtime::API::StackTrace>
|
||||
buildInspectorObject() const = 0;
|
||||
virtual std::unique_ptr<StringBuffer> toString() const = 0;
|
||||
|
||||
// Safe to pass between threads, drops async chain.
|
||||
virtual std::unique_ptr<V8StackTrace> clone() = 0;
|
||||
};
|
||||
|
||||
class V8_EXPORT V8InspectorSession {
|
||||
public:
|
||||
virtual ~V8InspectorSession() {}
|
||||
|
||||
// Cross-context inspectable values (DOM nodes in different worlds, etc.).
|
||||
class V8_EXPORT Inspectable {
|
||||
public:
|
||||
virtual v8::Local<v8::Value> get(v8::Local<v8::Context>) = 0;
|
||||
virtual ~Inspectable() {}
|
||||
};
|
||||
virtual void addInspectedObject(std::unique_ptr<Inspectable>) = 0;
|
||||
|
||||
// Dispatching protocol messages.
|
||||
static bool canDispatchMethod(const StringView& method);
|
||||
virtual void dispatchProtocolMessage(const StringView& message) = 0;
|
||||
virtual std::unique_ptr<StringBuffer> stateJSON() = 0;
|
||||
virtual std::vector<std::unique_ptr<protocol::Schema::API::Domain>>
|
||||
supportedDomains() = 0;
|
||||
|
||||
// Debugger actions.
|
||||
virtual void schedulePauseOnNextStatement(const StringView& breakReason,
|
||||
const StringView& breakDetails) = 0;
|
||||
virtual void cancelPauseOnNextStatement() = 0;
|
||||
virtual void breakProgram(const StringView& breakReason,
|
||||
const StringView& breakDetails) = 0;
|
||||
virtual void setSkipAllPauses(bool) = 0;
|
||||
virtual void resume() = 0;
|
||||
virtual void stepOver() = 0;
|
||||
virtual std::vector<std::unique_ptr<protocol::Debugger::API::SearchMatch>>
|
||||
searchInTextByLines(const StringView& text, const StringView& query,
|
||||
bool caseSensitive, bool isRegex) = 0;
|
||||
|
||||
// Remote objects.
|
||||
virtual std::unique_ptr<protocol::Runtime::API::RemoteObject> wrapObject(
|
||||
v8::Local<v8::Context>, v8::Local<v8::Value>,
|
||||
const StringView& groupName) = 0;
|
||||
virtual bool unwrapObject(std::unique_ptr<StringBuffer>* error,
|
||||
const StringView& objectId, v8::Local<v8::Value>*,
|
||||
v8::Local<v8::Context>*,
|
||||
std::unique_ptr<StringBuffer>* objectGroup) = 0;
|
||||
virtual void releaseObjectGroup(const StringView&) = 0;
|
||||
};
|
||||
|
||||
class V8_EXPORT V8InspectorClient {
|
||||
public:
|
||||
virtual ~V8InspectorClient() {}
|
||||
|
||||
virtual void runMessageLoopOnPause(int contextGroupId) {}
|
||||
virtual void quitMessageLoopOnPause() {}
|
||||
virtual void runIfWaitingForDebugger(int contextGroupId) {}
|
||||
|
||||
virtual void muteMetrics(int contextGroupId) {}
|
||||
virtual void unmuteMetrics(int contextGroupId) {}
|
||||
|
||||
virtual void beginUserGesture() {}
|
||||
virtual void endUserGesture() {}
|
||||
|
||||
virtual std::unique_ptr<StringBuffer> valueSubtype(v8::Local<v8::Value>) {
|
||||
return nullptr;
|
||||
}
|
||||
virtual bool formatAccessorsAsProperties(v8::Local<v8::Value>) {
|
||||
return false;
|
||||
}
|
||||
virtual bool isInspectableHeapObject(v8::Local<v8::Object>) { return true; }
|
||||
|
||||
virtual v8::Local<v8::Context> ensureDefaultContextInGroup(
|
||||
int contextGroupId) {
|
||||
return v8::Local<v8::Context>();
|
||||
}
|
||||
virtual void beginEnsureAllContextsInGroup(int contextGroupId) {}
|
||||
virtual void endEnsureAllContextsInGroup(int contextGroupId) {}
|
||||
|
||||
virtual void installAdditionalCommandLineAPI(v8::Local<v8::Context>,
|
||||
v8::Local<v8::Object>) {}
|
||||
virtual void consoleAPIMessage(int contextGroupId,
|
||||
v8::Isolate::MessageErrorLevel level,
|
||||
const StringView& message,
|
||||
const StringView& url, unsigned lineNumber,
|
||||
unsigned columnNumber, V8StackTrace*) {}
|
||||
virtual v8::MaybeLocal<v8::Value> memoryInfo(v8::Isolate*,
|
||||
v8::Local<v8::Context>) {
|
||||
return v8::MaybeLocal<v8::Value>();
|
||||
}
|
||||
|
||||
virtual void consoleTime(const StringView& title) {}
|
||||
virtual void consoleTimeEnd(const StringView& title) {}
|
||||
virtual void consoleTimeStamp(const StringView& title) {}
|
||||
virtual void consoleClear(int contextGroupId) {}
|
||||
virtual double currentTimeMS() { return 0; }
|
||||
typedef void (*TimerCallback)(void*);
|
||||
virtual void startRepeatingTimer(double, TimerCallback, void* data) {}
|
||||
virtual void cancelTimer(void* data) {}
|
||||
|
||||
// TODO(dgozman): this was added to support service worker shadow page. We
|
||||
// should not connect at all.
|
||||
virtual bool canExecuteScripts(int contextGroupId) { return true; }
|
||||
};
|
||||
|
||||
class V8_EXPORT V8Inspector {
|
||||
public:
|
||||
static std::unique_ptr<V8Inspector> create(v8::Isolate*, V8InspectorClient*);
|
||||
virtual ~V8Inspector() {}
|
||||
|
||||
// Contexts instrumentation.
|
||||
virtual void contextCreated(const V8ContextInfo&) = 0;
|
||||
virtual void contextDestroyed(v8::Local<v8::Context>) = 0;
|
||||
virtual void resetContextGroup(int contextGroupId) = 0;
|
||||
|
||||
// Various instrumentation.
|
||||
virtual void idleStarted() = 0;
|
||||
virtual void idleFinished() = 0;
|
||||
|
||||
// Async stack traces instrumentation.
|
||||
virtual void asyncTaskScheduled(const StringView& taskName, void* task,
|
||||
bool recurring) = 0;
|
||||
virtual void asyncTaskCanceled(void* task) = 0;
|
||||
virtual void asyncTaskStarted(void* task) = 0;
|
||||
virtual void asyncTaskFinished(void* task) = 0;
|
||||
virtual void allAsyncTasksCanceled() = 0;
|
||||
|
||||
// Exceptions instrumentation.
|
||||
virtual unsigned exceptionThrown(
|
||||
v8::Local<v8::Context>, const StringView& message,
|
||||
v8::Local<v8::Value> exception, const StringView& detailedMessage,
|
||||
const StringView& url, unsigned lineNumber, unsigned columnNumber,
|
||||
std::unique_ptr<V8StackTrace>, int scriptId) = 0;
|
||||
virtual void exceptionRevoked(v8::Local<v8::Context>, unsigned exceptionId,
|
||||
const StringView& message) = 0;
|
||||
|
||||
// Connection.
|
||||
class V8_EXPORT Channel {
|
||||
public:
|
||||
virtual ~Channel() {}
|
||||
virtual void sendResponse(int callId,
|
||||
std::unique_ptr<StringBuffer> message) = 0;
|
||||
virtual void sendNotification(std::unique_ptr<StringBuffer> message) = 0;
|
||||
virtual void flushProtocolNotifications() = 0;
|
||||
};
|
||||
virtual std::unique_ptr<V8InspectorSession> connect(
|
||||
int contextGroupId, Channel*, const StringView& state) = 0;
|
||||
|
||||
// API methods.
|
||||
virtual std::unique_ptr<V8StackTrace> createStackTrace(
|
||||
v8::Local<v8::StackTrace>) = 0;
|
||||
virtual std::unique_ptr<V8StackTrace> captureStackTrace(bool fullStack) = 0;
|
||||
};
|
||||
|
||||
} // namespace v8_inspector
|
||||
|
||||
#endif // V8_V8_INSPECTOR_H_
|
||||
|
|
@ -0,0 +1,227 @@
|
|||
// Copyright 2013 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_V8_PLATFORM_H_
|
||||
#define V8_V8_PLATFORM_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace v8 {
|
||||
|
||||
class Isolate;
|
||||
|
||||
/**
|
||||
* A Task represents a unit of work.
|
||||
*/
|
||||
class Task {
|
||||
public:
|
||||
virtual ~Task() = default;
|
||||
|
||||
virtual void Run() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* An IdleTask represents a unit of work to be performed in idle time.
|
||||
* The Run method is invoked with an argument that specifies the deadline in
|
||||
* seconds returned by MonotonicallyIncreasingTime().
|
||||
* The idle task is expected to complete by this deadline.
|
||||
*/
|
||||
class IdleTask {
|
||||
public:
|
||||
virtual ~IdleTask() = default;
|
||||
virtual void Run(double deadline_in_seconds) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* The interface represents complex arguments to trace events.
|
||||
*/
|
||||
class ConvertableToTraceFormat {
|
||||
public:
|
||||
virtual ~ConvertableToTraceFormat() = default;
|
||||
|
||||
/**
|
||||
* Append the class info to the provided |out| string. The appended
|
||||
* data must be a valid JSON object. Strings must be properly quoted, and
|
||||
* escaped. There is no processing applied to the content after it is
|
||||
* appended.
|
||||
*/
|
||||
virtual void AppendAsTraceFormat(std::string* out) const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* V8 Platform abstraction layer.
|
||||
*
|
||||
* The embedder has to provide an implementation of this interface before
|
||||
* initializing the rest of V8.
|
||||
*/
|
||||
class Platform {
|
||||
public:
|
||||
/**
|
||||
* This enum is used to indicate whether a task is potentially long running,
|
||||
* or causes a long wait. The embedder might want to use this hint to decide
|
||||
* whether to execute the task on a dedicated thread.
|
||||
*/
|
||||
enum ExpectedRuntime {
|
||||
kShortRunningTask,
|
||||
kLongRunningTask
|
||||
};
|
||||
|
||||
virtual ~Platform() = default;
|
||||
|
||||
/**
|
||||
* Gets the number of threads that are used to execute background tasks. Is
|
||||
* used to estimate the number of tasks a work package should be split into.
|
||||
* A return value of 0 means that there are no background threads available.
|
||||
* Note that a value of 0 won't prohibit V8 from posting tasks using
|
||||
* |CallOnBackgroundThread|.
|
||||
*/
|
||||
virtual size_t NumberOfAvailableBackgroundThreads() { return 0; }
|
||||
|
||||
/**
|
||||
* Schedules a task to be invoked on a background thread. |expected_runtime|
|
||||
* indicates that the task will run a long time. The Platform implementation
|
||||
* takes ownership of |task|. There is no guarantee about order of execution
|
||||
* of tasks wrt order of scheduling, nor is there a guarantee about the
|
||||
* thread the task will be run on.
|
||||
*/
|
||||
virtual void CallOnBackgroundThread(Task* task,
|
||||
ExpectedRuntime expected_runtime) = 0;
|
||||
|
||||
/**
|
||||
* Schedules a task to be invoked on a foreground thread wrt a specific
|
||||
* |isolate|. Tasks posted for the same isolate should be execute in order of
|
||||
* scheduling. The definition of "foreground" is opaque to V8.
|
||||
*/
|
||||
virtual void CallOnForegroundThread(Isolate* isolate, Task* task) = 0;
|
||||
|
||||
/**
|
||||
* Schedules a task to be invoked on a foreground thread wrt a specific
|
||||
* |isolate| after the given number of seconds |delay_in_seconds|.
|
||||
* Tasks posted for the same isolate should be execute in order of
|
||||
* scheduling. The definition of "foreground" is opaque to V8.
|
||||
*/
|
||||
virtual void CallDelayedOnForegroundThread(Isolate* isolate, Task* task,
|
||||
double delay_in_seconds) = 0;
|
||||
|
||||
/**
|
||||
* Schedules a task to be invoked on a foreground thread wrt a specific
|
||||
* |isolate| when the embedder is idle.
|
||||
* Requires that SupportsIdleTasks(isolate) is true.
|
||||
* Idle tasks may be reordered relative to other task types and may be
|
||||
* starved for an arbitrarily long time if no idle time is available.
|
||||
* The definition of "foreground" is opaque to V8.
|
||||
*/
|
||||
virtual void CallIdleOnForegroundThread(Isolate* isolate, IdleTask* task) {
|
||||
// TODO(ulan): Make this function abstract after V8 roll in Chromium.
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if idle tasks are enabled for the given |isolate|.
|
||||
*/
|
||||
virtual bool IdleTasksEnabled(Isolate* isolate) {
|
||||
// TODO(ulan): Make this function abstract after V8 roll in Chromium.
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Monotonically increasing time in seconds from an arbitrary fixed point in
|
||||
* the past. This function is expected to return at least
|
||||
* millisecond-precision values. For this reason,
|
||||
* it is recommended that the fixed point be no further in the past than
|
||||
* the epoch.
|
||||
**/
|
||||
virtual double MonotonicallyIncreasingTime() = 0;
|
||||
|
||||
/**
|
||||
* Called by TRACE_EVENT* macros, don't call this directly.
|
||||
* The name parameter is a category group for example:
|
||||
* TRACE_EVENT0("v8,parse", "V8.Parse")
|
||||
* The pointer returned points to a value with zero or more of the bits
|
||||
* defined in CategoryGroupEnabledFlags.
|
||||
**/
|
||||
virtual const uint8_t* GetCategoryGroupEnabled(const char* name) {
|
||||
static uint8_t no = 0;
|
||||
return &no;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the category group name of the given category_enabled_flag pointer.
|
||||
* Usually used while serliazing TRACE_EVENTs.
|
||||
**/
|
||||
virtual const char* GetCategoryGroupName(
|
||||
const uint8_t* category_enabled_flag) {
|
||||
static const char dummy[] = "dummy";
|
||||
return dummy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a trace event to the platform tracing system. This function call is
|
||||
* usually the result of a TRACE_* macro from trace_event_common.h when
|
||||
* tracing and the category of the particular trace are enabled. It is not
|
||||
* advisable to call this function on its own; it is really only meant to be
|
||||
* used by the trace macros. The returned handle can be used by
|
||||
* UpdateTraceEventDuration to update the duration of COMPLETE events.
|
||||
*/
|
||||
virtual uint64_t AddTraceEvent(
|
||||
char phase, const uint8_t* category_enabled_flag, const char* name,
|
||||
const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args,
|
||||
const char** arg_names, const uint8_t* arg_types,
|
||||
const uint64_t* arg_values, unsigned int flags) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a trace event to the platform tracing system. This function call is
|
||||
* usually the result of a TRACE_* macro from trace_event_common.h when
|
||||
* tracing and the category of the particular trace are enabled. It is not
|
||||
* advisable to call this function on its own; it is really only meant to be
|
||||
* used by the trace macros. The returned handle can be used by
|
||||
* UpdateTraceEventDuration to update the duration of COMPLETE events.
|
||||
*/
|
||||
virtual uint64_t AddTraceEvent(
|
||||
char phase, const uint8_t* category_enabled_flag, const char* name,
|
||||
const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args,
|
||||
const char** arg_names, const uint8_t* arg_types,
|
||||
const uint64_t* arg_values,
|
||||
std::unique_ptr<ConvertableToTraceFormat>* arg_convertables,
|
||||
unsigned int flags) {
|
||||
return AddTraceEvent(phase, category_enabled_flag, name, scope, id, bind_id,
|
||||
num_args, arg_names, arg_types, arg_values, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the duration field of a COMPLETE trace event. It must be called with
|
||||
* the handle returned from AddTraceEvent().
|
||||
**/
|
||||
virtual void UpdateTraceEventDuration(const uint8_t* category_enabled_flag,
|
||||
const char* name, uint64_t handle) {}
|
||||
|
||||
class TraceStateObserver {
|
||||
public:
|
||||
virtual ~TraceStateObserver() = default;
|
||||
virtual void OnTraceEnabled() = 0;
|
||||
virtual void OnTraceDisabled() = 0;
|
||||
};
|
||||
|
||||
/** Adds tracing state change observer. */
|
||||
virtual void AddTraceStateObserver(TraceStateObserver*) {}
|
||||
|
||||
/** Removes tracing state change observer. */
|
||||
virtual void RemoveTraceStateObserver(TraceStateObserver*) {}
|
||||
|
||||
typedef void (*StackTracePrinter)();
|
||||
|
||||
/**
|
||||
* Returns a function pointer that print a stack trace of the current stack
|
||||
* on invocation. Disables printing of the stack trace if nullptr.
|
||||
*/
|
||||
virtual StackTracePrinter GetStackTracePrinter() { return nullptr; }
|
||||
};
|
||||
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_V8_PLATFORM_H_
|
||||
|
|
@ -0,0 +1,912 @@
|
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_V8_PROFILER_H_
|
||||
#define V8_V8_PROFILER_H_
|
||||
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include "v8.h" // NOLINT(build/include)
|
||||
|
||||
/**
|
||||
* Profiler support for the V8 JavaScript engine.
|
||||
*/
|
||||
namespace v8 {
|
||||
|
||||
class HeapGraphNode;
|
||||
struct HeapStatsUpdate;
|
||||
|
||||
typedef uint32_t SnapshotObjectId;
|
||||
|
||||
|
||||
struct CpuProfileDeoptFrame {
|
||||
int script_id;
|
||||
size_t position;
|
||||
};
|
||||
|
||||
} // namespace v8
|
||||
|
||||
#ifdef V8_OS_WIN
|
||||
template class V8_EXPORT std::vector<v8::CpuProfileDeoptFrame>;
|
||||
#endif
|
||||
|
||||
namespace v8 {
|
||||
|
||||
struct V8_EXPORT CpuProfileDeoptInfo {
|
||||
/** A pointer to a static string owned by v8. */
|
||||
const char* deopt_reason;
|
||||
std::vector<CpuProfileDeoptFrame> stack;
|
||||
};
|
||||
|
||||
} // namespace v8
|
||||
|
||||
#ifdef V8_OS_WIN
|
||||
template class V8_EXPORT std::vector<v8::CpuProfileDeoptInfo>;
|
||||
#endif
|
||||
|
||||
namespace v8 {
|
||||
|
||||
/**
|
||||
* TracingCpuProfiler monitors tracing being enabled/disabled
|
||||
* and emits CpuProfile trace events once v8.cpu_profiler tracing category
|
||||
* is enabled. It has no overhead unless the category is enabled.
|
||||
*/
|
||||
class V8_EXPORT TracingCpuProfiler {
|
||||
public:
|
||||
static std::unique_ptr<TracingCpuProfiler> Create(Isolate*);
|
||||
virtual ~TracingCpuProfiler() = default;
|
||||
|
||||
protected:
|
||||
TracingCpuProfiler() = default;
|
||||
};
|
||||
|
||||
// TickSample captures the information collected for each sample.
|
||||
struct TickSample {
|
||||
// Internal profiling (with --prof + tools/$OS-tick-processor) wants to
|
||||
// include the runtime function we're calling. Externally exposed tick
|
||||
// samples don't care.
|
||||
enum RecordCEntryFrame { kIncludeCEntryFrame, kSkipCEntryFrame };
|
||||
|
||||
TickSample()
|
||||
: state(OTHER),
|
||||
pc(nullptr),
|
||||
external_callback_entry(nullptr),
|
||||
frames_count(0),
|
||||
has_external_callback(false),
|
||||
update_stats(true) {}
|
||||
|
||||
/**
|
||||
* Initialize a tick sample from the isolate.
|
||||
* \param isolate The isolate.
|
||||
* \param state Execution state.
|
||||
* \param record_c_entry_frame Include or skip the runtime function.
|
||||
* \param update_stats Whether update the sample to the aggregated stats.
|
||||
* \param use_simulator_reg_state When set to true and V8 is running under a
|
||||
* simulator, the method will use the simulator
|
||||
* register state rather than the one provided
|
||||
* with |state| argument. Otherwise the method
|
||||
* will use provided register |state| as is.
|
||||
*/
|
||||
void Init(Isolate* isolate, const v8::RegisterState& state,
|
||||
RecordCEntryFrame record_c_entry_frame, bool update_stats,
|
||||
bool use_simulator_reg_state = true);
|
||||
/**
|
||||
* Get a call stack sample from the isolate.
|
||||
* \param isolate The isolate.
|
||||
* \param state Register state.
|
||||
* \param record_c_entry_frame Include or skip the runtime function.
|
||||
* \param frames Caller allocated buffer to store stack frames.
|
||||
* \param frames_limit Maximum number of frames to capture. The buffer must
|
||||
* be large enough to hold the number of frames.
|
||||
* \param sample_info The sample info is filled up by the function
|
||||
* provides number of actual captured stack frames and
|
||||
* the current VM state.
|
||||
* \param use_simulator_reg_state When set to true and V8 is running under a
|
||||
* simulator, the method will use the simulator
|
||||
* register state rather than the one provided
|
||||
* with |state| argument. Otherwise the method
|
||||
* will use provided register |state| as is.
|
||||
* \note GetStackSample is thread and signal safe and should only be called
|
||||
* when the JS thread is paused or interrupted.
|
||||
* Otherwise the behavior is undefined.
|
||||
*/
|
||||
static bool GetStackSample(Isolate* isolate, v8::RegisterState* state,
|
||||
RecordCEntryFrame record_c_entry_frame,
|
||||
void** frames, size_t frames_limit,
|
||||
v8::SampleInfo* sample_info,
|
||||
bool use_simulator_reg_state = true);
|
||||
StateTag state; // The state of the VM.
|
||||
void* pc; // Instruction pointer.
|
||||
union {
|
||||
void* tos; // Top stack value (*sp).
|
||||
void* external_callback_entry;
|
||||
};
|
||||
static const unsigned kMaxFramesCountLog2 = 8;
|
||||
static const unsigned kMaxFramesCount = (1 << kMaxFramesCountLog2) - 1;
|
||||
void* stack[kMaxFramesCount]; // Call stack.
|
||||
unsigned frames_count : kMaxFramesCountLog2; // Number of captured frames.
|
||||
bool has_external_callback : 1;
|
||||
bool update_stats : 1; // Whether the sample should update aggregated stats.
|
||||
};
|
||||
|
||||
/**
|
||||
* CpuProfileNode represents a node in a call graph.
|
||||
*/
|
||||
class V8_EXPORT CpuProfileNode {
|
||||
public:
|
||||
struct LineTick {
|
||||
/** The 1-based number of the source line where the function originates. */
|
||||
int line;
|
||||
|
||||
/** The count of samples associated with the source line. */
|
||||
unsigned int hit_count;
|
||||
};
|
||||
|
||||
/** Returns function name (empty string for anonymous functions.) */
|
||||
Local<String> GetFunctionName() const;
|
||||
|
||||
/**
|
||||
* Returns function name (empty string for anonymous functions.)
|
||||
* The string ownership is *not* passed to the caller. It stays valid until
|
||||
* profile is deleted. The function is thread safe.
|
||||
*/
|
||||
const char* GetFunctionNameStr() const;
|
||||
|
||||
/** Returns id of the script where function is located. */
|
||||
int GetScriptId() const;
|
||||
|
||||
/** Returns resource name for script from where the function originates. */
|
||||
Local<String> GetScriptResourceName() const;
|
||||
|
||||
/**
|
||||
* Returns resource name for script from where the function originates.
|
||||
* The string ownership is *not* passed to the caller. It stays valid until
|
||||
* profile is deleted. The function is thread safe.
|
||||
*/
|
||||
const char* GetScriptResourceNameStr() const;
|
||||
|
||||
/**
|
||||
* Returns the number, 1-based, of the line where the function originates.
|
||||
* kNoLineNumberInfo if no line number information is available.
|
||||
*/
|
||||
int GetLineNumber() const;
|
||||
|
||||
/**
|
||||
* Returns 1-based number of the column where the function originates.
|
||||
* kNoColumnNumberInfo if no column number information is available.
|
||||
*/
|
||||
int GetColumnNumber() const;
|
||||
|
||||
/**
|
||||
* Returns the number of the function's source lines that collect the samples.
|
||||
*/
|
||||
unsigned int GetHitLineCount() const;
|
||||
|
||||
/** Returns the set of source lines that collect the samples.
|
||||
* The caller allocates buffer and responsible for releasing it.
|
||||
* True if all available entries are copied, otherwise false.
|
||||
* The function copies nothing if buffer is not large enough.
|
||||
*/
|
||||
bool GetLineTicks(LineTick* entries, unsigned int length) const;
|
||||
|
||||
/** Returns bailout reason for the function
|
||||
* if the optimization was disabled for it.
|
||||
*/
|
||||
const char* GetBailoutReason() const;
|
||||
|
||||
/**
|
||||
* Returns the count of samples where the function was currently executing.
|
||||
*/
|
||||
unsigned GetHitCount() const;
|
||||
|
||||
/** Returns function entry UID. */
|
||||
V8_DEPRECATE_SOON(
|
||||
"Use GetScriptId, GetLineNumber, and GetColumnNumber instead.",
|
||||
unsigned GetCallUid() const);
|
||||
|
||||
/** Returns id of the node. The id is unique within the tree */
|
||||
unsigned GetNodeId() const;
|
||||
|
||||
/** Returns child nodes count of the node. */
|
||||
int GetChildrenCount() const;
|
||||
|
||||
/** Retrieves a child node by index. */
|
||||
const CpuProfileNode* GetChild(int index) const;
|
||||
|
||||
/** Retrieves deopt infos for the node. */
|
||||
const std::vector<CpuProfileDeoptInfo>& GetDeoptInfos() const;
|
||||
|
||||
static const int kNoLineNumberInfo = Message::kNoLineNumberInfo;
|
||||
static const int kNoColumnNumberInfo = Message::kNoColumnInfo;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* CpuProfile contains a CPU profile in a form of top-down call tree
|
||||
* (from main() down to functions that do all the work).
|
||||
*/
|
||||
class V8_EXPORT CpuProfile {
|
||||
public:
|
||||
/** Returns CPU profile title. */
|
||||
Local<String> GetTitle() const;
|
||||
|
||||
/** Returns the root node of the top down call tree. */
|
||||
const CpuProfileNode* GetTopDownRoot() const;
|
||||
|
||||
/**
|
||||
* Returns number of samples recorded. The samples are not recorded unless
|
||||
* |record_samples| parameter of CpuProfiler::StartCpuProfiling is true.
|
||||
*/
|
||||
int GetSamplesCount() const;
|
||||
|
||||
/**
|
||||
* Returns profile node corresponding to the top frame the sample at
|
||||
* the given index.
|
||||
*/
|
||||
const CpuProfileNode* GetSample(int index) const;
|
||||
|
||||
/**
|
||||
* Returns the timestamp of the sample. The timestamp is the number of
|
||||
* microseconds since some unspecified starting point.
|
||||
* The point is equal to the starting point used by GetStartTime.
|
||||
*/
|
||||
int64_t GetSampleTimestamp(int index) const;
|
||||
|
||||
/**
|
||||
* Returns time when the profile recording was started (in microseconds)
|
||||
* since some unspecified starting point.
|
||||
*/
|
||||
int64_t GetStartTime() const;
|
||||
|
||||
/**
|
||||
* Returns time when the profile recording was stopped (in microseconds)
|
||||
* since some unspecified starting point.
|
||||
* The point is equal to the starting point used by GetStartTime.
|
||||
*/
|
||||
int64_t GetEndTime() const;
|
||||
|
||||
/**
|
||||
* Deletes the profile and removes it from CpuProfiler's list.
|
||||
* All pointers to nodes previously returned become invalid.
|
||||
*/
|
||||
void Delete();
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface for controlling CPU profiling. Instance of the
|
||||
* profiler can be created using v8::CpuProfiler::New method.
|
||||
*/
|
||||
class V8_EXPORT CpuProfiler {
|
||||
public:
|
||||
/**
|
||||
* Creates a new CPU profiler for the |isolate|. The isolate must be
|
||||
* initialized. The profiler object must be disposed after use by calling
|
||||
* |Dispose| method.
|
||||
*/
|
||||
static CpuProfiler* New(Isolate* isolate);
|
||||
|
||||
/**
|
||||
* Disposes the CPU profiler object.
|
||||
*/
|
||||
void Dispose();
|
||||
|
||||
/**
|
||||
* Changes default CPU profiler sampling interval to the specified number
|
||||
* of microseconds. Default interval is 1000us. This method must be called
|
||||
* when there are no profiles being recorded.
|
||||
*/
|
||||
void SetSamplingInterval(int us);
|
||||
|
||||
/**
|
||||
* Starts collecting CPU profile. Title may be an empty string. It
|
||||
* is allowed to have several profiles being collected at
|
||||
* once. Attempts to start collecting several profiles with the same
|
||||
* title are silently ignored. While collecting a profile, functions
|
||||
* from all security contexts are included in it. The token-based
|
||||
* filtering is only performed when querying for a profile.
|
||||
*
|
||||
* |record_samples| parameter controls whether individual samples should
|
||||
* be recorded in addition to the aggregated tree.
|
||||
*/
|
||||
void StartProfiling(Local<String> title, bool record_samples = false);
|
||||
|
||||
/**
|
||||
* Stops collecting CPU profile with a given title and returns it.
|
||||
* If the title given is empty, finishes the last profile started.
|
||||
*/
|
||||
CpuProfile* StopProfiling(Local<String> title);
|
||||
|
||||
/**
|
||||
* Force collection of a sample. Must be called on the VM thread.
|
||||
* Recording the forced sample does not contribute to the aggregated
|
||||
* profile statistics.
|
||||
*/
|
||||
void CollectSample();
|
||||
|
||||
/**
|
||||
* Tells the profiler whether the embedder is idle.
|
||||
*/
|
||||
void SetIdle(bool is_idle);
|
||||
|
||||
private:
|
||||
CpuProfiler();
|
||||
~CpuProfiler();
|
||||
CpuProfiler(const CpuProfiler&);
|
||||
CpuProfiler& operator=(const CpuProfiler&);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* HeapSnapshotEdge represents a directed connection between heap
|
||||
* graph nodes: from retainers to retained nodes.
|
||||
*/
|
||||
class V8_EXPORT HeapGraphEdge {
|
||||
public:
|
||||
enum Type {
|
||||
kContextVariable = 0, // A variable from a function context.
|
||||
kElement = 1, // An element of an array.
|
||||
kProperty = 2, // A named object property.
|
||||
kInternal = 3, // A link that can't be accessed from JS,
|
||||
// thus, its name isn't a real property name
|
||||
// (e.g. parts of a ConsString).
|
||||
kHidden = 4, // A link that is needed for proper sizes
|
||||
// calculation, but may be hidden from user.
|
||||
kShortcut = 5, // A link that must not be followed during
|
||||
// sizes calculation.
|
||||
kWeak = 6 // A weak reference (ignored by the GC).
|
||||
};
|
||||
|
||||
/** Returns edge type (see HeapGraphEdge::Type). */
|
||||
Type GetType() const;
|
||||
|
||||
/**
|
||||
* Returns edge name. This can be a variable name, an element index, or
|
||||
* a property name.
|
||||
*/
|
||||
Local<Value> GetName() const;
|
||||
|
||||
/** Returns origin node. */
|
||||
const HeapGraphNode* GetFromNode() const;
|
||||
|
||||
/** Returns destination node. */
|
||||
const HeapGraphNode* GetToNode() const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* HeapGraphNode represents a node in a heap graph.
|
||||
*/
|
||||
class V8_EXPORT HeapGraphNode {
|
||||
public:
|
||||
enum Type {
|
||||
kHidden = 0, // Hidden node, may be filtered when shown to user.
|
||||
kArray = 1, // An array of elements.
|
||||
kString = 2, // A string.
|
||||
kObject = 3, // A JS object (except for arrays and strings).
|
||||
kCode = 4, // Compiled code.
|
||||
kClosure = 5, // Function closure.
|
||||
kRegExp = 6, // RegExp.
|
||||
kHeapNumber = 7, // Number stored in the heap.
|
||||
kNative = 8, // Native object (not from V8 heap).
|
||||
kSynthetic = 9, // Synthetic object, usualy used for grouping
|
||||
// snapshot items together.
|
||||
kConsString = 10, // Concatenated string. A pair of pointers to strings.
|
||||
kSlicedString = 11, // Sliced string. A fragment of another string.
|
||||
kSymbol = 12 // A Symbol (ES6).
|
||||
};
|
||||
|
||||
/** Returns node type (see HeapGraphNode::Type). */
|
||||
Type GetType() const;
|
||||
|
||||
/**
|
||||
* Returns node name. Depending on node's type this can be the name
|
||||
* of the constructor (for objects), the name of the function (for
|
||||
* closures), string value, or an empty string (for compiled code).
|
||||
*/
|
||||
Local<String> GetName() const;
|
||||
|
||||
/**
|
||||
* Returns node id. For the same heap object, the id remains the same
|
||||
* across all snapshots.
|
||||
*/
|
||||
SnapshotObjectId GetId() const;
|
||||
|
||||
/** Returns node's own size, in bytes. */
|
||||
size_t GetShallowSize() const;
|
||||
|
||||
/** Returns child nodes count of the node. */
|
||||
int GetChildrenCount() const;
|
||||
|
||||
/** Retrieves a child by index. */
|
||||
const HeapGraphEdge* GetChild(int index) const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An interface for exporting data from V8, using "push" model.
|
||||
*/
|
||||
class V8_EXPORT OutputStream { // NOLINT
|
||||
public:
|
||||
enum WriteResult {
|
||||
kContinue = 0,
|
||||
kAbort = 1
|
||||
};
|
||||
virtual ~OutputStream() {}
|
||||
/** Notify about the end of stream. */
|
||||
virtual void EndOfStream() = 0;
|
||||
/** Get preferred output chunk size. Called only once. */
|
||||
virtual int GetChunkSize() { return 1024; }
|
||||
/**
|
||||
* Writes the next chunk of snapshot data into the stream. Writing
|
||||
* can be stopped by returning kAbort as function result. EndOfStream
|
||||
* will not be called in case writing was aborted.
|
||||
*/
|
||||
virtual WriteResult WriteAsciiChunk(char* data, int size) = 0;
|
||||
/**
|
||||
* Writes the next chunk of heap stats data into the stream. Writing
|
||||
* can be stopped by returning kAbort as function result. EndOfStream
|
||||
* will not be called in case writing was aborted.
|
||||
*/
|
||||
virtual WriteResult WriteHeapStatsChunk(HeapStatsUpdate* data, int count) {
|
||||
return kAbort;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* HeapSnapshots record the state of the JS heap at some moment.
|
||||
*/
|
||||
class V8_EXPORT HeapSnapshot {
|
||||
public:
|
||||
enum SerializationFormat {
|
||||
kJSON = 0 // See format description near 'Serialize' method.
|
||||
};
|
||||
|
||||
/** Returns the root node of the heap graph. */
|
||||
const HeapGraphNode* GetRoot() const;
|
||||
|
||||
/** Returns a node by its id. */
|
||||
const HeapGraphNode* GetNodeById(SnapshotObjectId id) const;
|
||||
|
||||
/** Returns total nodes count in the snapshot. */
|
||||
int GetNodesCount() const;
|
||||
|
||||
/** Returns a node by index. */
|
||||
const HeapGraphNode* GetNode(int index) const;
|
||||
|
||||
/** Returns a max seen JS object Id. */
|
||||
SnapshotObjectId GetMaxSnapshotJSObjectId() const;
|
||||
|
||||
/**
|
||||
* Deletes the snapshot and removes it from HeapProfiler's list.
|
||||
* All pointers to nodes, edges and paths previously returned become
|
||||
* invalid.
|
||||
*/
|
||||
void Delete();
|
||||
|
||||
/**
|
||||
* Prepare a serialized representation of the snapshot. The result
|
||||
* is written into the stream provided in chunks of specified size.
|
||||
* The total length of the serialized snapshot is unknown in
|
||||
* advance, it can be roughly equal to JS heap size (that means,
|
||||
* it can be really big - tens of megabytes).
|
||||
*
|
||||
* For the JSON format, heap contents are represented as an object
|
||||
* with the following structure:
|
||||
*
|
||||
* {
|
||||
* snapshot: {
|
||||
* title: "...",
|
||||
* uid: nnn,
|
||||
* meta: { meta-info },
|
||||
* node_count: nnn,
|
||||
* edge_count: nnn
|
||||
* },
|
||||
* nodes: [nodes array],
|
||||
* edges: [edges array],
|
||||
* strings: [strings array]
|
||||
* }
|
||||
*
|
||||
* Nodes reference strings, other nodes, and edges by their indexes
|
||||
* in corresponding arrays.
|
||||
*/
|
||||
void Serialize(OutputStream* stream,
|
||||
SerializationFormat format = kJSON) const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An interface for reporting progress and controlling long-running
|
||||
* activities.
|
||||
*/
|
||||
class V8_EXPORT ActivityControl { // NOLINT
|
||||
public:
|
||||
enum ControlOption {
|
||||
kContinue = 0,
|
||||
kAbort = 1
|
||||
};
|
||||
virtual ~ActivityControl() {}
|
||||
/**
|
||||
* Notify about current progress. The activity can be stopped by
|
||||
* returning kAbort as the callback result.
|
||||
*/
|
||||
virtual ControlOption ReportProgressValue(int done, int total) = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* AllocationProfile is a sampled profile of allocations done by the program.
|
||||
* This is structured as a call-graph.
|
||||
*/
|
||||
class V8_EXPORT AllocationProfile {
|
||||
public:
|
||||
struct Allocation {
|
||||
/**
|
||||
* Size of the sampled allocation object.
|
||||
*/
|
||||
size_t size;
|
||||
|
||||
/**
|
||||
* The number of objects of such size that were sampled.
|
||||
*/
|
||||
unsigned int count;
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a node in the call-graph.
|
||||
*/
|
||||
struct Node {
|
||||
/**
|
||||
* Name of the function. May be empty for anonymous functions or if the
|
||||
* script corresponding to this function has been unloaded.
|
||||
*/
|
||||
Local<String> name;
|
||||
|
||||
/**
|
||||
* Name of the script containing the function. May be empty if the script
|
||||
* name is not available, or if the script has been unloaded.
|
||||
*/
|
||||
Local<String> script_name;
|
||||
|
||||
/**
|
||||
* id of the script where the function is located. May be equal to
|
||||
* v8::UnboundScript::kNoScriptId in cases where the script doesn't exist.
|
||||
*/
|
||||
int script_id;
|
||||
|
||||
/**
|
||||
* Start position of the function in the script.
|
||||
*/
|
||||
int start_position;
|
||||
|
||||
/**
|
||||
* 1-indexed line number where the function starts. May be
|
||||
* kNoLineNumberInfo if no line number information is available.
|
||||
*/
|
||||
int line_number;
|
||||
|
||||
/**
|
||||
* 1-indexed column number where the function starts. May be
|
||||
* kNoColumnNumberInfo if no line number information is available.
|
||||
*/
|
||||
int column_number;
|
||||
|
||||
/**
|
||||
* List of callees called from this node for which we have sampled
|
||||
* allocations. The lifetime of the children is scoped to the containing
|
||||
* AllocationProfile.
|
||||
*/
|
||||
std::vector<Node*> children;
|
||||
|
||||
/**
|
||||
* List of self allocations done by this node in the call-graph.
|
||||
*/
|
||||
std::vector<Allocation> allocations;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the root node of the call-graph. The root node corresponds to an
|
||||
* empty JS call-stack. The lifetime of the returned Node* is scoped to the
|
||||
* containing AllocationProfile.
|
||||
*/
|
||||
virtual Node* GetRootNode() = 0;
|
||||
|
||||
virtual ~AllocationProfile() {}
|
||||
|
||||
static const int kNoLineNumberInfo = Message::kNoLineNumberInfo;
|
||||
static const int kNoColumnNumberInfo = Message::kNoColumnInfo;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Interface for controlling heap profiling. Instance of the
|
||||
* profiler can be retrieved using v8::Isolate::GetHeapProfiler.
|
||||
*/
|
||||
class V8_EXPORT HeapProfiler {
|
||||
public:
|
||||
enum SamplingFlags {
|
||||
kSamplingNoFlags = 0,
|
||||
kSamplingForceGC = 1 << 0,
|
||||
};
|
||||
|
||||
typedef std::unordered_set<const v8::PersistentBase<v8::Value>*>
|
||||
RetainerChildren;
|
||||
typedef std::vector<std::pair<v8::RetainedObjectInfo*, RetainerChildren>>
|
||||
RetainerGroups;
|
||||
typedef std::vector<std::pair<const v8::PersistentBase<v8::Value>*,
|
||||
const v8::PersistentBase<v8::Value>*>>
|
||||
RetainerEdges;
|
||||
|
||||
struct RetainerInfos {
|
||||
RetainerGroups groups;
|
||||
RetainerEdges edges;
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback function invoked to retrieve all RetainerInfos from the embedder.
|
||||
*/
|
||||
typedef RetainerInfos (*GetRetainerInfosCallback)(v8::Isolate* isolate);
|
||||
|
||||
/**
|
||||
* Callback function invoked for obtaining RetainedObjectInfo for
|
||||
* the given JavaScript wrapper object. It is prohibited to enter V8
|
||||
* while the callback is running: only getters on the handle and
|
||||
* GetPointerFromInternalField on the objects are allowed.
|
||||
*/
|
||||
typedef RetainedObjectInfo* (*WrapperInfoCallback)(uint16_t class_id,
|
||||
Local<Value> wrapper);
|
||||
|
||||
/** Returns the number of snapshots taken. */
|
||||
int GetSnapshotCount();
|
||||
|
||||
/** Returns a snapshot by index. */
|
||||
const HeapSnapshot* GetHeapSnapshot(int index);
|
||||
|
||||
/**
|
||||
* Returns SnapshotObjectId for a heap object referenced by |value| if
|
||||
* it has been seen by the heap profiler, kUnknownObjectId otherwise.
|
||||
*/
|
||||
SnapshotObjectId GetObjectId(Local<Value> value);
|
||||
|
||||
/**
|
||||
* Returns heap object with given SnapshotObjectId if the object is alive,
|
||||
* otherwise empty handle is returned.
|
||||
*/
|
||||
Local<Value> FindObjectById(SnapshotObjectId id);
|
||||
|
||||
/**
|
||||
* Clears internal map from SnapshotObjectId to heap object. The new objects
|
||||
* will not be added into it unless a heap snapshot is taken or heap object
|
||||
* tracking is kicked off.
|
||||
*/
|
||||
void ClearObjectIds();
|
||||
|
||||
/**
|
||||
* A constant for invalid SnapshotObjectId. GetSnapshotObjectId will return
|
||||
* it in case heap profiler cannot find id for the object passed as
|
||||
* parameter. HeapSnapshot::GetNodeById will always return NULL for such id.
|
||||
*/
|
||||
static const SnapshotObjectId kUnknownObjectId = 0;
|
||||
|
||||
/**
|
||||
* Callback interface for retrieving user friendly names of global objects.
|
||||
*/
|
||||
class ObjectNameResolver {
|
||||
public:
|
||||
/**
|
||||
* Returns name to be used in the heap snapshot for given node. Returned
|
||||
* string must stay alive until snapshot collection is completed.
|
||||
*/
|
||||
virtual const char* GetName(Local<Object> object) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~ObjectNameResolver() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Takes a heap snapshot and returns it.
|
||||
*/
|
||||
const HeapSnapshot* TakeHeapSnapshot(
|
||||
ActivityControl* control = NULL,
|
||||
ObjectNameResolver* global_object_name_resolver = NULL);
|
||||
|
||||
/**
|
||||
* Starts tracking of heap objects population statistics. After calling
|
||||
* this method, all heap objects relocations done by the garbage collector
|
||||
* are being registered.
|
||||
*
|
||||
* |track_allocations| parameter controls whether stack trace of each
|
||||
* allocation in the heap will be recorded and reported as part of
|
||||
* HeapSnapshot.
|
||||
*/
|
||||
void StartTrackingHeapObjects(bool track_allocations = false);
|
||||
|
||||
/**
|
||||
* Adds a new time interval entry to the aggregated statistics array. The
|
||||
* time interval entry contains information on the current heap objects
|
||||
* population size. The method also updates aggregated statistics and
|
||||
* reports updates for all previous time intervals via the OutputStream
|
||||
* object. Updates on each time interval are provided as a stream of the
|
||||
* HeapStatsUpdate structure instances.
|
||||
* If |timestamp_us| is supplied, timestamp of the new entry will be written
|
||||
* into it. The return value of the function is the last seen heap object Id.
|
||||
*
|
||||
* StartTrackingHeapObjects must be called before the first call to this
|
||||
* method.
|
||||
*/
|
||||
SnapshotObjectId GetHeapStats(OutputStream* stream,
|
||||
int64_t* timestamp_us = NULL);
|
||||
|
||||
/**
|
||||
* Stops tracking of heap objects population statistics, cleans up all
|
||||
* collected data. StartHeapObjectsTracking must be called again prior to
|
||||
* calling GetHeapStats next time.
|
||||
*/
|
||||
void StopTrackingHeapObjects();
|
||||
|
||||
/**
|
||||
* Starts gathering a sampling heap profile. A sampling heap profile is
|
||||
* similar to tcmalloc's heap profiler and Go's mprof. It samples object
|
||||
* allocations and builds an online 'sampling' heap profile. At any point in
|
||||
* time, this profile is expected to be a representative sample of objects
|
||||
* currently live in the system. Each sampled allocation includes the stack
|
||||
* trace at the time of allocation, which makes this really useful for memory
|
||||
* leak detection.
|
||||
*
|
||||
* This mechanism is intended to be cheap enough that it can be used in
|
||||
* production with minimal performance overhead.
|
||||
*
|
||||
* Allocations are sampled using a randomized Poisson process. On average, one
|
||||
* allocation will be sampled every |sample_interval| bytes allocated. The
|
||||
* |stack_depth| parameter controls the maximum number of stack frames to be
|
||||
* captured on each allocation.
|
||||
*
|
||||
* NOTE: This is a proof-of-concept at this point. Right now we only sample
|
||||
* newspace allocations. Support for paged space allocation (e.g. pre-tenured
|
||||
* objects, large objects, code objects, etc.) and native allocations
|
||||
* doesn't exist yet, but is anticipated in the future.
|
||||
*
|
||||
* Objects allocated before the sampling is started will not be included in
|
||||
* the profile.
|
||||
*
|
||||
* Returns false if a sampling heap profiler is already running.
|
||||
*/
|
||||
bool StartSamplingHeapProfiler(uint64_t sample_interval = 512 * 1024,
|
||||
int stack_depth = 16,
|
||||
SamplingFlags flags = kSamplingNoFlags);
|
||||
|
||||
/**
|
||||
* Stops the sampling heap profile and discards the current profile.
|
||||
*/
|
||||
void StopSamplingHeapProfiler();
|
||||
|
||||
/**
|
||||
* Returns the sampled profile of allocations allocated (and still live) since
|
||||
* StartSamplingHeapProfiler was called. The ownership of the pointer is
|
||||
* transfered to the caller. Returns nullptr if sampling heap profiler is not
|
||||
* active.
|
||||
*/
|
||||
AllocationProfile* GetAllocationProfile();
|
||||
|
||||
/**
|
||||
* Deletes all snapshots taken. All previously returned pointers to
|
||||
* snapshots and their contents become invalid after this call.
|
||||
*/
|
||||
void DeleteAllHeapSnapshots();
|
||||
|
||||
/** Binds a callback to embedder's class ID. */
|
||||
void SetWrapperClassInfoProvider(
|
||||
uint16_t class_id,
|
||||
WrapperInfoCallback callback);
|
||||
|
||||
void SetGetRetainerInfosCallback(GetRetainerInfosCallback callback);
|
||||
|
||||
/**
|
||||
* Default value of persistent handle class ID. Must not be used to
|
||||
* define a class. Can be used to reset a class of a persistent
|
||||
* handle.
|
||||
*/
|
||||
static const uint16_t kPersistentHandleNoClassId = 0;
|
||||
|
||||
/** Returns memory used for profiler internal data and snapshots. */
|
||||
size_t GetProfilerMemorySize();
|
||||
|
||||
private:
|
||||
HeapProfiler();
|
||||
~HeapProfiler();
|
||||
HeapProfiler(const HeapProfiler&);
|
||||
HeapProfiler& operator=(const HeapProfiler&);
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface for providing information about embedder's objects
|
||||
* held by global handles. This information is reported in two ways:
|
||||
*
|
||||
* 1. When calling AddObjectGroup, an embedder may pass
|
||||
* RetainedObjectInfo instance describing the group. To collect
|
||||
* this information while taking a heap snapshot, V8 calls GC
|
||||
* prologue and epilogue callbacks.
|
||||
*
|
||||
* 2. When a heap snapshot is collected, V8 additionally
|
||||
* requests RetainedObjectInfos for persistent handles that
|
||||
* were not previously reported via AddObjectGroup.
|
||||
*
|
||||
* Thus, if an embedder wants to provide information about native
|
||||
* objects for heap snapshots, it can do it in a GC prologue
|
||||
* handler, and / or by assigning wrapper class ids in the following way:
|
||||
*
|
||||
* 1. Bind a callback to class id by calling SetWrapperClassInfoProvider.
|
||||
* 2. Call SetWrapperClassId on certain persistent handles.
|
||||
*
|
||||
* V8 takes ownership of RetainedObjectInfo instances passed to it and
|
||||
* keeps them alive only during snapshot collection. Afterwards, they
|
||||
* are freed by calling the Dispose class function.
|
||||
*/
|
||||
class V8_EXPORT RetainedObjectInfo { // NOLINT
|
||||
public:
|
||||
/** Called by V8 when it no longer needs an instance. */
|
||||
virtual void Dispose() = 0;
|
||||
|
||||
/** Returns whether two instances are equivalent. */
|
||||
virtual bool IsEquivalent(RetainedObjectInfo* other) = 0;
|
||||
|
||||
/**
|
||||
* Returns hash value for the instance. Equivalent instances
|
||||
* must have the same hash value.
|
||||
*/
|
||||
virtual intptr_t GetHash() = 0;
|
||||
|
||||
/**
|
||||
* Returns human-readable label. It must be a null-terminated UTF-8
|
||||
* encoded string. V8 copies its contents during a call to GetLabel.
|
||||
*/
|
||||
virtual const char* GetLabel() = 0;
|
||||
|
||||
/**
|
||||
* Returns human-readable group label. It must be a null-terminated UTF-8
|
||||
* encoded string. V8 copies its contents during a call to GetGroupLabel.
|
||||
* Heap snapshot generator will collect all the group names, create
|
||||
* top level entries with these names and attach the objects to the
|
||||
* corresponding top level group objects. There is a default
|
||||
* implementation which is required because embedders don't have their
|
||||
* own implementation yet.
|
||||
*/
|
||||
virtual const char* GetGroupLabel() { return GetLabel(); }
|
||||
|
||||
/**
|
||||
* Returns element count in case if a global handle retains
|
||||
* a subgraph by holding one of its nodes.
|
||||
*/
|
||||
virtual intptr_t GetElementCount() { return -1; }
|
||||
|
||||
/** Returns embedder's object size in bytes. */
|
||||
virtual intptr_t GetSizeInBytes() { return -1; }
|
||||
|
||||
protected:
|
||||
RetainedObjectInfo() {}
|
||||
virtual ~RetainedObjectInfo() {}
|
||||
|
||||
private:
|
||||
RetainedObjectInfo(const RetainedObjectInfo&);
|
||||
RetainedObjectInfo& operator=(const RetainedObjectInfo&);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A struct for exporting HeapStats data from V8, using "push" model.
|
||||
* See HeapProfiler::GetHeapStats.
|
||||
*/
|
||||
struct HeapStatsUpdate {
|
||||
HeapStatsUpdate(uint32_t index, uint32_t count, uint32_t size)
|
||||
: index(index), count(count), size(size) { }
|
||||
uint32_t index; // Index of the time interval that was changed.
|
||||
uint32_t count; // New value of count field for the interval with this index.
|
||||
uint32_t size; // New value of size field for the interval with this index.
|
||||
};
|
||||
|
||||
|
||||
} // namespace v8
|
||||
|
||||
|
||||
#endif // V8_V8_PROFILER_H_
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_V8_TEST_H_
|
||||
#define V8_V8_TEST_H_
|
||||
|
||||
#include "v8.h" // NOLINT(build/include)
|
||||
|
||||
/**
|
||||
* Testing support for the V8 JavaScript engine.
|
||||
*/
|
||||
namespace v8 {
|
||||
|
||||
class V8_EXPORT Testing {
|
||||
public:
|
||||
enum StressType {
|
||||
kStressTypeOpt,
|
||||
kStressTypeDeopt
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the type of stressing to do. The default if not set is kStressTypeOpt.
|
||||
*/
|
||||
static void SetStressRunType(StressType type);
|
||||
|
||||
/**
|
||||
* Get the number of runs of a given test that is required to get the full
|
||||
* stress coverage.
|
||||
*/
|
||||
static int GetStressRuns();
|
||||
|
||||
/**
|
||||
* Indicate the number of the run which is about to start. The value of run
|
||||
* should be between 0 and one less than the result from GetStressRuns()
|
||||
*/
|
||||
static void PrepareStressRun(int run);
|
||||
|
||||
/**
|
||||
* Force deoptimization of all functions.
|
||||
*/
|
||||
static void DeoptimizeAll(Isolate* isolate);
|
||||
};
|
||||
|
||||
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_V8_TEST_H_
|
||||
|
|
@ -0,0 +1,655 @@
|
|||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_UTIL_H_
|
||||
#define V8_UTIL_H_
|
||||
|
||||
#include "v8.h" // NOLINT(build/include)
|
||||
#include <assert.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* Support for Persistent containers.
|
||||
*
|
||||
* C++11 embedders can use STL containers with Global values,
|
||||
* but pre-C++11 does not support the required move semantic and hence
|
||||
* may want these container classes.
|
||||
*/
|
||||
namespace v8 {
|
||||
|
||||
typedef uintptr_t PersistentContainerValue;
|
||||
static const uintptr_t kPersistentContainerNotFound = 0;
|
||||
enum PersistentContainerCallbackType {
|
||||
kNotWeak,
|
||||
// These correspond to v8::WeakCallbackType
|
||||
kWeakWithParameter,
|
||||
kWeakWithInternalFields,
|
||||
kWeak = kWeakWithParameter // For backwards compatibility. Deprecate.
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A default trait implemenation for PersistentValueMap which uses std::map
|
||||
* as a backing map.
|
||||
*
|
||||
* Users will have to implement their own weak callbacks & dispose traits.
|
||||
*/
|
||||
template<typename K, typename V>
|
||||
class StdMapTraits {
|
||||
public:
|
||||
// STL map & related:
|
||||
typedef std::map<K, PersistentContainerValue> Impl;
|
||||
typedef typename Impl::iterator Iterator;
|
||||
|
||||
static bool Empty(Impl* impl) { return impl->empty(); }
|
||||
static size_t Size(Impl* impl) { return impl->size(); }
|
||||
static void Swap(Impl& a, Impl& b) { std::swap(a, b); } // NOLINT
|
||||
static Iterator Begin(Impl* impl) { return impl->begin(); }
|
||||
static Iterator End(Impl* impl) { return impl->end(); }
|
||||
static K Key(Iterator it) { return it->first; }
|
||||
static PersistentContainerValue Value(Iterator it) { return it->second; }
|
||||
static PersistentContainerValue Set(Impl* impl, K key,
|
||||
PersistentContainerValue value) {
|
||||
std::pair<Iterator, bool> res = impl->insert(std::make_pair(key, value));
|
||||
PersistentContainerValue old_value = kPersistentContainerNotFound;
|
||||
if (!res.second) {
|
||||
old_value = res.first->second;
|
||||
res.first->second = value;
|
||||
}
|
||||
return old_value;
|
||||
}
|
||||
static PersistentContainerValue Get(Impl* impl, K key) {
|
||||
Iterator it = impl->find(key);
|
||||
if (it == impl->end()) return kPersistentContainerNotFound;
|
||||
return it->second;
|
||||
}
|
||||
static PersistentContainerValue Remove(Impl* impl, K key) {
|
||||
Iterator it = impl->find(key);
|
||||
if (it == impl->end()) return kPersistentContainerNotFound;
|
||||
PersistentContainerValue value = it->second;
|
||||
impl->erase(it);
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A default trait implementation for PersistentValueMap, which inherits
|
||||
* a std:map backing map from StdMapTraits and holds non-weak persistent
|
||||
* objects and has no special Dispose handling.
|
||||
*
|
||||
* You should not derive from this class, since MapType depends on the
|
||||
* surrounding class, and hence a subclass cannot simply inherit the methods.
|
||||
*/
|
||||
template<typename K, typename V>
|
||||
class DefaultPersistentValueMapTraits : public StdMapTraits<K, V> {
|
||||
public:
|
||||
// Weak callback & friends:
|
||||
static const PersistentContainerCallbackType kCallbackType = kNotWeak;
|
||||
typedef PersistentValueMap<K, V, DefaultPersistentValueMapTraits<K, V> >
|
||||
MapType;
|
||||
typedef void WeakCallbackDataType;
|
||||
|
||||
static WeakCallbackDataType* WeakCallbackParameter(
|
||||
MapType* map, const K& key, Local<V> value) {
|
||||
return NULL;
|
||||
}
|
||||
static MapType* MapFromWeakCallbackInfo(
|
||||
const WeakCallbackInfo<WeakCallbackDataType>& data) {
|
||||
return NULL;
|
||||
}
|
||||
static K KeyFromWeakCallbackInfo(
|
||||
const WeakCallbackInfo<WeakCallbackDataType>& data) {
|
||||
return K();
|
||||
}
|
||||
static void DisposeCallbackData(WeakCallbackDataType* data) { }
|
||||
static void Dispose(Isolate* isolate, Global<V> value, K key) {}
|
||||
};
|
||||
|
||||
|
||||
template <typename K, typename V>
|
||||
class DefaultGlobalMapTraits : public StdMapTraits<K, V> {
|
||||
private:
|
||||
template <typename T>
|
||||
struct RemovePointer;
|
||||
|
||||
public:
|
||||
// Weak callback & friends:
|
||||
static const PersistentContainerCallbackType kCallbackType = kNotWeak;
|
||||
typedef GlobalValueMap<K, V, DefaultGlobalMapTraits<K, V> > MapType;
|
||||
typedef void WeakCallbackDataType;
|
||||
|
||||
static WeakCallbackDataType* WeakCallbackParameter(MapType* map, const K& key,
|
||||
Local<V> value) {
|
||||
return nullptr;
|
||||
}
|
||||
static MapType* MapFromWeakCallbackInfo(
|
||||
const WeakCallbackInfo<WeakCallbackDataType>& data) {
|
||||
return nullptr;
|
||||
}
|
||||
static K KeyFromWeakCallbackInfo(
|
||||
const WeakCallbackInfo<WeakCallbackDataType>& data) {
|
||||
return K();
|
||||
}
|
||||
static void DisposeCallbackData(WeakCallbackDataType* data) {}
|
||||
static void OnWeakCallback(
|
||||
const WeakCallbackInfo<WeakCallbackDataType>& data) {}
|
||||
static void Dispose(Isolate* isolate, Global<V> value, K key) {}
|
||||
// This is a second pass callback, so SetSecondPassCallback cannot be called.
|
||||
static void DisposeWeak(const WeakCallbackInfo<WeakCallbackDataType>& data) {}
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
struct RemovePointer<T*> {
|
||||
typedef T Type;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A map wrapper that allows using Global as a mapped value.
|
||||
* C++11 embedders don't need this class, as they can use Global
|
||||
* directly in std containers.
|
||||
*
|
||||
* The map relies on a backing map, whose type and accessors are described
|
||||
* by the Traits class. The backing map will handle values of type
|
||||
* PersistentContainerValue, with all conversion into and out of V8
|
||||
* handles being transparently handled by this class.
|
||||
*/
|
||||
template <typename K, typename V, typename Traits>
|
||||
class PersistentValueMapBase {
|
||||
public:
|
||||
Isolate* GetIsolate() { return isolate_; }
|
||||
|
||||
/**
|
||||
* Return size of the map.
|
||||
*/
|
||||
size_t Size() { return Traits::Size(&impl_); }
|
||||
|
||||
/**
|
||||
* Return whether the map holds weak persistents.
|
||||
*/
|
||||
bool IsWeak() { return Traits::kCallbackType != kNotWeak; }
|
||||
|
||||
/**
|
||||
* Get value stored in map.
|
||||
*/
|
||||
Local<V> Get(const K& key) {
|
||||
return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, key)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a value is contained in the map.
|
||||
*/
|
||||
bool Contains(const K& key) {
|
||||
return Traits::Get(&impl_, key) != kPersistentContainerNotFound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value stored in map and set it in returnValue.
|
||||
* Return true if a value was found.
|
||||
*/
|
||||
bool SetReturnValue(const K& key,
|
||||
ReturnValue<Value> returnValue) {
|
||||
return SetReturnValueFromVal(&returnValue, Traits::Get(&impl_, key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Call Isolate::SetReference with the given parent and the map value.
|
||||
*/
|
||||
void SetReference(const K& key,
|
||||
const Persistent<Object>& parent) {
|
||||
GetIsolate()->SetReference(
|
||||
reinterpret_cast<internal::Object**>(parent.val_),
|
||||
reinterpret_cast<internal::Object**>(FromVal(Traits::Get(&impl_, key))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Call V8::RegisterExternallyReferencedObject with the map value for given
|
||||
* key.
|
||||
*/
|
||||
void RegisterExternallyReferencedObject(K& key) {
|
||||
assert(Contains(key));
|
||||
V8::RegisterExternallyReferencedObject(
|
||||
reinterpret_cast<internal::Object**>(FromVal(Traits::Get(&impl_, key))),
|
||||
reinterpret_cast<internal::Isolate*>(GetIsolate()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return value for key and remove it from the map.
|
||||
*/
|
||||
Global<V> Remove(const K& key) {
|
||||
return Release(Traits::Remove(&impl_, key)).Pass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverses the map repeatedly,
|
||||
* in case side effects of disposal cause insertions.
|
||||
**/
|
||||
void Clear() {
|
||||
typedef typename Traits::Iterator It;
|
||||
HandleScope handle_scope(isolate_);
|
||||
// TODO(dcarney): figure out if this swap and loop is necessary.
|
||||
while (!Traits::Empty(&impl_)) {
|
||||
typename Traits::Impl impl;
|
||||
Traits::Swap(impl_, impl);
|
||||
for (It i = Traits::Begin(&impl); i != Traits::End(&impl); ++i) {
|
||||
Traits::Dispose(isolate_, Release(Traits::Value(i)).Pass(),
|
||||
Traits::Key(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class for GetReference/SetWithReference. Do not use outside
|
||||
* that context.
|
||||
*/
|
||||
class PersistentValueReference {
|
||||
public:
|
||||
PersistentValueReference() : value_(kPersistentContainerNotFound) { }
|
||||
PersistentValueReference(const PersistentValueReference& other)
|
||||
: value_(other.value_) { }
|
||||
|
||||
Local<V> NewLocal(Isolate* isolate) const {
|
||||
return Local<V>::New(isolate, FromVal(value_));
|
||||
}
|
||||
bool IsEmpty() const {
|
||||
return value_ == kPersistentContainerNotFound;
|
||||
}
|
||||
template<typename T>
|
||||
bool SetReturnValue(ReturnValue<T> returnValue) {
|
||||
return SetReturnValueFromVal(&returnValue, value_);
|
||||
}
|
||||
void Reset() {
|
||||
value_ = kPersistentContainerNotFound;
|
||||
}
|
||||
void operator=(const PersistentValueReference& other) {
|
||||
value_ = other.value_;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class PersistentValueMapBase;
|
||||
friend class PersistentValueMap<K, V, Traits>;
|
||||
friend class GlobalValueMap<K, V, Traits>;
|
||||
|
||||
explicit PersistentValueReference(PersistentContainerValue value)
|
||||
: value_(value) { }
|
||||
|
||||
void operator=(PersistentContainerValue value) {
|
||||
value_ = value;
|
||||
}
|
||||
|
||||
PersistentContainerValue value_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a reference to a map value. This enables fast, repeated access
|
||||
* to a value stored in the map while the map remains unchanged.
|
||||
*
|
||||
* Careful: This is potentially unsafe, so please use with care.
|
||||
* The value will become invalid if the value for this key changes
|
||||
* in the underlying map, as a result of Set or Remove for the same
|
||||
* key; as a result of the weak callback for the same key; or as a
|
||||
* result of calling Clear() or destruction of the map.
|
||||
*/
|
||||
PersistentValueReference GetReference(const K& key) {
|
||||
return PersistentValueReference(Traits::Get(&impl_, key));
|
||||
}
|
||||
|
||||
protected:
|
||||
explicit PersistentValueMapBase(Isolate* isolate) : isolate_(isolate) {}
|
||||
|
||||
~PersistentValueMapBase() { Clear(); }
|
||||
|
||||
Isolate* isolate() { return isolate_; }
|
||||
typename Traits::Impl* impl() { return &impl_; }
|
||||
|
||||
static V* FromVal(PersistentContainerValue v) {
|
||||
return reinterpret_cast<V*>(v);
|
||||
}
|
||||
|
||||
static PersistentContainerValue ClearAndLeak(Global<V>* persistent) {
|
||||
V* v = persistent->val_;
|
||||
persistent->val_ = 0;
|
||||
return reinterpret_cast<PersistentContainerValue>(v);
|
||||
}
|
||||
|
||||
static PersistentContainerValue Leak(Global<V>* persistent) {
|
||||
return reinterpret_cast<PersistentContainerValue>(persistent->val_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a container value as Global and make sure the weak
|
||||
* callback is properly disposed of. All remove functionality should go
|
||||
* through this.
|
||||
*/
|
||||
static Global<V> Release(PersistentContainerValue v) {
|
||||
Global<V> p;
|
||||
p.val_ = FromVal(v);
|
||||
if (Traits::kCallbackType != kNotWeak && p.IsWeak()) {
|
||||
Traits::DisposeCallbackData(
|
||||
p.template ClearWeak<typename Traits::WeakCallbackDataType>());
|
||||
}
|
||||
return p.Pass();
|
||||
}
|
||||
|
||||
void RemoveWeak(const K& key) {
|
||||
Global<V> p;
|
||||
p.val_ = FromVal(Traits::Remove(&impl_, key));
|
||||
p.Reset();
|
||||
}
|
||||
|
||||
private:
|
||||
PersistentValueMapBase(PersistentValueMapBase&);
|
||||
void operator=(PersistentValueMapBase&);
|
||||
|
||||
static bool SetReturnValueFromVal(ReturnValue<Value>* returnValue,
|
||||
PersistentContainerValue value) {
|
||||
bool hasValue = value != kPersistentContainerNotFound;
|
||||
if (hasValue) {
|
||||
returnValue->SetInternal(
|
||||
*reinterpret_cast<internal::Object**>(FromVal(value)));
|
||||
}
|
||||
return hasValue;
|
||||
}
|
||||
|
||||
Isolate* isolate_;
|
||||
typename Traits::Impl impl_;
|
||||
};
|
||||
|
||||
|
||||
template <typename K, typename V, typename Traits>
|
||||
class PersistentValueMap : public PersistentValueMapBase<K, V, Traits> {
|
||||
public:
|
||||
explicit PersistentValueMap(Isolate* isolate)
|
||||
: PersistentValueMapBase<K, V, Traits>(isolate) {}
|
||||
|
||||
typedef
|
||||
typename PersistentValueMapBase<K, V, Traits>::PersistentValueReference
|
||||
PersistentValueReference;
|
||||
|
||||
/**
|
||||
* Put value into map. Depending on Traits::kIsWeak, the value will be held
|
||||
* by the map strongly or weakly.
|
||||
* Returns old value as Global.
|
||||
*/
|
||||
Global<V> Set(const K& key, Local<V> value) {
|
||||
Global<V> persistent(this->isolate(), value);
|
||||
return SetUnique(key, &persistent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put value into map, like Set(const K&, Local<V>).
|
||||
*/
|
||||
Global<V> Set(const K& key, Global<V> value) {
|
||||
return SetUnique(key, &value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put the value into the map, and set the 'weak' callback when demanded
|
||||
* by the Traits class.
|
||||
*/
|
||||
Global<V> SetUnique(const K& key, Global<V>* persistent) {
|
||||
if (Traits::kCallbackType != kNotWeak) {
|
||||
Local<V> value(Local<V>::New(this->isolate(), *persistent));
|
||||
persistent->template SetWeak<typename Traits::WeakCallbackDataType>(
|
||||
Traits::WeakCallbackParameter(this, key, value), WeakCallback);
|
||||
}
|
||||
PersistentContainerValue old_value =
|
||||
Traits::Set(this->impl(), key, this->ClearAndLeak(persistent));
|
||||
return this->Release(old_value).Pass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a value into the map and update the reference.
|
||||
* Restrictions of GetReference apply here as well.
|
||||
*/
|
||||
Global<V> Set(const K& key, Global<V> value,
|
||||
PersistentValueReference* reference) {
|
||||
*reference = this->Leak(&value);
|
||||
return SetUnique(key, &value);
|
||||
}
|
||||
|
||||
private:
|
||||
static void WeakCallback(
|
||||
const WeakCallbackInfo<typename Traits::WeakCallbackDataType>& data) {
|
||||
if (Traits::kCallbackType != kNotWeak) {
|
||||
PersistentValueMap<K, V, Traits>* persistentValueMap =
|
||||
Traits::MapFromWeakCallbackInfo(data);
|
||||
K key = Traits::KeyFromWeakCallbackInfo(data);
|
||||
Traits::Dispose(data.GetIsolate(),
|
||||
persistentValueMap->Remove(key).Pass(), key);
|
||||
Traits::DisposeCallbackData(data.GetParameter());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename K, typename V, typename Traits>
|
||||
class GlobalValueMap : public PersistentValueMapBase<K, V, Traits> {
|
||||
public:
|
||||
explicit GlobalValueMap(Isolate* isolate)
|
||||
: PersistentValueMapBase<K, V, Traits>(isolate) {}
|
||||
|
||||
typedef
|
||||
typename PersistentValueMapBase<K, V, Traits>::PersistentValueReference
|
||||
PersistentValueReference;
|
||||
|
||||
/**
|
||||
* Put value into map. Depending on Traits::kIsWeak, the value will be held
|
||||
* by the map strongly or weakly.
|
||||
* Returns old value as Global.
|
||||
*/
|
||||
Global<V> Set(const K& key, Local<V> value) {
|
||||
Global<V> persistent(this->isolate(), value);
|
||||
return SetUnique(key, &persistent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put value into map, like Set(const K&, Local<V>).
|
||||
*/
|
||||
Global<V> Set(const K& key, Global<V> value) {
|
||||
return SetUnique(key, &value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put the value into the map, and set the 'weak' callback when demanded
|
||||
* by the Traits class.
|
||||
*/
|
||||
Global<V> SetUnique(const K& key, Global<V>* persistent) {
|
||||
if (Traits::kCallbackType != kNotWeak) {
|
||||
WeakCallbackType callback_type =
|
||||
Traits::kCallbackType == kWeakWithInternalFields
|
||||
? WeakCallbackType::kInternalFields
|
||||
: WeakCallbackType::kParameter;
|
||||
Local<V> value(Local<V>::New(this->isolate(), *persistent));
|
||||
persistent->template SetWeak<typename Traits::WeakCallbackDataType>(
|
||||
Traits::WeakCallbackParameter(this, key, value), OnWeakCallback,
|
||||
callback_type);
|
||||
}
|
||||
PersistentContainerValue old_value =
|
||||
Traits::Set(this->impl(), key, this->ClearAndLeak(persistent));
|
||||
return this->Release(old_value).Pass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a value into the map and update the reference.
|
||||
* Restrictions of GetReference apply here as well.
|
||||
*/
|
||||
Global<V> Set(const K& key, Global<V> value,
|
||||
PersistentValueReference* reference) {
|
||||
*reference = this->Leak(&value);
|
||||
return SetUnique(key, &value);
|
||||
}
|
||||
|
||||
private:
|
||||
static void OnWeakCallback(
|
||||
const WeakCallbackInfo<typename Traits::WeakCallbackDataType>& data) {
|
||||
if (Traits::kCallbackType != kNotWeak) {
|
||||
auto map = Traits::MapFromWeakCallbackInfo(data);
|
||||
K key = Traits::KeyFromWeakCallbackInfo(data);
|
||||
map->RemoveWeak(key);
|
||||
Traits::OnWeakCallback(data);
|
||||
data.SetSecondPassCallback(SecondWeakCallback);
|
||||
}
|
||||
}
|
||||
|
||||
static void SecondWeakCallback(
|
||||
const WeakCallbackInfo<typename Traits::WeakCallbackDataType>& data) {
|
||||
Traits::DisposeWeak(data);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A map that uses Global as value and std::map as the backing
|
||||
* implementation. Persistents are held non-weak.
|
||||
*
|
||||
* C++11 embedders don't need this class, as they can use
|
||||
* Global directly in std containers.
|
||||
*/
|
||||
template<typename K, typename V,
|
||||
typename Traits = DefaultPersistentValueMapTraits<K, V> >
|
||||
class StdPersistentValueMap : public PersistentValueMap<K, V, Traits> {
|
||||
public:
|
||||
explicit StdPersistentValueMap(Isolate* isolate)
|
||||
: PersistentValueMap<K, V, Traits>(isolate) {}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A map that uses Global as value and std::map as the backing
|
||||
* implementation. Globals are held non-weak.
|
||||
*
|
||||
* C++11 embedders don't need this class, as they can use
|
||||
* Global directly in std containers.
|
||||
*/
|
||||
template <typename K, typename V,
|
||||
typename Traits = DefaultGlobalMapTraits<K, V> >
|
||||
class StdGlobalValueMap : public GlobalValueMap<K, V, Traits> {
|
||||
public:
|
||||
explicit StdGlobalValueMap(Isolate* isolate)
|
||||
: GlobalValueMap<K, V, Traits>(isolate) {}
|
||||
};
|
||||
|
||||
|
||||
class DefaultPersistentValueVectorTraits {
|
||||
public:
|
||||
typedef std::vector<PersistentContainerValue> Impl;
|
||||
|
||||
static void Append(Impl* impl, PersistentContainerValue value) {
|
||||
impl->push_back(value);
|
||||
}
|
||||
static bool IsEmpty(const Impl* impl) {
|
||||
return impl->empty();
|
||||
}
|
||||
static size_t Size(const Impl* impl) {
|
||||
return impl->size();
|
||||
}
|
||||
static PersistentContainerValue Get(const Impl* impl, size_t i) {
|
||||
return (i < impl->size()) ? impl->at(i) : kPersistentContainerNotFound;
|
||||
}
|
||||
static void ReserveCapacity(Impl* impl, size_t capacity) {
|
||||
impl->reserve(capacity);
|
||||
}
|
||||
static void Clear(Impl* impl) {
|
||||
impl->clear();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A vector wrapper that safely stores Global values.
|
||||
* C++11 embedders don't need this class, as they can use Global
|
||||
* directly in std containers.
|
||||
*
|
||||
* This class relies on a backing vector implementation, whose type and methods
|
||||
* are described by the Traits class. The backing map will handle values of type
|
||||
* PersistentContainerValue, with all conversion into and out of V8
|
||||
* handles being transparently handled by this class.
|
||||
*/
|
||||
template<typename V, typename Traits = DefaultPersistentValueVectorTraits>
|
||||
class PersistentValueVector {
|
||||
public:
|
||||
explicit PersistentValueVector(Isolate* isolate) : isolate_(isolate) { }
|
||||
|
||||
~PersistentValueVector() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a value to the vector.
|
||||
*/
|
||||
void Append(Local<V> value) {
|
||||
Global<V> persistent(isolate_, value);
|
||||
Traits::Append(&impl_, ClearAndLeak(&persistent));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a persistent's value to the vector.
|
||||
*/
|
||||
void Append(Global<V> persistent) {
|
||||
Traits::Append(&impl_, ClearAndLeak(&persistent));
|
||||
}
|
||||
|
||||
/**
|
||||
* Are there any values in the vector?
|
||||
*/
|
||||
bool IsEmpty() const {
|
||||
return Traits::IsEmpty(&impl_);
|
||||
}
|
||||
|
||||
/**
|
||||
* How many elements are in the vector?
|
||||
*/
|
||||
size_t Size() const {
|
||||
return Traits::Size(&impl_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the i-th value in the vector.
|
||||
*/
|
||||
Local<V> Get(size_t index) const {
|
||||
return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, index)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all elements from the vector.
|
||||
*/
|
||||
void Clear() {
|
||||
size_t length = Traits::Size(&impl_);
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
Global<V> p;
|
||||
p.val_ = FromVal(Traits::Get(&impl_, i));
|
||||
}
|
||||
Traits::Clear(&impl_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reserve capacity in the vector.
|
||||
* (Efficiency gains depend on the backing implementation.)
|
||||
*/
|
||||
void ReserveCapacity(size_t capacity) {
|
||||
Traits::ReserveCapacity(&impl_, capacity);
|
||||
}
|
||||
|
||||
private:
|
||||
static PersistentContainerValue ClearAndLeak(Global<V>* persistent) {
|
||||
V* v = persistent->val_;
|
||||
persistent->val_ = 0;
|
||||
return reinterpret_cast<PersistentContainerValue>(v);
|
||||
}
|
||||
|
||||
static V* FromVal(PersistentContainerValue v) {
|
||||
return reinterpret_cast<V*>(v);
|
||||
}
|
||||
|
||||
Isolate* isolate_;
|
||||
typename Traits::Impl impl_;
|
||||
};
|
||||
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_UTIL_H
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright 2017 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* Compile-time constants.
|
||||
*
|
||||
* This header provides access to information about the value serializer at
|
||||
* compile time, without declaring or defining any symbols that require linking
|
||||
* to V8.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_V8_VALUE_SERIALIZER_VERSION_H_
|
||||
#define INCLUDE_V8_VALUE_SERIALIZER_VERSION_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace v8 {
|
||||
|
||||
constexpr uint32_t CurrentValueSerializerFormatVersion() { return 13; }
|
||||
|
||||
} // namespace v8
|
||||
|
||||
#endif // INCLUDE_V8_VALUE_SERIALIZER_VERSION_H_
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright 2017 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_VERSION_STRING_H_
|
||||
#define V8_VERSION_STRING_H_
|
||||
|
||||
#include "v8-version.h" // NOLINT(build/include)
|
||||
|
||||
// This is here rather than v8-version.h to keep that file simple and
|
||||
// machine-processable.
|
||||
|
||||
#if V8_IS_CANDIDATE_VERSION
|
||||
#define V8_CANDIDATE_STRING " (candidate)"
|
||||
#else
|
||||
#define V8_CANDIDATE_STRING ""
|
||||
#endif
|
||||
|
||||
#define V8_SX(x) #x
|
||||
#define V8_S(x) V8_SX(x)
|
||||
|
||||
#if V8_PATCH_LEVEL > 0
|
||||
#define V8_VERSION_STRING \
|
||||
V8_S(V8_MAJOR_VERSION) \
|
||||
"." V8_S(V8_MINOR_VERSION) "." V8_S(V8_BUILD_NUMBER) "." V8_S( \
|
||||
V8_PATCH_LEVEL) V8_CANDIDATE_STRING
|
||||
#else
|
||||
#define V8_VERSION_STRING \
|
||||
V8_S(V8_MAJOR_VERSION) \
|
||||
"." V8_S(V8_MINOR_VERSION) "." V8_S(V8_BUILD_NUMBER) V8_CANDIDATE_STRING
|
||||
#endif
|
||||
|
||||
#endif // V8_VERSION_STRING_H_
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2015 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_INCLUDE_VERSION_H_ // V8_VERSION_H_ conflicts with src/version.h
|
||||
#define V8_INCLUDE_VERSION_H_
|
||||
|
||||
// These macros define the version number for the current version.
|
||||
// NOTE these macros are used by some of the tool scripts and the build
|
||||
// system so their names cannot be changed without changing the scripts.
|
||||
#define V8_MAJOR_VERSION 6
|
||||
#define V8_MINOR_VERSION 0
|
||||
#define V8_BUILD_NUMBER 286
|
||||
#define V8_PATCH_LEVEL 52
|
||||
|
||||
// Use 1 for candidates and 0 otherwise.
|
||||
// (Boolean macro values are not supported by all preprocessors.)
|
||||
#define V8_IS_CANDIDATE_VERSION 0
|
||||
|
||||
#endif // V8_INCLUDE_VERSION_H_
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,428 @@
|
|||
// Copyright 2013 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8CONFIG_H_
|
||||
#define V8CONFIG_H_
|
||||
|
||||
// clang-format off
|
||||
|
||||
// Platform headers for feature detection below.
|
||||
#if defined(__ANDROID__)
|
||||
# include <sys/cdefs.h>
|
||||
#elif defined(__APPLE__)
|
||||
# include <TargetConditionals.h>
|
||||
#elif defined(__linux__)
|
||||
# include <features.h>
|
||||
#endif
|
||||
|
||||
|
||||
// This macro allows to test for the version of the GNU C library (or
|
||||
// a compatible C library that masquerades as glibc). It evaluates to
|
||||
// 0 if libc is not GNU libc or compatible.
|
||||
// Use like:
|
||||
// #if V8_GLIBC_PREREQ(2, 3)
|
||||
// ...
|
||||
// #endif
|
||||
#if defined(__GLIBC__) && defined(__GLIBC_MINOR__)
|
||||
# define V8_GLIBC_PREREQ(major, minor) \
|
||||
((__GLIBC__ * 100 + __GLIBC_MINOR__) >= ((major) * 100 + (minor)))
|
||||
#else
|
||||
# define V8_GLIBC_PREREQ(major, minor) 0
|
||||
#endif
|
||||
|
||||
|
||||
// This macro allows to test for the version of the GNU C++ compiler.
|
||||
// Note that this also applies to compilers that masquerade as GCC,
|
||||
// for example clang and the Intel C++ compiler for Linux.
|
||||
// Use like:
|
||||
// #if V8_GNUC_PREREQ(4, 3, 1)
|
||||
// ...
|
||||
// #endif
|
||||
#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
|
||||
# define V8_GNUC_PREREQ(major, minor, patchlevel) \
|
||||
((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= \
|
||||
((major) * 10000 + (minor) * 100 + (patchlevel)))
|
||||
#elif defined(__GNUC__) && defined(__GNUC_MINOR__)
|
||||
# define V8_GNUC_PREREQ(major, minor, patchlevel) \
|
||||
((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= \
|
||||
((major) * 10000 + (minor) * 100 + (patchlevel)))
|
||||
#else
|
||||
# define V8_GNUC_PREREQ(major, minor, patchlevel) 0
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Operating system detection
|
||||
//
|
||||
// V8_OS_ANDROID - Android
|
||||
// V8_OS_BSD - BSDish (Mac OS X, Net/Free/Open/DragonFlyBSD)
|
||||
// V8_OS_CYGWIN - Cygwin
|
||||
// V8_OS_DRAGONFLYBSD - DragonFlyBSD
|
||||
// V8_OS_FREEBSD - FreeBSD
|
||||
// V8_OS_LINUX - Linux
|
||||
// V8_OS_MACOSX - Mac OS X
|
||||
// V8_OS_NETBSD - NetBSD
|
||||
// V8_OS_OPENBSD - OpenBSD
|
||||
// V8_OS_POSIX - POSIX compatible (mostly everything except Windows)
|
||||
// V8_OS_QNX - QNX Neutrino
|
||||
// V8_OS_SOLARIS - Sun Solaris and OpenSolaris
|
||||
// V8_OS_AIX - AIX
|
||||
// V8_OS_WIN - Microsoft Windows
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
# define V8_OS_ANDROID 1
|
||||
# define V8_OS_LINUX 1
|
||||
# define V8_OS_POSIX 1
|
||||
#elif defined(__APPLE__)
|
||||
# define V8_OS_BSD 1
|
||||
# define V8_OS_MACOSX 1
|
||||
# define V8_OS_POSIX 1
|
||||
#elif defined(__CYGWIN__)
|
||||
# define V8_OS_CYGWIN 1
|
||||
# define V8_OS_POSIX 1
|
||||
#elif defined(__linux__)
|
||||
# define V8_OS_LINUX 1
|
||||
# define V8_OS_POSIX 1
|
||||
#elif defined(__sun)
|
||||
# define V8_OS_POSIX 1
|
||||
# define V8_OS_SOLARIS 1
|
||||
#elif defined(_AIX)
|
||||
#define V8_OS_POSIX 1
|
||||
#define V8_OS_AIX 1
|
||||
#elif defined(__FreeBSD__)
|
||||
# define V8_OS_BSD 1
|
||||
# define V8_OS_FREEBSD 1
|
||||
# define V8_OS_POSIX 1
|
||||
#elif defined(__DragonFly__)
|
||||
# define V8_OS_BSD 1
|
||||
# define V8_OS_DRAGONFLYBSD 1
|
||||
# define V8_OS_POSIX 1
|
||||
#elif defined(__NetBSD__)
|
||||
# define V8_OS_BSD 1
|
||||
# define V8_OS_NETBSD 1
|
||||
# define V8_OS_POSIX 1
|
||||
#elif defined(__OpenBSD__)
|
||||
# define V8_OS_BSD 1
|
||||
# define V8_OS_OPENBSD 1
|
||||
# define V8_OS_POSIX 1
|
||||
#elif defined(__QNXNTO__)
|
||||
# define V8_OS_POSIX 1
|
||||
# define V8_OS_QNX 1
|
||||
#elif defined(_WIN32)
|
||||
# define V8_OS_WIN 1
|
||||
#endif
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// C library detection
|
||||
//
|
||||
// V8_LIBC_MSVCRT - MSVC libc
|
||||
// V8_LIBC_BIONIC - Bionic libc
|
||||
// V8_LIBC_BSD - BSD libc derivate
|
||||
// V8_LIBC_GLIBC - GNU C library
|
||||
// V8_LIBC_UCLIBC - uClibc
|
||||
//
|
||||
// Note that testing for libc must be done using #if not #ifdef. For example,
|
||||
// to test for the GNU C library, use:
|
||||
// #if V8_LIBC_GLIBC
|
||||
// ...
|
||||
// #endif
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# define V8_LIBC_MSVCRT 1
|
||||
#elif defined(__BIONIC__)
|
||||
# define V8_LIBC_BIONIC 1
|
||||
# define V8_LIBC_BSD 1
|
||||
#elif defined(__UCLIBC__)
|
||||
// Must test for UCLIBC before GLIBC, as UCLIBC pretends to be GLIBC.
|
||||
# define V8_LIBC_UCLIBC 1
|
||||
#elif defined(__GLIBC__) || defined(__GNU_LIBRARY__)
|
||||
# define V8_LIBC_GLIBC 1
|
||||
#else
|
||||
# define V8_LIBC_BSD V8_OS_BSD
|
||||
#endif
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Compiler detection
|
||||
//
|
||||
// V8_CC_GNU - GCC, or clang in gcc mode
|
||||
// V8_CC_INTEL - Intel C++
|
||||
// V8_CC_MINGW - Minimalist GNU for Windows
|
||||
// V8_CC_MINGW32 - Minimalist GNU for Windows (mingw32)
|
||||
// V8_CC_MINGW64 - Minimalist GNU for Windows (mingw-w64)
|
||||
// V8_CC_MSVC - Microsoft Visual C/C++, or clang in cl.exe mode
|
||||
//
|
||||
// C++11 feature detection
|
||||
//
|
||||
// V8_HAS_CXX11_ALIGNAS - alignas specifier supported
|
||||
// V8_HAS_CXX11_ALIGNOF - alignof(type) operator supported
|
||||
//
|
||||
// Compiler-specific feature detection
|
||||
//
|
||||
// V8_HAS___ALIGNOF - __alignof(type) operator supported
|
||||
// V8_HAS___ALIGNOF__ - __alignof__(type) operator supported
|
||||
// V8_HAS_ATTRIBUTE_ALIGNED - __attribute__((aligned(n))) supported
|
||||
// V8_HAS_ATTRIBUTE_ALWAYS_INLINE - __attribute__((always_inline))
|
||||
// supported
|
||||
// V8_HAS_ATTRIBUTE_DEPRECATED - __attribute__((deprecated)) supported
|
||||
// V8_HAS_ATTRIBUTE_NOINLINE - __attribute__((noinline)) supported
|
||||
// V8_HAS_ATTRIBUTE_NORETURN - __attribute__((noreturn)) supported
|
||||
// V8_HAS_ATTRIBUTE_UNUSED - __attribute__((unused)) supported
|
||||
// V8_HAS_ATTRIBUTE_VISIBILITY - __attribute__((visibility)) supported
|
||||
// V8_HAS_ATTRIBUTE_WARN_UNUSED_RESULT - __attribute__((warn_unused_result))
|
||||
// supported
|
||||
// V8_HAS_BUILTIN_CLZ - __builtin_clz() supported
|
||||
// V8_HAS_BUILTIN_CTZ - __builtin_ctz() supported
|
||||
// V8_HAS_BUILTIN_EXPECT - __builtin_expect() supported
|
||||
// V8_HAS_BUILTIN_FRAME_ADDRESS - __builtin_frame_address() supported
|
||||
// V8_HAS_BUILTIN_POPCOUNT - __builtin_popcount() supported
|
||||
// V8_HAS_BUILTIN_SADD_OVERFLOW - __builtin_sadd_overflow() supported
|
||||
// V8_HAS_BUILTIN_SSUB_OVERFLOW - __builtin_ssub_overflow() supported
|
||||
// V8_HAS_BUILTIN_UADD_OVERFLOW - __builtin_uadd_overflow() supported
|
||||
// V8_HAS_DECLSPEC_ALIGN - __declspec(align(n)) supported
|
||||
// V8_HAS_DECLSPEC_DEPRECATED - __declspec(deprecated) supported
|
||||
// V8_HAS_DECLSPEC_NOINLINE - __declspec(noinline) supported
|
||||
// V8_HAS_DECLSPEC_SELECTANY - __declspec(selectany) supported
|
||||
// V8_HAS_DECLSPEC_NORETURN - __declspec(noreturn) supported
|
||||
// V8_HAS___FORCEINLINE - __forceinline supported
|
||||
//
|
||||
// Note that testing for compilers and/or features must be done using #if
|
||||
// not #ifdef. For example, to test for Intel C++ Compiler, use:
|
||||
// #if V8_CC_INTEL
|
||||
// ...
|
||||
// #endif
|
||||
|
||||
#if defined(__clang__)
|
||||
|
||||
#if defined(__GNUC__) // Clang in gcc mode.
|
||||
# define V8_CC_GNU 1
|
||||
#endif
|
||||
|
||||
// Clang defines __alignof__ as alias for __alignof
|
||||
# define V8_HAS___ALIGNOF 1
|
||||
# define V8_HAS___ALIGNOF__ V8_HAS___ALIGNOF
|
||||
|
||||
# define V8_HAS_ATTRIBUTE_ALIGNED (__has_attribute(aligned))
|
||||
# define V8_HAS_ATTRIBUTE_ALWAYS_INLINE (__has_attribute(always_inline))
|
||||
# define V8_HAS_ATTRIBUTE_DEPRECATED (__has_attribute(deprecated))
|
||||
# define V8_HAS_ATTRIBUTE_NOINLINE (__has_attribute(noinline))
|
||||
# define V8_HAS_ATTRIBUTE_NORETURN (__has_attribute(noreturn))
|
||||
# define V8_HAS_ATTRIBUTE_UNUSED (__has_attribute(unused))
|
||||
# define V8_HAS_ATTRIBUTE_VISIBILITY (__has_attribute(visibility))
|
||||
# define V8_HAS_ATTRIBUTE_WARN_UNUSED_RESULT \
|
||||
(__has_attribute(warn_unused_result))
|
||||
|
||||
# define V8_HAS_BUILTIN_CLZ (__has_builtin(__builtin_clz))
|
||||
# define V8_HAS_BUILTIN_CTZ (__has_builtin(__builtin_ctz))
|
||||
# define V8_HAS_BUILTIN_EXPECT (__has_builtin(__builtin_expect))
|
||||
# define V8_HAS_BUILTIN_FRAME_ADDRESS (__has_builtin(__builtin_frame_address))
|
||||
# define V8_HAS_BUILTIN_POPCOUNT (__has_builtin(__builtin_popcount))
|
||||
# define V8_HAS_BUILTIN_SADD_OVERFLOW (__has_builtin(__builtin_sadd_overflow))
|
||||
# define V8_HAS_BUILTIN_SSUB_OVERFLOW (__has_builtin(__builtin_ssub_overflow))
|
||||
# define V8_HAS_BUILTIN_UADD_OVERFLOW (__has_builtin(__builtin_uadd_overflow))
|
||||
|
||||
# define V8_HAS_CXX11_ALIGNAS (__has_feature(cxx_alignas))
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
|
||||
# define V8_CC_GNU 1
|
||||
# if defined(__INTEL_COMPILER) // Intel C++ also masquerades as GCC 3.2.0
|
||||
# define V8_CC_INTEL 1
|
||||
# endif
|
||||
# if defined(__MINGW32__)
|
||||
# define V8_CC_MINGW32 1
|
||||
# endif
|
||||
# if defined(__MINGW64__)
|
||||
# define V8_CC_MINGW64 1
|
||||
# endif
|
||||
# define V8_CC_MINGW (V8_CC_MINGW32 || V8_CC_MINGW64)
|
||||
|
||||
# define V8_HAS___ALIGNOF__ (V8_GNUC_PREREQ(4, 3, 0))
|
||||
|
||||
# define V8_HAS_ATTRIBUTE_ALIGNED (V8_GNUC_PREREQ(2, 95, 0))
|
||||
// always_inline is available in gcc 4.0 but not very reliable until 4.4.
|
||||
// Works around "sorry, unimplemented: inlining failed" build errors with
|
||||
// older compilers.
|
||||
# define V8_HAS_ATTRIBUTE_ALWAYS_INLINE (V8_GNUC_PREREQ(4, 4, 0))
|
||||
# define V8_HAS_ATTRIBUTE_DEPRECATED (V8_GNUC_PREREQ(3, 4, 0))
|
||||
# define V8_HAS_ATTRIBUTE_DEPRECATED_MESSAGE (V8_GNUC_PREREQ(4, 5, 0))
|
||||
# define V8_HAS_ATTRIBUTE_NOINLINE (V8_GNUC_PREREQ(3, 4, 0))
|
||||
# define V8_HAS_ATTRIBUTE_NORETURN (V8_GNUC_PREREQ(2, 5, 0))
|
||||
# define V8_HAS_ATTRIBUTE_UNUSED (V8_GNUC_PREREQ(2, 95, 0))
|
||||
# define V8_HAS_ATTRIBUTE_VISIBILITY (V8_GNUC_PREREQ(4, 3, 0))
|
||||
# define V8_HAS_ATTRIBUTE_WARN_UNUSED_RESULT \
|
||||
(!V8_CC_INTEL && V8_GNUC_PREREQ(4, 1, 0))
|
||||
|
||||
# define V8_HAS_BUILTIN_CLZ (V8_GNUC_PREREQ(3, 4, 0))
|
||||
# define V8_HAS_BUILTIN_CTZ (V8_GNUC_PREREQ(3, 4, 0))
|
||||
# define V8_HAS_BUILTIN_EXPECT (V8_GNUC_PREREQ(2, 96, 0))
|
||||
# define V8_HAS_BUILTIN_FRAME_ADDRESS (V8_GNUC_PREREQ(2, 96, 0))
|
||||
# define V8_HAS_BUILTIN_POPCOUNT (V8_GNUC_PREREQ(3, 4, 0))
|
||||
|
||||
# if __cplusplus >= 201103L
|
||||
# define V8_HAS_CXX11_ALIGNAS (V8_GNUC_PREREQ(4, 8, 0))
|
||||
# define V8_HAS_CXX11_ALIGNOF (V8_GNUC_PREREQ(4, 8, 0))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define V8_CC_MSVC 1
|
||||
# define V8_HAS___ALIGNOF 1
|
||||
|
||||
# define V8_HAS_DECLSPEC_ALIGN 1
|
||||
# define V8_HAS_DECLSPEC_DEPRECATED 1
|
||||
# define V8_HAS_DECLSPEC_NOINLINE 1
|
||||
# define V8_HAS_DECLSPEC_SELECTANY 1
|
||||
# define V8_HAS_DECLSPEC_NORETURN 1
|
||||
|
||||
# define V8_HAS___FORCEINLINE 1
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Helper macros
|
||||
|
||||
// A macro used to make better inlining. Don't bother for debug builds.
|
||||
// Use like:
|
||||
// V8_INLINE int GetZero() { return 0; }
|
||||
#if !defined(DEBUG) && V8_HAS_ATTRIBUTE_ALWAYS_INLINE
|
||||
# define V8_INLINE inline __attribute__((always_inline))
|
||||
#elif !defined(DEBUG) && V8_HAS___FORCEINLINE
|
||||
# define V8_INLINE __forceinline
|
||||
#else
|
||||
# define V8_INLINE inline
|
||||
#endif
|
||||
|
||||
|
||||
// A macro used to tell the compiler to never inline a particular function.
|
||||
// Don't bother for debug builds.
|
||||
// Use like:
|
||||
// V8_NOINLINE int GetMinusOne() { return -1; }
|
||||
#if !defined(DEBUG) && V8_HAS_ATTRIBUTE_NOINLINE
|
||||
# define V8_NOINLINE __attribute__((noinline))
|
||||
#elif !defined(DEBUG) && V8_HAS_DECLSPEC_NOINLINE
|
||||
# define V8_NOINLINE __declspec(noinline)
|
||||
#else
|
||||
# define V8_NOINLINE /* NOT SUPPORTED */
|
||||
#endif
|
||||
|
||||
|
||||
// A macro used to tell the compiler that a particular function never returns.
|
||||
// Use like:
|
||||
// V8_NORETURN void MyAbort() { abort(); }
|
||||
#if V8_HAS_ATTRIBUTE_NORETURN
|
||||
# define V8_NORETURN __attribute__((noreturn))
|
||||
#elif V8_HAS_DECLSPEC_NORETURN
|
||||
# define V8_NORETURN __declspec(noreturn)
|
||||
#else
|
||||
# define V8_NORETURN /* NOT SUPPORTED */
|
||||
#endif
|
||||
|
||||
|
||||
// A macro (V8_DEPRECATED) to mark classes or functions as deprecated.
|
||||
#if defined(V8_DEPRECATION_WARNINGS) && V8_HAS_ATTRIBUTE_DEPRECATED_MESSAGE
|
||||
#define V8_DEPRECATED(message, declarator) \
|
||||
declarator __attribute__((deprecated(message)))
|
||||
#elif defined(V8_DEPRECATION_WARNINGS) && V8_HAS_ATTRIBUTE_DEPRECATED
|
||||
#define V8_DEPRECATED(message, declarator) \
|
||||
declarator __attribute__((deprecated))
|
||||
#elif defined(V8_DEPRECATION_WARNINGS) && V8_HAS_DECLSPEC_DEPRECATED
|
||||
#define V8_DEPRECATED(message, declarator) __declspec(deprecated) declarator
|
||||
#else
|
||||
#define V8_DEPRECATED(message, declarator) declarator
|
||||
#endif
|
||||
|
||||
|
||||
// A macro (V8_DEPRECATE_SOON) to make it easier to see what will be deprecated.
|
||||
#if defined(V8_IMMINENT_DEPRECATION_WARNINGS) && \
|
||||
V8_HAS_ATTRIBUTE_DEPRECATED_MESSAGE
|
||||
#define V8_DEPRECATE_SOON(message, declarator) \
|
||||
declarator __attribute__((deprecated(message)))
|
||||
#elif defined(V8_IMMINENT_DEPRECATION_WARNINGS) && V8_HAS_ATTRIBUTE_DEPRECATED
|
||||
#define V8_DEPRECATE_SOON(message, declarator) \
|
||||
declarator __attribute__((deprecated))
|
||||
#elif defined(V8_IMMINENT_DEPRECATION_WARNINGS) && V8_HAS_DECLSPEC_DEPRECATED
|
||||
#define V8_DEPRECATE_SOON(message, declarator) __declspec(deprecated) declarator
|
||||
#else
|
||||
#define V8_DEPRECATE_SOON(message, declarator) declarator
|
||||
#endif
|
||||
|
||||
|
||||
// A macro to provide the compiler with branch prediction information.
|
||||
#if V8_HAS_BUILTIN_EXPECT
|
||||
# define V8_UNLIKELY(condition) (__builtin_expect(!!(condition), 0))
|
||||
# define V8_LIKELY(condition) (__builtin_expect(!!(condition), 1))
|
||||
#else
|
||||
# define V8_UNLIKELY(condition) (condition)
|
||||
# define V8_LIKELY(condition) (condition)
|
||||
#endif
|
||||
|
||||
|
||||
// This macro allows to specify memory alignment for structs, classes, etc.
|
||||
// Use like:
|
||||
// class V8_ALIGNED(16) MyClass { ... };
|
||||
// V8_ALIGNED(32) int array[42];
|
||||
#if V8_HAS_CXX11_ALIGNAS
|
||||
# define V8_ALIGNED(n) alignas(n)
|
||||
#elif V8_HAS_ATTRIBUTE_ALIGNED
|
||||
# define V8_ALIGNED(n) __attribute__((aligned(n)))
|
||||
#elif V8_HAS_DECLSPEC_ALIGN
|
||||
# define V8_ALIGNED(n) __declspec(align(n))
|
||||
#else
|
||||
# define V8_ALIGNED(n) /* NOT SUPPORTED */
|
||||
#endif
|
||||
|
||||
|
||||
// This macro is similar to V8_ALIGNED(), but takes a type instead of size
|
||||
// in bytes. If the compiler does not supports using the alignment of the
|
||||
// |type|, it will align according to the |alignment| instead. For example,
|
||||
// Visual Studio C++ cannot combine __declspec(align) and __alignof. The
|
||||
// |alignment| must be a literal that is used as a kind of worst-case fallback
|
||||
// alignment.
|
||||
// Use like:
|
||||
// struct V8_ALIGNAS(AnotherClass, 16) NewClass { ... };
|
||||
// V8_ALIGNAS(double, 8) int array[100];
|
||||
#if V8_HAS_CXX11_ALIGNAS
|
||||
# define V8_ALIGNAS(type, alignment) alignas(type)
|
||||
#elif V8_HAS___ALIGNOF__ && V8_HAS_ATTRIBUTE_ALIGNED
|
||||
# define V8_ALIGNAS(type, alignment) __attribute__((aligned(__alignof__(type))))
|
||||
#else
|
||||
# define V8_ALIGNAS(type, alignment) V8_ALIGNED(alignment)
|
||||
#endif
|
||||
|
||||
|
||||
// This macro returns alignment in bytes (an integer power of two) required for
|
||||
// any instance of the given type, which is either complete type, an array type,
|
||||
// or a reference type.
|
||||
// Use like:
|
||||
// size_t alignment = V8_ALIGNOF(double);
|
||||
#if V8_HAS_CXX11_ALIGNOF
|
||||
# define V8_ALIGNOF(type) alignof(type)
|
||||
#elif V8_HAS___ALIGNOF
|
||||
# define V8_ALIGNOF(type) __alignof(type)
|
||||
#elif V8_HAS___ALIGNOF__
|
||||
# define V8_ALIGNOF(type) __alignof__(type)
|
||||
#else
|
||||
// Note that alignment of a type within a struct can be less than the
|
||||
// alignment of the type stand-alone (because of ancient ABIs), so this
|
||||
// should only be used as a last resort.
|
||||
namespace v8 { template <typename T> class AlignOfHelper { char c; T t; }; }
|
||||
# define V8_ALIGNOF(type) (sizeof(::v8::AlignOfHelper<type>) - sizeof(type))
|
||||
#endif
|
||||
|
||||
// Annotate a function indicating the caller must examine the return value.
|
||||
// Use like:
|
||||
// int foo() WARN_UNUSED_RESULT;
|
||||
#if V8_HAS_ATTRIBUTE_WARN_UNUSED_RESULT
|
||||
#define V8_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
||||
#else
|
||||
#define V8_WARN_UNUSED_RESULT /* NOT SUPPORTED */
|
||||
#endif
|
||||
|
||||
// clang-format on
|
||||
|
||||
#endif // V8CONFIG_H_
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue