Beispiel #1
0
static duk_hstring *duk__do_intern(duk_heap *heap, duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
	duk_hstring *res;

	if (duk__recheck_strtab_size(heap, heap->st_used + 1)) {
		return NULL;
	}

	res = duk__alloc_init_hstring(heap, str, blen, strhash);
	if (!res) {
		return NULL;
	}

	duk__insert_hstring(heap, heap->st, heap->st_size, &heap->st_used, res);  /* guaranteed to succeed */

	/* Note: hstring is in heap but has refcount zero and is not strongly reachable.
	 * Caller should increase refcount and make the hstring reachable before any
	 * operations which require allocation (and possible gc).
	 */

	return res;
}
static duk_hstring *duk__do_intern(duk_heap *heap, duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
	duk_hstring *res;

	if (duk__recheck_strtab_size(heap, heap->st_used + 1)) {
		return NULL;
	}

	/* For manual testing only. */
#if 0
	{
		duk_size_t i;
		printf("INTERN: \"");
		for (i = 0; i < blen; i++) {
			duk_uint8_t x = str[i];
			if (x >= 0x20 && x <= 0x7e && x != '"' && x != '\\') {
				printf("%c", (int) x);  /* char: use int cast */
			} else {
				printf("\\x%02lx", (long) x);
			}
		}
		printf("\"\n");
	}
#endif

	res = duk__alloc_init_hstring(heap, str, blen, strhash);
	if (!res) {
		return NULL;
	}

	duk__insert_hstring(heap, heap->st, heap->st_size, &heap->st_used, res);  /* guaranteed to succeed */

	/* Note: hstring is in heap but has refcount zero and is not strongly reachable.
	 * Caller should increase refcount and make the hstring reachable before any
	 * operations which require allocation (and possible gc).
	 */

	return res;
}
Beispiel #3
0
static int duk__resize_strtab_raw(duk_heap *heap, duk_uint32_t new_size) {
#ifdef DUK_USE_MARK_AND_SWEEP
	int prev_mark_and_sweep_base_flags;
#endif
#ifdef DUK_USE_DEBUG
	duk_uint32_t old_used = heap->st_used;
#endif
	duk_uint32_t old_size = heap->st_size;
	duk_hstring **old_entries = heap->st;
	duk_hstring **new_entries = NULL;
	duk_uint32_t new_used = 0;
	duk_uint32_t i;

#ifdef DUK_USE_DEBUG
	DUK_UNREF(old_used);  /* unused with some debug level combinations */
#endif

#ifdef DUK_USE_DDDPRINT
	DUK_DDD(DUK_DDDPRINT("attempt to resize stringtable: %d entries, %d bytes, %d used, %d%% load -> %d entries, %d bytes, %d used, %d%% load",
	                     (int) old_size, (int) (sizeof(duk_hstring *) * old_size), (int) old_used,
	                     (int) (((double) old_used) / ((double) old_size) * 100.0),
	                     (int) new_size, (int) (sizeof(duk_hstring *) * new_size), (int) duk__count_used(heap),
	                     (int) (((double) duk__count_used(heap)) / ((double) new_size) * 100.0)));
#endif

	DUK_ASSERT(new_size > (duk_uint32_t) duk__count_used(heap));  /* required for rehash to succeed, equality not that useful */
	DUK_ASSERT(old_entries);
#ifdef DUK_USE_MARK_AND_SWEEP
	DUK_ASSERT((heap->mark_and_sweep_base_flags & DUK_MS_FLAG_NO_STRINGTABLE_RESIZE) == 0);
#endif

	/*
	 *  The attempt to allocate may cause a GC.  Such a GC must not attempt to resize
	 *  the stringtable (though it can be swept); finalizer execution and object
	 *  compaction must also be postponed to avoid the pressure to add strings to the
	 *  string table.
	 */

#ifdef DUK_USE_MARK_AND_SWEEP
	prev_mark_and_sweep_base_flags = heap->mark_and_sweep_base_flags;
	heap->mark_and_sweep_base_flags |= \
	        DUK_MS_FLAG_NO_STRINGTABLE_RESIZE |  /* avoid recursive call here */
	        DUK_MS_FLAG_NO_FINALIZERS |          /* avoid pressure to add/remove strings */
	        DUK_MS_FLAG_NO_OBJECT_COMPACTION;    /* avoid array abandoning which interns strings */
#endif

	new_entries = (duk_hstring **) DUK_ALLOC(heap, sizeof(duk_hstring *) * new_size);

#ifdef DUK_USE_MARK_AND_SWEEP
	heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags;
#endif

	if (!new_entries) {
		goto error;
	}

#ifdef DUK_USE_EXPLICIT_NULL_INIT
	for (i = 0; i < new_size; i++) {
		new_entries[i] = NULL;
	}
#else
	DUK_MEMZERO(new_entries, sizeof(duk_hstring *) * new_size);
#endif

	/* Because new_size > duk__count_used(heap), guaranteed to work */
	for (i = 0; i < old_size; i++) {
		duk_hstring *e;

		e = old_entries[i];
		if (e == NULL || e == DUK__DELETED_MARKER(heap)) {
			continue;
		}
		/* checking for DUK__DELETED_MARKER is not necessary here, but helper does it now */
		duk__insert_hstring(heap, new_entries, new_size, &new_used, e);
	}

#ifdef DUK_USE_DDPRINT
	DUK_DD(DUK_DDPRINT("resized stringtable: %d entries, %d bytes, %d used, %d%% load -> %d entries, %d bytes, %d used, %d%% load",
	                   (int) old_size, (int) (sizeof(duk_hstring *) * old_size), (int) old_used,
	                   (int) (((double) old_used) / ((double) old_size) * 100.0),
	                   (int) new_size, (int) (sizeof(duk_hstring *) * new_size), (int) new_used,
	                   (int) (((double) new_used) / ((double) new_size) * 100.0)));
#endif

	DUK_FREE(heap, heap->st);
	heap->st = new_entries;
	heap->st_size = new_size;
	heap->st_used = new_used;  /* may be less, since DELETED entries are NULLed by rehash */

	return 0;  /* OK */

 error:
	DUK_FREE(heap, new_entries);
	return 1;  /* FAIL */
}