Browse Source

Merge branch 'align-rework'

pull/2/head
Sami Vaarala 11 years ago
parent
commit
5be8695433
  1. 9
      Makefile
  2. 3
      src/duk_api.c
  3. 83
      src/duk_features.h
  4. 41
      src/duk_hbuffer.h
  5. 7
      src/duk_hobject.h
  6. 2
      src/duk_hobject_props.c
  7. 6
      website/guide/compiling.html
  8. 24
      website/guide/portability.html

9
Makefile

@ -133,6 +133,9 @@ CCOPTS_SHARED += -Wextra # very picky but catches e.g. signed/unsigned comparis
CCOPTS_SHARED += -I./dist/src
#CCOPTS_SHARED += -I./dist/src-separate
#CCOPTS_SHARED += -m32 # force 32-bit compilation on a 64-bit host
#CCOPTS_SHARED += -DDUK_OPT_NO_PACKED_TVAL
#CCOPTS_SHARED += -DDUK_OPT_FORCE_ALIGN=4
#CCOPTS_SHARED += -DDUK_OPT_FORCE_ALIGN=8
#CCOPTS_SHARED += -DDUK_OPT_NO_REFERENCE_COUNTING
#CCOPTS_SHARED += -DDUK_OPT_NO_MARK_AND_SWEEP
#CCOPTS_SHARED += -DDUK_OPT_NO_VOLUNTARY_GC
@ -424,7 +427,7 @@ vgemscriptentest: emscripten duk
# - Using -O2 without asm.js for now.
# https://github.com/kripken/emscripten/wiki/Optimizing-Code
# http://mozakai.blogspot.fi/2013/08/outlining-workaround-for-jits-and-big.html
EMCCOPTS_DUKVM=-O2 -std=c99 -Wall -s OUTLINING_LIMIT=20000 -s MAX_SETJMPS=1000 -s ASM_JS=0
EMCCOPTS_DUKVM=-O2 -std=c99 -Wall -s OUTLINING_LIMIT=20000 -s MAX_SETJMPS=1000 -s ASM_JS=0 -DEMSCRIPTEN
MAND_BASE64=dyA9IDgwOyBoID0gNDA7IGl0ZXIgPSAxMDA7IGZvciAoaSA9IDA7IGkgLSBoOyBpICs9IDEpIHsgeTAgPSAoaSAvIGgpICogNC4wIC0gMi4wOyByZXMgPSBbXTsgZm9yIChqID0gMDsgaiAtIHc7IGogKz0gMSkgeyB4MCA9IChqIC8gdykgKiA0LjAgLSAyLjA7IHh4ID0gMDsgeXkgPSAwOyBjID0gIiMiOyBmb3IgKGsgPSAwOyBrIC0gaXRlcjsgayArPSAxKSB7IHh4MiA9IHh4Knh4OyB5eTIgPSB5eSp5eTsgaWYgKE1hdGgubWF4KDAsIDQuMCAtICh4eDIgKyB5eTIpKSkgeyB5eSA9IDIqeHgqeXkgKyB5MDsgeHggPSB4eDIgLSB5eTIgKyB4MDsgfSBlbHNlIHsgYyA9ICIuIjsgYnJlYWs7IH0gfSByZXNbcmVzLmxlbmd0aF0gPSBjOyB9IHByaW50KHJlcy5qb2luKCIiKSk7IH0K
@ -432,7 +435,7 @@ MAND_BASE64=dyA9IDgwOyBoID0gNDA7IGl0ZXIgPSAxMDA7IGZvciAoaSA9IDA7IGkgLSBoOyBpICs9
emscriptenduktest: emscripten dist
@echo "### emscriptenduktest"
-@rm -f /tmp/duk-emcc-duktest.js
emscripten/emcc $(EMCCOPTS_DUKVM) -DDUK_OPT_NO_PACKED_TVAL -DDUK_OPT_ASSERTIONS -DDUK_OPT_SELF_TESTS -Idist/src/ dist/src/duktape.c dist/examples/eval/eval.c -o /tmp/duk-emcc-duktest.js
emscripten/emcc $(EMCCOPTS_DUKVM) -DDUK_OPT_ASSERTIONS -DDUK_OPT_SELF_TESTS -Idist/src/ dist/src/duktape.c dist/examples/eval/eval.c -o /tmp/duk-emcc-duktest.js
node /tmp/duk-emcc-duktest.js \
'print("Hello from Duktape running inside Emscripten/NodeJS");' \
'print(Duktape.version, Duktape.env);' \
@ -445,7 +448,7 @@ emscriptenduktest: emscripten dist
EMCCOPTS_DUKVM_EXPORT=-s EXPORTED_FUNCTIONS='["_dukweb_is_open", "_dukweb_open","_dukweb_close","_dukweb_eval"]'
dukweb.js: emscripten dist
emscripten/emcc $(EMCCOPTS_DUKVM) $(EMCCOPTS_DUKVM_EXPORT) -DDUK_OPT_NO_PACKED_TVAL -DDUK_OPT_ASSERTIONS -DDUK_OPT_SELF_TESTS -Idist/src/ dist/src/duktape.c dukweb/dukweb.c -o dukweb.js
emscripten/emcc $(EMCCOPTS_DUKVM) $(EMCCOPTS_DUKVM_EXPORT) -DDUK_OPT_ASSERTIONS -DDUK_OPT_SELF_TESTS -Idist/src/ dist/src/duktape.c dukweb/dukweb.c -o dukweb.js
cat dukweb/dukweb_extra.js >> dukweb.js
@wc dukweb.js

