8sa1-gcc/gcc/d/dmd/root/stringtable.c
Iain Buclaw a3b38b7781 d: Merge upstream dmd 7132b3537
Splits out all semantic passes for Dsymbol, Type, and TemplateParameter
nodes into Visitors in separate files, and the copyright years of all
sources have been updated.

Reviewed-on: https://github.com/dlang/dmd/pull/12190

gcc/d/ChangeLog:

	* dmd/MERGE: Merge upstream dmd 7132b3537.
	* Make-lang.in (D_FRONTEND_OBJS): Add d/dsymbolsem.o, d/semantic2.o,
	d/semantic3.o, and d/templateparamsem.o.
	* d-compiler.cc (Compiler::genCmain): Update calls to semantic
	entrypoint functions.
	* d-lang.cc (d_parse_file): Likewise.
	* typeinfo.cc (make_frontend_typeinfo): Likewise.
2021-02-13 12:50:45 +01:00

197 lines
5.2 KiB
C

/* Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* http://www.digitalmars.com
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
* https://github.com/D-Programming-Language/dmd/blob/master/src/root/stringtable.c
*/
#include "dsystem.h" // uint{8|16|32}_t, memcpy()
#include "root.h"
#include "rmem.h" // mem
#include "stringtable.h"
#include "hash.h"
#define POOL_BITS 12
#define POOL_SIZE (1U << POOL_BITS)
struct StringEntry
{
uint32_t hash;
uint32_t vptr;
};
uint32_t StringTable::allocValue(const char *s, size_t length, void *ptrvalue)
{
const size_t nbytes = sizeof(StringValue) + length + 1;
if (!npools || nfill + nbytes > POOL_SIZE)
{
pools = (uint8_t **)mem.xrealloc(pools, ++npools * sizeof(pools[0]));
pools[npools - 1] = (uint8_t *)mem.xmalloc(nbytes > POOL_SIZE ? nbytes : POOL_SIZE);
nfill = 0;
}
StringValue *sv = (StringValue *)&pools[npools - 1][nfill];
sv->ptrvalue = ptrvalue;
sv->length = length;
::memcpy(sv->lstring(), s, length);
sv->lstring()[length] = 0;
const uint32_t vptr = (uint32_t)(npools << POOL_BITS | nfill);
nfill += nbytes + (-nbytes & 7); // align to 8 bytes
return vptr;
}
StringValue *StringTable::getValue(uint32_t vptr)
{
if (!vptr) return NULL;
const size_t idx = (vptr >> POOL_BITS) - 1;
const size_t off = vptr & (POOL_SIZE - 1);
return (StringValue *)&pools[idx][off];
}
static size_t nextpow2(size_t val)
{
size_t res = 1;
while (res < val)
res <<= 1;
return res;
}
static const double loadFactor = 0.8;
void StringTable::_init(size_t size)
{
size = nextpow2((size_t)(size / loadFactor));
if (size < 32) size = 32;
table = (StringEntry *)mem.xcalloc(size, sizeof(table[0]));
tabledim = size;
pools = NULL;
npools = nfill = 0;
count = 0;
}
void StringTable::reset(size_t size)
{
for (size_t i = 0; i < npools; ++i)
mem.xfree(pools[i]);
mem.xfree(table);
mem.xfree(pools);
table = NULL;
pools = NULL;
_init(size);
}
StringTable::~StringTable()
{
for (size_t i = 0; i < npools; ++i)
mem.xfree(pools[i]);
mem.xfree(table);
mem.xfree(pools);
table = NULL;
pools = NULL;
}
size_t StringTable::findSlot(hash_t hash, const char *s, size_t length)
{
// quadratic probing using triangular numbers
// http://stackoverflow.com/questions/2348187/moving-from-linear-probing-to-quadratic-probing-hash-collisons/2349774#2349774
for (size_t i = hash & (tabledim - 1), j = 1; ;++j)
{
StringValue *sv;
if (!table[i].vptr ||
(table[i].hash == hash &&
(sv = getValue(table[i].vptr))->length == length &&
::memcmp(s, sv->lstring(), length) == 0))
return i;
i = (i + j) & (tabledim - 1);
}
}
StringValue *StringTable::lookup(const char *s, size_t length)
{
const hash_t hash = calcHash(s, length);
const size_t i = findSlot(hash, s, length);
// printf("lookup %.*s %p\n", (int)length, s, table[i].value ?: NULL);
return getValue(table[i].vptr);
}
StringValue *StringTable::update(const char *s, size_t length)
{
const hash_t hash = calcHash(s, length);
size_t i = findSlot(hash, s, length);
if (!table[i].vptr)
{
if (++count > tabledim * loadFactor)
{
grow();
i = findSlot(hash, s, length);
}
table[i].hash = hash;
table[i].vptr = allocValue(s, length, NULL);
}
// printf("update %.*s %p\n", (int)length, s, table[i].value ?: NULL);
return getValue(table[i].vptr);
}
StringValue *StringTable::insert(const char *s, size_t length, void *ptrvalue)
{
const hash_t hash = calcHash(s, length);
size_t i = findSlot(hash, s, length);
if (table[i].vptr)
return NULL; // already in table
if (++count > tabledim * loadFactor)
{
grow();
i = findSlot(hash, s, length);
}
table[i].hash = hash;
table[i].vptr = allocValue(s, length, ptrvalue);
// printf("insert %.*s %p\n", (int)length, s, table[i].value ?: NULL);
return getValue(table[i].vptr);
}
void StringTable::grow()
{
const size_t odim = tabledim;
StringEntry *otab = table;
tabledim *= 2;
table = (StringEntry *)mem.xcalloc(tabledim, sizeof(table[0]));
for (size_t i = 0; i < odim; ++i)
{
StringEntry *se = &otab[i];
if (!se->vptr) continue;
StringValue *sv = getValue(se->vptr);
table[findSlot(se->hash, sv->lstring(), sv->length)] = *se;
}
mem.xfree(otab);
}
/********************************
* Walk the contents of the string table,
* calling fp for each entry.
* Params:
* fp = function to call. Returns !=0 to stop
* Returns:
* last return value of fp call
*/
int StringTable::apply(int (*fp)(StringValue *))
{
for (size_t i = 0; i < tabledim; ++i)
{
StringEntry *se = &table[i];
if (!se->vptr) continue;
StringValue *sv = getValue(se->vptr);
int result = (*fp)(sv);
if (result)
return result;
}
return 0;
}