|
|
@ -3,6 +3,32 @@ |
|
|
|
*/ |
|
|
|
|
|
|
|
#ifdef DUK_CMDLINE_AJSHEAP |
|
|
|
|
|
|
|
#include <stdio.h> |
|
|
|
#include <stdlib.h> |
|
|
|
#include <string.h> |
|
|
|
#include "ajs.h" |
|
|
|
#include "ajs_heap.h" |
|
|
|
|
|
|
|
/*
|
|
|
|
* Helpers |
|
|
|
*/ |
|
|
|
|
|
|
|
static void safe_print_chars(const char *p, duk_size_t len) { |
|
|
|
duk_size_t i; |
|
|
|
|
|
|
|
printf("\""); |
|
|
|
for (i = 0; i < len; i++) { |
|
|
|
unsigned char x = (unsigned char) p[i]; |
|
|
|
if (x < 0x20 || x >= 0x7e || x == '"' || x == '\'' || x == '\\') { |
|
|
|
printf("\\x%02x", (int) x); |
|
|
|
} else { |
|
|
|
printf("%c", (char) x); |
|
|
|
} |
|
|
|
} |
|
|
|
printf("\""); |
|
|
|
} |
|
|
|
|
|
|
|
/*
|
|
|
|
* Heap initialization when using AllJoyn.js pool allocator (without any |
|
|
|
* other AllJoyn.js integration). This serves as an example of how to |
|
|
@ -19,12 +45,6 @@ |
|
|
|
* https://git.allseenalliance.org/cgit/core/alljoyn-js.git/tree/ajs.c
|
|
|
|
*/ |
|
|
|
|
|
|
|
#include <stdio.h> |
|
|
|
#include <stdlib.h> |
|
|
|
#include <string.h> |
|
|
|
#include "ajs.h" |
|
|
|
#include "ajs_heap.h" |
|
|
|
|
|
|
|
static const AJS_HeapConfig ajsheap_config[] = { |
|
|
|
{ 8, 10, AJS_POOL_BORROW, 0 }, |
|
|
|
{ 12, 10, AJS_POOL_BORROW, 0 }, |
|
|
@ -50,10 +70,70 @@ static const AJS_HeapConfig ajsheap_config[] = { |
|
|
|
|
|
|
|
uint8_t *ajsheap_ram = NULL; |
|
|
|
|
|
|
|
/* Example pointer compression functions.
|
|
|
|
* 'base' is chosen so that no non-NULL pointer results in a zero result |
|
|
|
* which is reserved for NULL pointers. |
|
|
|
void ajsheap_init(void) { |
|
|
|
size_t heap_sz[1]; |
|
|
|
uint8_t *heap_array[1]; |
|
|
|
uint8_t num_pools, i; |
|
|
|
AJ_Status ret; |
|
|
|
|
|
|
|
num_pools = (uint8_t) (sizeof(ajsheap_config) / sizeof(AJS_HeapConfig)); |
|
|
|
heap_sz[0] = AJS_HeapRequired(ajsheap_config, /* heapConfig */ |
|
|
|
num_pools, /* numPools */ |
|
|
|
0); /* heapNum */ |
|
|
|
ajsheap_ram = (uint8_t *) malloc(heap_sz[0]); |
|
|
|
if (!ajsheap_ram) { |
|
|
|
fprintf(stderr, "Failed to allocate AJS heap\n"); |
|
|
|
fflush(stderr); |
|
|
|
exit(1); |
|
|
|
} |
|
|
|
heap_array[0] = ajsheap_ram; |
|
|
|
|
|
|
|
fprintf(stderr, "Allocated AJS heap of %ld bytes, pools:", (long) heap_sz[0]); |
|
|
|
for (i = 0; i < num_pools; i++) { |
|
|
|
fprintf(stderr, " (sz:%ld,num:%ld,brw:%ld,idx:%ld)", |
|
|
|
(long) ajsheap_config[i].size, (long) ajsheap_config[i].entries, |
|
|
|
(long) ajsheap_config[i].borrow, (long) ajsheap_config[i].heapIndex); |
|
|
|
} |
|
|
|
fprintf(stderr, "\n"); |
|
|
|
fflush(stderr); |
|
|
|
|
|
|
|
ret = AJS_HeapInit((void **) heap_array, /* heap */ |
|
|
|
(size_t *) heap_sz, /* heapSz */ |
|
|
|
ajsheap_config, /* heapConfig */ |
|
|
|
num_pools, /* numPools */ |
|
|
|
1); /* numHeaps */ |
|
|
|
fprintf(stderr, "AJS_HeapInit() -> %ld\n", (long) ret); |
|
|
|
fflush(stderr); |
|
|
|
} |
|
|
|
|
|
|
|
/* AjsHeap.dump(), allows Ecmascript code to dump heap status at suitable
|
|
|
|
* points. |
|
|
|
*/ |
|
|
|
duk_ret_t ajsheap_dump_binding(duk_context *ctx) { |
|
|
|
AJS_HeapDump(); |
|
|
|
fflush(stdout); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
void ajsheap_dump(void) { |
|
|
|
AJS_HeapDump(); |
|
|
|
fflush(stdout); |
|
|
|
} |
|
|
|
|
|
|
|
void ajsheap_register(duk_context *ctx) { |
|
|
|
duk_push_object(ctx); |
|
|
|
duk_push_c_function(ctx, ajsheap_dump_binding, 0); |
|
|
|
duk_put_prop_string(ctx, -2, "dump"); |
|
|
|
duk_put_global_string(ctx, "AjsHeap"); |
|
|
|
} |
|
|
|
|
|
|
|
/*
|
|
|
|
* Example pointer compression functions. |
|
|
|
* |
|
|
|
* 'base' is chosen so that no non-NULL pointer results in a zero result |
|
|
|
* which is reserved for NULL pointers. |
|
|
|
*/ |
|
|
|
|
|
|
|
duk_uint16_t ajsheap_enc16(void *p) { |
|
|
|
duk_uint32_t ret; |
|
|
|
char *base = (char *) ajsheap_ram - 4; |
|
|
@ -88,31 +168,37 @@ void *ajsheap_dec16(duk_uint16_t x) { |
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
/* Simplified example of an external strings strategy where incoming strings
|
|
|
|
* are writted sequentially into a fixed flash memory area which is memory |
|
|
|
* mapped. The example first scans if the string is already in the flash |
|
|
|
* (which may happen if the same string is interned multiple times), then |
|
|
|
* adds it to flash if there is space. |
|
|
|
/*
|
|
|
|
* Simplified example of an external strings strategy where incoming strings |
|
|
|
* are written sequentially into a fixed, memory mapped flash area. |
|
|
|
* |
|
|
|
* This example is too slow to be used in a real world application: there |
|
|
|
* should be e.g. a hash table to quickly check for strings that are already |
|
|
|
* present in the string data (similarly to how string interning works in |
|
|
|
* Duktape itself). |
|
|
|
* The example first scans if the string is already in the flash (which may |
|
|
|
* happen if the same string is interned multiple times), then adds it to |
|
|
|
* flash if there is space. |
|
|
|
* |
|
|
|
* This example is too slow to be used in a real world application: there |
|
|
|
* should be e.g. a hash table to quickly check for strings that are already |
|
|
|
* present in the string data (similarly to how string interning works in |
|
|
|
* Duktape itself). |
|
|
|
*/ |
|
|
|
|
|
|
|
static uint8_t ajsheap_strdata[65536]; |
|
|
|
static size_t ajsheap_strdata_used = 0; |
|
|
|
|
|
|
|
const void *ajsheap_ext_str_check(const void *ptr, duk_size_t len) { |
|
|
|
const void *ajsheap_extstr_check_1(const void *ptr, duk_size_t len) { |
|
|
|
uint8_t *p, *p_end; |
|
|
|
uint8_t initial; |
|
|
|
uint8_t *ret; |
|
|
|
size_t left; |
|
|
|
|
|
|
|
(void) safe_print_chars; /* potentially unused */ |
|
|
|
|
|
|
|
if (len <= 3) { |
|
|
|
/* It's not worth it to make very small strings external, as
|
|
|
|
* they would take the same space anyway. Also avoids zero |
|
|
|
* length degenerate case. |
|
|
|
*/ |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
/*
|
|
|
@ -132,7 +218,11 @@ const void *ajsheap_ext_str_check(const void *ptr, duk_size_t len) { |
|
|
|
p[len] == 0) { |
|
|
|
ret = p; |
|
|
|
#if 0 |
|
|
|
printf("ajsheap_ext_str_check: ptr=%p, len=%ld -> existing %p (used=%ld)\n", (void *) ptr, (long) len, (void *) ret, (long) ajsheap_strdata_used); |
|
|
|
printf("ajsheap_extstr_check_1: ptr=%p, len=%ld ", |
|
|
|
(void *) ptr, (long) len); |
|
|
|
safe_print_chars((const char *) ptr, len); |
|
|
|
printf(" -> existing %p (used=%ld)\n", |
|
|
|
(void *) ret, (long) ajsheap_strdata_used); |
|
|
|
#endif |
|
|
|
return ret; |
|
|
|
} |
|
|
@ -145,7 +235,9 @@ const void *ajsheap_ext_str_check(const void *ptr, duk_size_t len) { |
|
|
|
|
|
|
|
if (ajsheap_strdata_used + len + 1 > sizeof(ajsheap_strdata)) { |
|
|
|
#if 0 |
|
|
|
printf("ajsheap_ext_str_check: ptr=%p, len=%ld -> no space (used=%ld)\n", (void *) ptr, (long) len, (long) ajsheap_strdata_used); |
|
|
|
printf("ajsheap_extstr_check_1: ptr=%p, len=%ld ", (void *) ptr, (long) len); |
|
|
|
safe_print_chars((const char *) ptr, len); |
|
|
|
printf(" -> no space (used=%ld)\n", (long) ajsheap_strdata_used); |
|
|
|
#endif |
|
|
|
return NULL; |
|
|
|
} |
|
|
@ -161,67 +253,419 @@ const void *ajsheap_ext_str_check(const void *ptr, duk_size_t len) { |
|
|
|
ajsheap_strdata_used += len + 1; |
|
|
|
|
|
|
|
#if 0 |
|
|
|
printf("ajsheap_ext_str_check: ptr=%p, len=%ld -> %p (used=%ld)\n", (void *) ptr, (long) len, (void *) ret, (long) ajsheap_strdata_used); |
|
|
|
printf("ajsheap_extstr_check_1: ptr=%p, len=%ld -> ", (void *) ptr, (long) len); |
|
|
|
safe_print_chars((const char *) ptr, len); |
|
|
|
printf(" -> %p (used=%ld)\n", (void *) ret, (long) ajsheap_strdata_used); |
|
|
|
#endif |
|
|
|
return (const void *) ret; |
|
|
|
} |
|
|
|
|
|
|
|
void ajsheap_init(void) { |
|
|
|
size_t heap_sz[1]; |
|
|
|
uint8_t *heap_array[1]; |
|
|
|
uint8_t num_pools, i; |
|
|
|
AJ_Status ret; |
|
|
|
/*
|
|
|
|
* Simplified example of an external strings strategy where a set of strings |
|
|
|
* is gathered during application compile time and baked into the application |
|
|
|
* binary. |
|
|
|
* |
|
|
|
* Duktape built-in strings are available from duk_build_meta.json, see |
|
|
|
* util/duk_meta_to_strarray.py. There may also be a lot of application |
|
|
|
* specific strings, e.g. those used by application specific APIs. These |
|
|
|
* must be gathered through some other means. |
|
|
|
*/ |
|
|
|
|
|
|
|
num_pools = (uint8_t) (sizeof(ajsheap_config) / sizeof(AJS_HeapConfig)); |
|
|
|
heap_sz[0] = AJS_HeapRequired(ajsheap_config, /* heapConfig */ |
|
|
|
num_pools, /* numPools */ |
|
|
|
0); /* heapNum */ |
|
|
|
ajsheap_ram = (uint8_t *) malloc(heap_sz[0]); |
|
|
|
if (!ajsheap_ram) { |
|
|
|
fprintf(stderr, "Failed to allocate AJS heap\n"); |
|
|
|
fflush(stderr); |
|
|
|
exit(1); |
|
|
|
} |
|
|
|
heap_array[0] = ajsheap_ram; |
|
|
|
static const char *strdata_duk_builtin_strings[] = { |
|
|
|
/*
|
|
|
|
* These strings are from util/duk_meta_to_strarray.py |
|
|
|
*/ |
|
|
|
|
|
|
|
fprintf(stderr, "Allocated AJS heap of %ld bytes, pools:", (long) heap_sz[0]); |
|
|
|
for (i = 0; i < num_pools; i++) { |
|
|
|
fprintf(stderr, " (sz:%ld,num:%ld,brw:%ld,idx:%ld)", |
|
|
|
(long) ajsheap_config[i].size, (long) ajsheap_config[i].entries, |
|
|
|
(long) ajsheap_config[i].borrow, (long) ajsheap_config[i].heapIndex); |
|
|
|
} |
|
|
|
fprintf(stderr, "\n"); |
|
|
|
fflush(stderr); |
|
|
|
"Logger", |
|
|
|
"Thread", |
|
|
|
"Pointer", |
|
|
|
"Buffer", |
|
|
|
"DecEnv", |
|
|
|
"ObjEnv", |
|
|
|
"", |
|
|
|
"global", |
|
|
|
"Arguments", |
|
|
|
"JSON", |
|
|
|
"Math", |
|
|
|
"Error", |
|
|
|
"RegExp", |
|
|
|
"Date", |
|
|
|
"Number", |
|
|
|
"Boolean", |
|
|
|
"String", |
|
|
|
"Array", |
|
|
|
"Function", |
|
|
|
"Object", |
|
|
|
"Null", |
|
|
|
"Undefined", |
|
|
|
"{_func:true}", |
|
|
|
"{\x22" "_func\x22" ":true}", |
|
|
|
"{\x22" "_ninf\x22" ":true}", |
|
|
|
"{\x22" "_inf\x22" ":true}", |
|
|
|
"{\x22" "_nan\x22" ":true}", |
|
|
|
"{\x22" "_undef\x22" ":true}", |
|
|
|
"toLogString", |
|
|
|
"clog", |
|
|
|
"l", |
|
|
|
"n", |
|
|
|
"fatal", |
|
|
|
"error", |
|
|
|
"warn", |
|
|
|
"debug", |
|
|
|
"trace", |
|
|
|
"raw", |
|
|
|
"fmt", |
|
|
|
"current", |
|
|
|
"resume", |
|
|
|
"compact", |
|
|
|
"jc", |
|
|
|
"jx", |
|
|
|
"base64", |
|
|
|
"hex", |
|
|
|
"dec", |
|
|
|
"enc", |
|
|
|
"fin", |
|
|
|
"gc", |
|
|
|
"act", |
|
|
|
"info", |
|
|
|
"version", |
|
|
|
"env", |
|
|
|
"modLoaded", |
|
|
|
"modSearch", |
|
|
|
"errThrow", |
|
|
|
"errCreate", |
|
|
|
"compile", |
|
|
|
"\xff" "Regbase", |
|
|
|
"\xff" "Thread", |
|
|
|
"\xff" "Handler", |
|
|
|
"\xff" "Finalizer", |
|
|
|
"\xff" "Callee", |
|
|
|
"\xff" "Map", |
|
|
|
"\xff" "Args", |
|
|
|
"\xff" "This", |
|
|
|
"\xff" "Pc2line", |
|
|
|
"\xff" "Source", |
|
|
|
"\xff" "Varenv", |
|
|
|
"\xff" "Lexenv", |
|
|
|
"\xff" "Varmap", |
|
|
|
"\xff" "Formals", |
|
|
|
"\xff" "Bytecode", |
|
|
|
"\xff" "Next", |
|
|
|
"\xff" "Target", |
|
|
|
"\xff" "Value", |
|
|
|
"pointer", |
|
|
|
"buffer", |
|
|
|
"\xff" "Tracedata", |
|
|
|
"lineNumber", |
|
|
|
"fileName", |
|
|
|
"pc", |
|
|
|
"stack", |
|
|
|
"ThrowTypeError", |
|
|
|
"Duktape", |
|
|
|
"id", |
|
|
|
"require", |
|
|
|
"__proto__", |
|
|
|
"setPrototypeOf", |
|
|
|
"ownKeys", |
|
|
|
"enumerate", |
|
|
|
"deleteProperty", |
|
|
|
"has", |
|
|
|
"Proxy", |
|
|
|
"callee", |
|
|
|
"Invalid Date", |
|
|
|
"[...]", |
|
|
|
"\x0a" "\x09", |
|
|
|
" ", |
|
|
|
",", |
|
|
|
"-0", |
|
|
|
"+0", |
|
|
|
"0", |
|
|
|
"-Infinity", |
|
|
|
"+Infinity", |
|
|
|
"Infinity", |
|
|
|
"object", |
|
|
|
"string", |
|
|
|
"number", |
|
|
|
"boolean", |
|
|
|
"undefined", |
|
|
|
"stringify", |
|
|
|
"tan", |
|
|
|
"sqrt", |
|
|
|
"sin", |
|
|
|
"round", |
|
|
|
"random", |
|
|
|
"pow", |
|
|
|
"min", |
|
|
|
"max", |
|
|
|
"log", |
|
|
|
"floor", |
|
|
|
"exp", |
|
|
|
"cos", |
|
|
|
"ceil", |
|
|
|
"atan2", |
|
|
|
"atan", |
|
|
|
"asin", |
|
|
|
"acos", |
|
|
|
"abs", |
|
|
|
"SQRT2", |
|
|
|
"SQRT1_2", |
|
|
|
"PI", |
|
|
|
"LOG10E", |
|
|
|
"LOG2E", |
|
|
|
"LN2", |
|
|
|
"LN10", |
|
|
|
"E", |
|
|
|
"message", |
|
|
|
"name", |
|
|
|
"input", |
|
|
|
"index", |
|
|
|
"(?:)", |
|
|
|
"lastIndex", |
|
|
|
"multiline", |
|
|
|
"ignoreCase", |
|
|
|
"source", |
|
|
|
"test", |
|
|
|
"exec", |
|
|
|
"toGMTString", |
|
|
|
"setYear", |
|
|
|
"getYear", |
|
|
|
"toJSON", |
|
|
|
"toISOString", |
|
|
|
"toUTCString", |
|
|
|
"setUTCFullYear", |
|
|
|
"setFullYear", |
|
|
|
"setUTCMonth", |
|
|
|
"setMonth", |
|
|
|
"setUTCDate", |
|
|
|
"setDate", |
|
|
|
"setUTCHours", |
|
|
|
"setHours", |
|
|
|
"setUTCMinutes", |
|
|
|
"setMinutes", |
|
|
|
"setUTCSeconds", |
|
|
|
"setSeconds", |
|
|
|
"setUTCMilliseconds", |
|
|
|
"setMilliseconds", |
|
|
|
"setTime", |
|
|
|
"getTimezoneOffset", |
|
|
|
"getUTCMilliseconds", |
|
|
|
"getMilliseconds", |
|
|
|
"getUTCSeconds", |
|
|
|
"getSeconds", |
|
|
|
"getUTCMinutes", |
|
|
|
"getMinutes", |
|
|
|
"getUTCHours", |
|
|
|
"getHours", |
|
|
|
"getUTCDay", |
|
|
|
"getDay", |
|
|
|
"getUTCDate", |
|
|
|
"getDate", |
|
|
|
"getUTCMonth", |
|
|
|
"getMonth", |
|
|
|
"getUTCFullYear", |
|
|
|
"getFullYear", |
|
|
|
"getTime", |
|
|
|
"toLocaleTimeString", |
|
|
|
"toLocaleDateString", |
|
|
|
"toTimeString", |
|
|
|
"toDateString", |
|
|
|
"now", |
|
|
|
"UTC", |
|
|
|
"parse", |
|
|
|
"toPrecision", |
|
|
|
"toExponential", |
|
|
|
"toFixed", |
|
|
|
"POSITIVE_INFINITY", |
|
|
|
"NEGATIVE_INFINITY", |
|
|
|
"NaN", |
|
|
|
"MIN_VALUE", |
|
|
|
"MAX_VALUE", |
|
|
|
"substr", |
|
|
|
"trim", |
|
|
|
"toLocaleUpperCase", |
|
|
|
"toUpperCase", |
|
|
|
"toLocaleLowerCase", |
|
|
|
"toLowerCase", |
|
|
|
"substring", |
|
|
|
"split", |
|
|
|
"search", |
|
|
|
"replace", |
|
|
|
"match", |
|
|
|
"localeCompare", |
|
|
|
"charCodeAt", |
|
|
|
"charAt", |
|
|
|
"fromCharCode", |
|
|
|
"reduceRight", |
|
|
|
"reduce", |
|
|
|
"filter", |
|
|
|
"map", |
|
|
|
"forEach", |
|
|
|
"some", |
|
|
|
"every", |
|
|
|
"lastIndexOf", |
|
|
|
"indexOf", |
|
|
|
"unshift", |
|
|
|
"splice", |
|
|
|
"sort", |
|
|
|
"slice", |
|
|
|
"shift", |
|
|
|
"reverse", |
|
|
|
"push", |
|
|
|
"pop", |
|
|
|
"join", |
|
|
|
"concat", |
|
|
|
"isArray", |
|
|
|
"arguments", |
|
|
|
"caller", |
|
|
|
"bind", |
|
|
|
"call", |
|
|
|
"apply", |
|
|
|
"propertyIsEnumerable", |
|
|
|
"isPrototypeOf", |
|
|
|
"hasOwnProperty", |
|
|
|
"valueOf", |
|
|
|
"toLocaleString", |
|
|
|
"toString", |
|
|
|
"constructor", |
|
|
|
"set", |
|
|
|
"get", |
|
|
|
"enumerable", |
|
|
|
"configurable", |
|
|
|
"writable", |
|
|
|
"value", |
|
|
|
"keys", |
|
|
|
"isExtensible", |
|
|
|
"isFrozen", |
|
|
|
"isSealed", |
|
|
|
"preventExtensions", |
|
|
|
"freeze", |
|
|
|
"seal", |
|
|
|
"defineProperties", |
|
|
|
"defineProperty", |
|
|
|
"create", |
|
|
|
"getOwnPropertyNames", |
|
|
|
"getOwnPropertyDescriptor", |
|
|
|
"getPrototypeOf", |
|
|
|
"prototype", |
|
|
|
"length", |
|
|
|
"alert", |
|
|
|
"print", |
|
|
|
"unescape", |
|
|
|
"escape", |
|
|
|
"encodeURIComponent", |
|
|
|
"encodeURI", |
|
|
|
"decodeURIComponent", |
|
|
|
"decodeURI", |
|
|
|
"isFinite", |
|
|
|
"isNaN", |
|
|
|
"parseFloat", |
|
|
|
"parseInt", |
|
|
|
"eval", |
|
|
|
"URIError", |
|
|
|
"TypeError", |
|
|
|
"SyntaxError", |
|
|
|
"ReferenceError", |
|
|
|
"RangeError", |
|
|
|
"EvalError", |
|
|
|
"break", |
|
|
|
"case", |
|
|
|
"catch", |
|
|
|
"continue", |
|
|
|
"debugger", |
|
|
|
"default", |
|
|
|
"delete", |
|
|
|
"do", |
|
|
|
"else", |
|
|
|
"finally", |
|
|
|
"for", |
|
|
|
"function", |
|
|
|
"if", |
|
|
|
"in", |
|
|
|
"instanceof", |
|
|
|
"new", |
|
|
|
"return", |
|
|
|
"switch", |
|
|
|
"this", |
|
|
|
"throw", |
|
|
|
"try", |
|
|
|
"typeof", |
|
|
|
"var", |
|
|
|
"void", |
|
|
|
"while", |
|
|
|
"with", |
|
|
|
"class", |
|
|
|
"const", |
|
|
|
"enum", |
|
|
|
"export", |
|
|
|
"extends", |
|
|
|
"import", |
|
|
|
"super", |
|
|
|
"null", |
|
|
|
"true", |
|
|
|
"false", |
|
|
|
"implements", |
|
|
|
"interface", |
|
|
|
"let", |
|
|
|
"package", |
|
|
|
"private", |
|
|
|
"protected", |
|
|
|
"public", |
|
|
|
"static", |
|
|
|
"yield", |
|
|
|
|
|
|
|
ret = AJS_HeapInit((void **) heap_array, /* heap */ |
|
|
|
(size_t *) heap_sz, /* heapSz */ |
|
|
|
ajsheap_config, /* heapConfig */ |
|
|
|
num_pools, /* numPools */ |
|
|
|
1); /* numHeaps */ |
|
|
|
fprintf(stderr, "AJS_HeapInit() -> %ld\n", (long) ret); |
|
|
|
fflush(stderr); |
|
|
|
} |
|
|
|
/*
|
|
|
|
* These strings are manually added, and would be gathered in some |
|
|
|
* application specific manner. |
|
|
|
*/ |
|
|
|
|
|
|
|
/* AjsHeap.dump(), allows Ecmascript code to dump heap status at suitable
|
|
|
|
* points. |
|
|
|
*/ |
|
|
|
duk_ret_t ajsheap_dump_binding(duk_context *ctx) { |
|
|
|
AJS_HeapDump(); |
|
|
|
fflush(stdout); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
"foo", |
|
|
|
"bar", |
|
|
|
"quux", |
|
|
|
"enableFrob", |
|
|
|
"disableFrob" |
|
|
|
/* ... */ |
|
|
|
}; |
|
|
|
|
|
|
|
void ajsheap_dump(void) { |
|
|
|
AJS_HeapDump(); |
|
|
|
fflush(stdout); |
|
|
|
} |
|
|
|
const void *ajsheap_extstr_check_2(const void *ptr, duk_size_t len) { |
|
|
|
int i, n; |
|
|
|
|
|
|
|
void ajsheap_register(duk_context *ctx) { |
|
|
|
duk_push_object(ctx); |
|
|
|
duk_push_c_function(ctx, ajsheap_dump_binding, 0); |
|
|
|
duk_put_prop_string(ctx, -2, "dump"); |
|
|
|
duk_put_global_string(ctx, "AjsHeap"); |
|
|
|
(void) safe_print_chars; /* potentially unused */ |
|
|
|
|
|
|
|
/* Linear scan. An actual implementation would need some acceleration
|
|
|
|
* structure, e.g. select a sublist based on first character. |
|
|
|
* |
|
|
|
* NOTE: input string (behind 'ptr' with 'len' bytes) DOES NOT have a |
|
|
|
* trailing NUL character. Any strings returned from this function |
|
|
|
* MUST have a trailing NUL character. |
|
|
|
*/ |
|
|
|
|
|
|
|
n = (int) (sizeof(strdata_duk_builtin_strings) / sizeof(const char *)); |
|
|
|
for (i = 0; i < n; i++) { |
|
|
|
const char *str; |
|
|
|
|
|
|
|
str = strdata_duk_builtin_strings[i]; |
|
|
|
if (strlen(str) == len && memcmp(ptr, (const void *) str, len) == 0) { |
|
|
|
#if 0 |
|
|
|
printf("ajsheap_extstr_check_2: ptr=%p, len=%ld ", |
|
|
|
(void *) ptr, (long) len); |
|
|
|
safe_print_chars((const char *) ptr, len); |
|
|
|
printf(" -> constant string index %ld\n", (long) i); |
|
|
|
#endif |
|
|
|
return (void *) strdata_duk_builtin_strings[i]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
#if 0 |
|
|
|
printf("ajsheap_extstr_check_2: ptr=%p, len=%ld ", |
|
|
|
(void *) ptr, (long) len); |
|
|
|
safe_print_chars((const char *) ptr, len); |
|
|
|
printf(" -> not found\n"); |
|
|
|
#endif |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
#else |
|
|
|
|
|
|
|
#else /* DUK_CMDLINE_AJSHEAP */ |
|
|
|
|
|
|
|
int ajs_dummy = 0; /* to avoid empty source file */ |
|
|
|
|
|
|
|
#endif /* DUK_CMDLINE_AJSHEAP */ |
|
|
|