3
src/duk_api.c

@ -3052,7 +3052,8 @@ void duk_pop_n(duk_context *ctx, unsigned int count) {
duk_hthread *thr = (duk_hthread *) ctx;
DUK_ASSERT(ctx != NULL);
if (thr->valstack_top - thr->valstack_bottom < count) {
DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
if ((size_t) (thr->valstack_top - thr->valstack_bottom) < (size_t) count) {
DUK_ERROR(thr, DUK_ERR_API_ERROR, "attempt to pop too many entries");
}

83
src/duk_features.h

@ -191,6 +191,11 @@ static __inline__ unsigned long long duk_rdtsc(void) {
#define DUK_F_FLASHPLAYER
#endif
/* Emscripten (provided explicitly by user), improve if possible */
#if defined(EMSCRIPTEN)
#define DUK_F_EMSCRIPTEN
#endif
/* GCC and GCC version convenience define. */
#if defined(__GNUC__)
#define DUK_F_GCC
@ -665,24 +670,67 @@ typedef double duk_double_t;
#endif
/*
* Support for unaligned accesses
* Alignment requirement and support for unaligned accesses
*
* Assume unaligned accesses are not supported unless specifically allowed
* in the target platform.
* in the target platform. Some platforms may support unaligned accesses
* but alignment to 4 or 8 may still be desirable.
*/
/* FIXME: alignment is now only guaranteed to 4 bytes in any case, so doubles
* are not guaranteed to be aligned.
*/
#if defined(DUK_F_ARM)
#undef DUK_USE_UNALIGNED_ACCESSES_POSSIBLE
#undef DUK_USE_ALIGN4
#undef DUK_USE_ALIGN8
#if defined(DUK_F_EMSCRIPTEN)
/* Required on at least some targets, so use whenever Emscripten used,
* regardless of compilation target.
*/
#define DUK_USE_ALIGN8
#elif defined(DUK_F_ARM)
#define DUK_USE_ALIGN4
#elif defined(DUK_F_MIPS)
#undef DUK_USE_UNALIGNED_ACCESSES_POSSIBLE
#define DUK_USE_ALIGN4
#elif defined(DUK_F_X86) || defined(DUK_F_X64)
#define DUK_USE_UNALIGNED_ACCESSES_POSSIBLE
#else
/* unknown, use safe default */
#define DUK_USE_ALIGN8
#endif
/* User forced alignment to 4 or 8. */
#if defined(DUK_OPT_FORCE_ALIGN)
#undef DUK_USE_UNALIGNED_ACCESSES_POSSIBLE
#undef DUK_USE_ALIGN4
#undef DUK_USE_ALIGN8
#if (DUK_OPT_FORCE_ALIGN == 4)
#define DUK_USE_ALIGN4
#elif (DUK_OPT_FORCE_ALIGN == 8)
#define DUK_USE_ALIGN8
#else
#error invalid DUK_OPT_FORCE_ALIGN value
#endif
#endif
/* Compiler specific hackery needed to force struct size to match aligment,
* see e.g. duk_hbuffer.h.
*
* http://stackoverflow.com/questions/11130109/c-struct-size-alignment
* http://stackoverflow.com/questions/10951039/specifying-64-bit-alignment
*/
#if defined(DUK_F_MSVC)
#define DUK_USE_PACK_MSVC_PRAGMA
#elif defined(DUK_F_GCC)
#define DUK_USE_PACK_GCC_ATTR
#elif defined(DUK_F_CLANG)
#define DUK_USE_PACK_CLANG_ATTR
#else
#define DUK_USE_PACK_DUMMY_MEMBER
#endif
#ifdef DUK_USE_UNALIGNED_ACCESSES_POSSIBLE
#define DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS
#else
#undef DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS
#endif
/*
@ -784,6 +832,11 @@ typedef double duk_double_t;
#define DUK_USE_PACKED_TVAL_POSSIBLE
#endif
/* With Emscripten, force unpacked duk_tval just to be safe. */
#if defined(DUK_F_EMSCRIPTEN) && defined(DUK_USE_PACKED_TVAL_POSSIBLE)
#undef DUK_USE_PACKED_TVAL_POSSIBLE
#endif
/* GCC/clang inaccurate math would break compliance and probably duk_tval,
* so refuse to compile. Relax this if -ffast-math is tested to work.
*/
@ -1343,20 +1396,6 @@ extern double duk_computed_nan;
#define DUK_USE_SELF_TESTS
#endif
/*
* Unaligned accesses
*/
#ifdef DUK_USE_UNALIGNED_ACCESSES_POSSIBLE
#define DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS
#define DUK_USE_HOBJECT_UNALIGNED_LAYOUT
#else
#undef DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS
#undef DUK_USE_HOBJECT_UNALIGNED_LAYOUT
#endif
/* FIXME: force alignment requirement */
/*
* Codecs
*/

41
src/duk_hbuffer.h

@ -81,17 +81,40 @@ struct duk_hbuffer {
*/
};
#if defined(DUK_USE_ALIGN8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
#pragma pack(push, 8)
#endif
struct duk_hbuffer_fixed {
duk_heaphdr hdr;
size_t size;
/* Data follows the struct header. The struct size is padded by the
* compiler so the buffer data area begins at an aligned address.
* This potentially a few bytes but would be difficult to implement
* portably (for instance, there is no portable way of figuring out
* the packed struct size, since packed attributes are non-portable).
/*
* Data follows the struct header. The struct size is padded by the
* compiler based on the struct members. This guarantees that the
* buffer data will be aligned-by-4 but not necessarily aligned-by-8.
*
* On platforms where alignment does not matter, the struct padding
* could be removed (if there is any). On platforms where alignment
* by 8 is required, the struct size must be forced to be a multiple
* of 8 by some means. Without it, some user code may break, and also
* Duktape itself breaks (e.g. the compiler stores duk_tvals in a
* dynamic buffer).
*/
};
#if defined(DUK_USE_ALIGN8) && defined(DUK_USE_PACK_DUMMY_MEMBER)
/* Portable but very wasteful approach to ensuring alignment by 8. */
duk_uint64_t dummy_for_align8;
#endif
}
#if defined(DUK_USE_ALIGN8) && defined(DUK_USE_PACK_GCC_ATTR)
__attribute__ ((aligned (8)))
#elif defined(DUK_USE_ALIGN8) && defined(DUK_USE_PACK_CLANG_ATTR)
__attribute__ ((aligned (8)))
#endif
;
#if defined(DUK_USE_ALIGN8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
#pragma pack(pop)
#endif
struct duk_hbuffer_dynamic {
duk_heaphdr hdr;
@ -100,7 +123,11 @@ struct duk_hbuffer_dynamic {
void *curr_alloc; /* may be NULL if usable_size == 0 */
size_t usable_size;
/* alloc size is usable_size + 1; a zero byte always follows the buffer */
/*
* Alloc size is usable_size + 1; a zero byte always follows the
* buffer. curr_alloc is explicitly allocated and will have
* alignment suitable for e.g. duk_tval.
*/
};
/*

7
src/duk_hobject.h

@ -371,9 +371,14 @@
/* limit is quite low: one array entry is 8 bytes, one normal entry is 4+1+8+4 = 17 bytes (with hash entry) */
#define DUK_HOBJECT_A_ABANDON_LIMIT 2 /* 25%, i.e. less than 25% used -> abandon */
/* FIXME: where to get align target (now fixed to 4)? */
/* internal align target for props allocation, must be 2*n for some n */
#if defined(DUK_USE_ALIGN4)
#define DUK_HOBJECT_ALIGN_TARGET 4
#elif defined(DUK_USE_ALIGN8)
#define DUK_HOBJECT_ALIGN_TARGET 8
#else
#define DUK_HOBJECT_ALIGN_TARGET 1
#endif
/* controls for minimum entry part growth */
#define DUK_HOBJECT_E_MIN_GROW_ADD 16

2
src/duk_hobject_props.c

@ -291,7 +291,7 @@ static void duk__realloc_props(duk_hthread *thr,
* computations to access the parts even more arcane.
*/
#ifdef DUK_USE_HOBJECT_UNALIGNED_LAYOUT
#if (DUK_HOBJECT_ALIGN_TARGET == 1)
/* no need to adjust new_e_size */
new_e_size_adjusted = new_e_size;
#else

6
website/guide/compiling.html

@ -45,6 +45,12 @@ The table below summarizes the available options, in no particular order:</p>
issues than the unpacked one.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_FORCE_ALIGN</td>
<td>Use <code>-DDUK_OPT_FORCE_ALIGN=4</code> or <code>-DDUK_OPT_FORCE_ALIGN=8</code>
to force a specific struct/value alignment instead of relying on Duktape's
automatic detection. This shouldn't normally be needed.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_NO_REFERENCE_COUNTING</td>
<td>Disable reference counting and use only mark-and-sweep for garbage collection.
Although this reduces memory footprint of heap objects, the downside is much

24
website/guide/portability.html

@ -133,6 +133,11 @@ detail below the table.</p>
<td>Requires some preprocessor defines, datetime resolution limited to full seconds.</td>
</tr>
<tr>
<td>Emscripten</td>
<td>Emscripten</td>
<td>n/a</td>
<td>Requires additional options, see below. At least V8/NodeJs works.</td>
<tr>
<td>Adobe Flash Runtime</td>
<td>CrossBridge<br />(GCC-4.2 with Flash backend)</td>
<td>n/a</td>
@ -172,6 +177,25 @@ M68K AmigaOS or TOS you must:</p>
<p>Datetime resolution is limited to full seconds only when using VBCC on
AmigaOS or TOS.</p>
<h3>Emscripten</h3>
<p>Needs a set of <code>emcc</code> options. When executed with
V8, the following seem to work:</p>
<ul>
<li><code>-DEMSCRIPTEN</code>: <b>mandatory option</b>, needed by Duktape
to detect Emscripten. Without this Duktape may use unaligned accesses
which Emscripten does not allow. This results in odd and inconsistent
behavior, and is not necessarily caught by Duktape self tests.</li>
<li><code>-std=c99</code></li>
<li><code>-O2</code></li>
<li><code>-s ASM_JS=0</code></li>
<li><code>-s MAX_SETJMPS=1000</code></li>
<li><code>-s OUTLINING_LIMIT=20000</li>
</ul>
<p>Dukweb is compiled using Emscripten, so you can also check out the Duktape
git repository to see how Dukweb is compiled.</p>
<h2>Using Duktape from a C++ program</h2>
<p>To use Duktape from a C++ program, simply compile Duktape in plain C and use

Loading…
Cancel
Save