Optimize lseek in the tell case.

`lseek(x, 0, SEEK_CUR)` has no effect other than to return the current
file offset. The patch here uses a macro with `__builtin_constant_p` to
recognize this case and rewrite it to a library call that uses `fd_tell`
rather than `fd_seek`, so that programs that don't need actual seeking
don't end up importing `fd_seek`.

This is also the first usage of `__wasi_fd_tell` in WASI libc, so this
adds it to undefined-symbols.txt.
This commit is contained in:
Dan Gohman 2019-04-29 12:53:18 -07:00
parent 9f103c2883
commit cf366c06d1
7 changed files with 46 additions and 0 deletions

View File

@ -241,6 +241,7 @@ __wasilibc_init_preopen
__wasilibc_register_preopened_fd
__wasilibc_rmdirat
__wasilibc_rmfileat
__wasilibc_tell
__wcscoll_l
__wcsftime_l
__wcsxfrm_l

View File

@ -3816,6 +3816,7 @@
#define logb(x) __tg_real(logb, (x))
#define lrint(x) __tg_real_nocast(lrint, (x))
#define lround(x) __tg_real_nocast(lround, (x))
#define lseek(fd,offset,whence) ({ off_t __f = (fd); off_t __o = (offset); off_t __w = (whence); __builtin_constant_p((offset)) && __builtin_constant_p((whence)) && __o == 0 && __w == SEEK_CUR ? __wasilibc_tell(__f) : lseek(__f, __o, __w); })
#define lseek64 lseek
#define lstat64 lstat
#define major(x) ((unsigned)( (((x)>>31>>1) & 0xfffff000) | (((x)>>8) & 0x00000fff) ))

View File

@ -47,6 +47,7 @@ __wasi_fd_readdir
__wasi_fd_renumber
__wasi_fd_seek
__wasi_fd_sync
__wasi_fd_tell
__wasi_fd_write
__wasi_path_create_directory
__wasi_path_filestat_get

View File

@ -11,7 +11,11 @@ static_assert(SEEK_CUR == __WASI_WHENCE_CUR, "Value mismatch");
static_assert(SEEK_END == __WASI_WHENCE_END, "Value mismatch");
static_assert(SEEK_SET == __WASI_WHENCE_SET, "Value mismatch");
#ifdef __wasilibc_unmodified_upstream /* Optimize the readonly case of lseek */
off_t lseek(int fildes, off_t offset, int whence) {
#else
off_t (lseek)(int fildes, off_t offset, int whence) {
#endif
__wasi_filesize_t new_offset;
__wasi_errno_t error =
__wasi_fd_seek(fildes, offset, whence, &new_offset);

View File

@ -1,6 +1,8 @@
#ifndef __wasi_libc_h
#define __wasi_libc_h
#include <__typedef_off_t.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -10,6 +12,7 @@ int __wasilibc_register_preopened_fd(int fd, const char *path);
int __wasilibc_fd_renumber(int fd, int newfd);
int __wasilibc_rmfileat(int fd, const char *path);
int __wasilibc_rmdirat(int fd, const char *path);
off_t __wasilibc_tell(int fd);
#ifdef __cplusplus
}

View File

@ -0,0 +1,14 @@
#include <wasi/core.h>
#include <errno.h>
off_t __wasilibc_tell(int fildes) {
__wasi_filesize_t offset;
__wasi_errno_t error = __wasi_fd_tell(fildes, &offset);
if (error != 0) {
// lseek returns ESPIPE on when called on a pipe, socket, or fifo,
// which on WASI would translate into ENOTCAPABLE.
errno = error == ENOTCAPABLE ? ESPIPE : error;
return -1;
}
return offset;
}

View File

@ -53,6 +53,28 @@ int dup2(int, int);
int dup3(int, int, int);
#endif
off_t lseek(int, off_t, int);
#ifdef __wasilibc_unmodified_upstream /* Optimize the readonly case of lseek */
#else
/*
* Optimize lseek in the case where it's just returning the current offset.
* This avoids importing `__wasi_fd_seek` altogether in many common cases.
*/
off_t __wasilibc_tell(int);
#define lseek(fd, offset, whence) \
({ \
off_t __f = (fd); \
off_t __o = (offset); \
off_t __w = (whence); \
__builtin_constant_p((offset)) && \
__builtin_constant_p((whence)) && \
__o == 0 && \
__w == SEEK_CUR \
? __wasilibc_tell(__f) \
: lseek(__f, __o, __w); \
})
#endif
int fsync(int);
int fdatasync(int);