From 5258785c81959109138ebeca613f12c277188abc Mon Sep 17 00:00:00 2001 From: Péter Szilágyi Date: Thu, 21 Dec 2017 13:56:11 +0200 Subject: cmd, core, eth/tracers: support fancier js tracing (#15516) * cmd, core, eth/tracers: support fancier js tracing * eth, internal/web3ext: rework trace API, concurrency, chain tracing * eth/tracers: add three more JavaScript tracers * eth/tracers, vendor: swap ottovm to duktape for tracing * core, eth, internal: finalize call tracer and needed extras * eth, tests: prestate tracer, call test suite, rewinding * vendor: fix windows builds for tracer js engine * vendor: temporary duktape fix * eth/tracers: fix up 4byte and evmdis tracer * vendor: pull in latest duktape with my upstream fixes * eth: fix some review comments * eth: rename rewind to reexec to make it more obvious * core/vm: terminate tracing using defers --- .../olebedev/go-duktape.v3/duk_alloc_pool.h | 223 +++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100755 vendor/gopkg.in/olebedev/go-duktape.v3/duk_alloc_pool.h (limited to 'vendor/gopkg.in/olebedev/go-duktape.v3/duk_alloc_pool.h') diff --git a/vendor/gopkg.in/olebedev/go-duktape.v3/duk_alloc_pool.h b/vendor/gopkg.in/olebedev/go-duktape.v3/duk_alloc_pool.h new file mode 100755 index 000000000..286ec0166 --- /dev/null +++ b/vendor/gopkg.in/olebedev/go-duktape.v3/duk_alloc_pool.h @@ -0,0 +1,223 @@ +#if !defined(DUK_ALLOC_POOL_H_INCLUDED) +#define DUK_ALLOC_POOL_H_INCLUDED + +#include "duktape.h" + +/* 32-bit (big endian) marker used at the end of pool entries so that wasted + * space can be detected. Waste tracking must be enabled explicitly. + */ +#if defined(DUK_ALLOC_POOL_TRACK_WASTE) +#define DUK_ALLOC_POOL_WASTE_MARKER 0xedcb2345UL +#endif + +/* Pointer compression with ROM strings/objects: + * + * For now, use DUK_USE_ROM_OBJECTS to signal the need for compressed ROM + * pointers. DUK_USE_ROM_PTRCOMP_FIRST is provided for the ROM pointer + * compression range minimum to avoid duplication in user code. + */ +#if defined(DUK_USE_ROM_OBJECTS) && defined(DUK_USE_HEAPPTR16) +#define DUK_ALLOC_POOL_ROMPTR_COMPRESSION +#define DUK_ALLOC_POOL_ROMPTR_FIRST DUK_USE_ROM_PTRCOMP_FIRST + +/* This extern declaration is provided by duktape.h, array provided by duktape.c. + * Because duk_config.h may include this file (to get the inline functions) we + * need to forward declare this also here. + */ +extern const void * const duk_rom_compressed_pointers[]; +#endif + +/* Pool configuration for a certain block size. */ +typedef struct { + unsigned int size; /* must be divisible by 4 and >= sizeof(void *) */ + unsigned int a; /* bytes (not count) to allocate: a*t + b, t is an arbitrary scale parameter */ + unsigned int b; +} duk_pool_config; + +/* Freelist entry, must fit into the smallest block size. */ +struct duk_pool_free; +typedef struct duk_pool_free duk_pool_free; +struct duk_pool_free { + duk_pool_free *next; +}; + +/* Pool state for a certain block size. */ +typedef struct { + duk_pool_free *first; + char *alloc_end; + unsigned int size; + unsigned int count; +#if defined(DUK_ALLOC_POOL_TRACK_HIGHWATER) + unsigned int hwm_used_count; +#endif +} duk_pool_state; + +/* Statistics for a certain pool. */ +typedef struct { + size_t used_count; + size_t used_bytes; + size_t free_count; + size_t free_bytes; + size_t waste_bytes; + size_t hwm_used_count; +} duk_pool_stats; + +/* Top level state for all pools. Pointer to this struct is used as the allocator + * userdata pointer. + */ +typedef struct { + int num_pools; + duk_pool_state *states; +#if defined(DUK_ALLOC_POOL_TRACK_HIGHWATER) + size_t hwm_used_bytes; + size_t hwm_waste_bytes; +#endif +} duk_pool_global; + +/* Statistics for the entire set of pools. */ +typedef struct { + size_t used_bytes; + size_t free_bytes; + size_t waste_bytes; + size_t hwm_used_bytes; + size_t hwm_waste_bytes; +} duk_pool_global_stats; + +/* Initialize a pool allocator, arguments: + * - buffer and size: continuous region to use for pool, must align to 4 + * - config: configuration for pools in ascending block size + * - state: state for pools, matches config order + * - num_pools: number of entries in 'config' and 'state' + * - global: global state structure + * + * The 'config', 'state', and 'global' pointers must be valid beyond the init + * call, as long as the pool is used. + * + * Returns a void pointer to be used as userdata for the allocator functions. + * Concretely the return value will be "(void *) global", i.e. the global + * state struct. If pool init fails, the return value will be NULL. + */ +void *duk_alloc_pool_init(char *buffer, + size_t size, + const duk_pool_config *configs, + duk_pool_state *states, + int num_pools, + duk_pool_global *global); + +/* Duktape allocation providers. Typing matches Duktape requirements. */ +void *duk_alloc_pool(void *udata, duk_size_t size); +void *duk_realloc_pool(void *udata, void *ptr, duk_size_t size); +void duk_free_pool(void *udata, void *ptr); + +/* Stats. */ +void duk_alloc_pool_get_pool_stats(duk_pool_state *s, duk_pool_stats *res); +void duk_alloc_pool_get_global_stats(duk_pool_global *g, duk_pool_global_stats *res); + +/* Duktape pointer compression global state (assumes single pool). */ +#if defined(DUK_USE_ROM_OBJECTS) && defined(DUK_USE_HEAPPTR16) +extern const void *duk_alloc_pool_romptr_low; +extern const void *duk_alloc_pool_romptr_high; +duk_uint16_t duk_alloc_pool_enc16_rom(void *ptr); +#endif +#if defined(DUK_USE_HEAPPTR16) +extern void *duk_alloc_pool_ptrcomp_base; +#endif + +#if 0 +duk_uint16_t duk_alloc_pool_enc16(void *ptr); +void *duk_alloc_pool_dec16(duk_uint16_t val); +#endif + +/* Inlined pointer compression functions. Gcc and clang -Os won't in + * practice inline these without an "always inline" attribute because it's + * more size efficient (by a few kB) to use explicit calls instead. Having + * these defined inline here allows performance optimized builds to inline + * pointer compression operations. + * + * Pointer compression assumes there's a single globally registered memory + * pool which makes pointer compression more efficient. This would be easy + * to fix by adding a userdata pointer to the compression functions and + * plumbing the heap userdata from the compression/decompression macros. + */ + +/* DUK_ALWAYS_INLINE is not a public API symbol so it may go away in even a + * minor update. But it's pragmatic for this extra because it handles many + * compilers via duk_config.h detection. Check that the macro exists so that + * if it's gone, we can still compile. + */ +#if defined(DUK_ALWAYS_INLINE) +#define DUK__ALLOC_POOL_ALWAYS_INLINE DUK_ALWAYS_INLINE +#else +#define DUK__ALLOC_POOL_ALWAYS_INLINE /* nop */ +#endif + +#if defined(DUK_USE_HEAPPTR16) +static DUK__ALLOC_POOL_ALWAYS_INLINE duk_uint16_t duk_alloc_pool_enc16(void *ptr) { + if (ptr == NULL) { + /* With 'return 0' gcc and clang -Os generate inefficient code. + * For example, gcc -Os generates: + * + * 0804911d : + * 804911d: 55 push %ebp + * 804911e: 85 c0 test %eax,%eax + * 8049120: 89 e5 mov %esp,%ebp + * 8049122: 74 0b je 804912f + * 8049124: 2b 05 e4 90 07 08 sub 0x80790e4,%eax + * 804912a: c1 e8 02 shr $0x2,%eax + * 804912d: eb 02 jmp 8049131 + * 804912f: 31 c0 xor %eax,%eax + * 8049131: 5d pop %ebp + * 8049132: c3 ret + * + * The NULL path checks %eax for zero; if it is zero, a zero + * is unnecessarily loaded into %eax again. The non-zero path + * has an unnecessary jump as a side effect of this. + * + * Using 'return (duk_uint16_t) (intptr_t) ptr;' generates similarly + * inefficient code; not sure how to make the result better. + */ + return 0; + } +#if defined(DUK_ALLOC_POOL_ROMPTR_COMPRESSION) + if (ptr >= duk_alloc_pool_romptr_low && ptr <= duk_alloc_pool_romptr_high) { + /* This is complex enough now to need a separate function. */ + return duk_alloc_pool_enc16_rom(ptr); + } +#endif + return (duk_uint16_t) (((size_t) ((char *) ptr - (char *) duk_alloc_pool_ptrcomp_base)) >> 2); +} + +static DUK__ALLOC_POOL_ALWAYS_INLINE void *duk_alloc_pool_dec16(duk_uint16_t val) { + if (val == 0) { + /* As with enc16 the gcc and clang -Os output is inefficient, + * e.g. gcc -Os: + * + * 08049133 : + * 8049133: 55 push %ebp + * 8049134: 66 85 c0 test %ax,%ax + * 8049137: 89 e5 mov %esp,%ebp + * 8049139: 74 0e je 8049149 + * 804913b: 8b 15 e4 90 07 08 mov 0x80790e4,%edx + * 8049141: 0f b7 c0 movzwl %ax,%eax + * 8049144: 8d 04 82 lea (%edx,%eax,4),%eax + * 8049147: eb 02 jmp 804914b + * 8049149: 31 c0 xor %eax,%eax + * 804914b: 5d pop %ebp + * 804914c: c3 ret + */ + return NULL; + } +#if defined(DUK_ALLOC_POOL_ROMPTR_COMPRESSION) + if (val >= DUK_ALLOC_POOL_ROMPTR_FIRST) { + /* This is a blind lookup, could check index validity. + * Duktape should never decompress a pointer which would + * be out-of-bounds here. + */ + return (void *) (intptr_t) (duk_rom_compressed_pointers[val - DUK_ALLOC_POOL_ROMPTR_FIRST]); + } +#endif + return (void *) ((char *) duk_alloc_pool_ptrcomp_base + (((size_t) val) << 2)); +} +#endif + +#endif /* DUK_ALLOC_POOL_H_INCLUDED */ -- cgit