Binary search import records.

git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3742 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
Cory McWilliams 2022-01-08 21:56:57 +00:00
parent bb81fc87b9
commit 26150f98e1

View File

@ -95,7 +95,7 @@ typedef struct _tf_task_t {
int _export_count;
exportid_t _nextExport;
import_record_t* _imports;
import_record_t** _imports;
int _import_count;
JSValue _requires;
JSValue _loadedFiles;
@ -143,64 +143,85 @@ static tf_taskstub_t* _tf_task_get_stub(tf_task_t* task, taskid_t id);
static void _tf_task_release_export(tf_taskstub_t* stub, exportid_t exportId);
typedef struct _import_record_t {
tf_task_t* _owner;
JSValue _function;
exportid_t _export;
taskid_t _task;
tf_task_t* _owner;
int _useCount;
import_record_t* _next;
} import_record_t;
static int _import_compare(const void* a, const void* b)
{
const import_record_t* ia = a;
const import_record_t* const* ib = b;
if (ia->_task != (*ib)->_task)
{
return ia->_task < (*ib)->_task ? -1 : 1;
}
else if (ia->_export != (*ib)->_export)
{
return ia->_export < (*ib)->_export ? -1 : 1;
}
else
{
return 0;
}
}
static import_record_t** _tf_task_find_import(tf_task_t* task, taskid_t task_id, exportid_t export_id)
{
if (!task->_imports)
{
return NULL;
}
import_record_t search =
{
._task = task_id,
._export = export_id,
};
import_record_t** it = bsearch(&search, task->_imports, task->_import_count, sizeof(import_record_t*), _import_compare);
return it;
}
static void _tf_task_trace_imports(tf_task_t* task)
{
tf_trace_counter(task->_trace, "imports", 1, (const char*[]) { "count" }, (int64_t[]) { task->_import_count });
}
static void _import_record_release(import_record_t* import)
static void _import_record_release(import_record_t** import)
{
JSContext* context = import->_owner->_context;
if (--import->_useCount > 0)
JSContext* context = (*import)->_owner->_context;
tf_task_t* task = (*import)->_owner;
import_record_t* record = *import;
if (--record->_useCount > 0)
{
return;
}
JS_SetOpaque(import->_function, NULL);
JS_FreeValue(context, import->_function);
import->_function = JS_UNDEFINED;
_tf_task_release_export(_tf_task_get_stub(import->_owner, import->_task), import->_export);
JS_SetOpaque(record->_function, NULL);
JS_FreeValue(context, record->_function);
record->_function = JS_UNDEFINED;
_tf_task_release_export(_tf_task_get_stub(task, record->_task), record->_export);
for (import_record_t** it = &import->_owner->_imports;
*it;
it = &(*it)->_next)
{
if (*it == import)
{
*it = import->_next;
import->_owner->_import_count--;
_tf_task_trace_imports(import->_owner);
import->_next = NULL;
break;
}
}
int index = import - task->_imports;
memmove(import, import + 1, sizeof(import_record_t*) * (task->_import_count - index - 1));
task->_import_count--;
_tf_task_trace_imports(task);
free(import);
free(record);
}
static void _import_record_release_for_task(tf_task_t* task, taskid_t task_id)
{
bool any = false;
import_record_t** next = NULL;
for (import_record_t** it = &task->_imports;
*it;
it = next)
for (int i = 0; i < task->_import_count; i++)
{
next = &(*it)->_next;
if ((*it)->_task == task_id)
if (task->_imports[i]->_task == task_id)
{
import_record_t* import = *it;
_import_record_release(import);
next = it;
_import_record_release(&task->_imports[i]);
any = true;
--i;
}
}
@ -644,12 +665,34 @@ static JSValue _tf_task_getFile(JSContext* context, JSValueConst this_val, int a
return result;
}
const char* _tf_task_get_message_type(tf_task_message_t type)
{
switch (type)
{
case kResolvePromise: return "kResolvePromise";
case kRejectPromise: return "kRejectPromise";
case kInvokeExport: return "kInvokeExport";
case kReleaseExport: return "kReleaseExport";
case kReleaseImport: return "kReleaseImport";
case kSetRequires: return "kSetRequires";
case kActivate: return "kActivate";
case kExecute: return "kExecute";
case kKill: return "kKill";
case kSetImports: return "kSetImports";
case kGetExports: return "kGetExports";
case kLoadFile: return "kLoadFile";
case kTaskError: return "kTaskError";
case kTaskTrace: return "kTaskTrace";
}
return "unknown";
}
void tf_task_on_receive_packet(int packetType, const char* begin, size_t length, void* userData)
{
tf_taskstub_t* stub = userData;
tf_taskstub_t* from = stub;
tf_task_t* to = tf_taskstub_get_owner(stub);
tf_trace_begin(to->_trace, "tf_task_on_receive_packet");
tf_trace_begin(to->_trace, _tf_task_get_message_type(packetType));
switch (packetType)
{
@ -721,13 +764,10 @@ void tf_task_on_receive_packet(int packetType, const char* begin, size_t length,
assert(length == sizeof(exportid_t));
exportid_t exportId;
memcpy(&exportId, begin, sizeof(exportId));
for (import_record_t* it = to->_imports; it; it = it->_next)
import_record_t** it = _tf_task_find_import(to, tf_taskstub_get_id(from), exportId);
if (it)
{
if (it->_task == tf_taskstub_get_id(from) && it->_export == exportId)
{
_import_record_release(it);
break;
}
_import_record_release(it);
}
}
break;
@ -1091,7 +1131,10 @@ promiseid_t tf_task_allocate_promise(tf_task_t* task)
promise.values[0] = JS_NewPromiseCapability(task->_context, &promise.values[1]);
int index = _insert_index((void*)(intptr_t)promiseId, task->_promises, task->_promise_count, sizeof(promise_t), _promise_compare);
task->_promises = realloc(task->_promises, sizeof(promise_t) * (task->_promise_count + 1));
memmove(task->_promises + index, task->_promises + index + 1, sizeof(promise_t) * (task->_promise_count - index));
if (task->_promise_count - index)
{
memmove(task->_promises + index + 1, task->_promises + index, sizeof(promise_t) * (task->_promise_count - index));
}
task->_promises[index] = promise;
task->_promise_count++;
_tf_task_trace_promises(task);
@ -1187,7 +1230,11 @@ void tf_task_remove_child(tf_task_t* task, tf_taskstub_t* child)
static void _import_finalizer(JSRuntime* runtime, JSValue value)
{
import_record_t* import = JS_GetOpaque(value, _import_class_id);
_import_record_release(import);
if (import)
{
import_record_t** it = _tf_task_find_import(import->_owner, import->_task, import->_export);
_import_record_release(it);
}
}
static void _import_mark_func(JSRuntime* runtime, JSValueConst value, JS_MarkFunc mark_func)
@ -1346,15 +1393,14 @@ JSContext* tf_task_get_context(tf_task_t* task)
void tf_task_destroy(tf_task_t* task)
{
import_record_t* it = task->_imports;
while (it)
for (int i = 0; i < task->_import_count; i++)
{
import_record_t* next = it->_next;
JS_FreeValue(task->_context, it->_function);
free(it);
it = next;
JS_FreeValue(task->_context, task->_imports[i]->_function);
free(task->_imports[i]);
}
free(task->_imports);
task->_imports = NULL;
task->_import_count = 0;
while (task->_exports)
{
@ -1429,10 +1475,15 @@ JSValue tf_task_add_import(tf_task_t* task, taskid_t stub_id, exportid_t export_
._owner = task,
._task = stub_id,
._useCount = 1,
._next = task->_imports,
};
task->_imports = import;
int index = _insert_index(import, task->_imports, task->_import_count, sizeof(import_record_t*), _import_compare);
task->_imports = realloc(task->_imports, sizeof(import_record_t*) * (task->_import_count + 1));
if (task->_import_count - index)
{
memmove(task->_imports + index + 1, task->_imports + index, sizeof(import_record_t*) * (task->_import_count - index));
}
task->_imports[index] = import;
task->_import_count++;
_tf_task_trace_imports(task);
return function;