Add engine-internal convenience macro for allocating typed arrays, improve error message.

PiperOrigin-RevId: 705126655
Change-Id: I2bd8fada6d33a919d2fb82297f93ac57958355a4
This commit is contained in:
Yuval Tassa
2024-12-11 09:03:39 -08:00
committed by Copybara-Service
parent 3ca97248a3
commit 2691887500
25 changed files with 283 additions and 274 deletions
+37 -19
View File
@@ -931,7 +931,7 @@ static void makeDofDofSparse(const mjModel* m, mjData* d,
}
mj_markStack(d);
int* remaining = mj_stackAllocInt(d, nv);
int* remaining = mjSTACKALLOC(d, nv, int);
// compute rownnz
mju_zeroInt(rownnz, nv);
@@ -1044,7 +1044,7 @@ static void makeBSparse(const mjModel* m, mjData* d) {
// allocate and clear incremental row counts
mj_markStack(d);
int* cnt = mj_stackAllocInt(d, nbody);
int* cnt = mjSTACKALLOC(d, nbody, int);
mju_zeroInt(cnt, nbody);
// add subtree dofs to colind
@@ -1134,7 +1134,7 @@ static void copyM2Sparse(const mjModel* m, mjData* d, int* dst, const int* src,
mj_markStack(d);
// init remaining
int* remaining = mj_stackAllocInt(d, nv);
int* remaining = mjSTACKALLOC(d, nv, int);
mju_copyInt(remaining, rownnz, nv);
// copy data
@@ -1202,7 +1202,7 @@ static void makeDmap(const mjModel* m, mjData* d) {
mj_markStack(d);
// make mapM2D
int* M = mj_stackAllocInt(d, nM);
int* M = mjSTACKALLOC(d, nM, int);
for (int i=0; i < nM; i++) M[i] = i;
for (int i=0; i < nD; i++) d->mapM2D[i] = -1;
copyM2Sparse(m, d, d->mapM2D, M, /*reduced=*/0);
@@ -1215,7 +1215,7 @@ static void makeDmap(const mjModel* m, mjData* d) {
}
// make mapD2M
int* D = mj_stackAllocInt(d, nD);
int* D = mjSTACKALLOC(d, nD, int);
for (int i=0; i < nD; i++) D[i] = i;
for (int i=0; i < nM; i++) d->mapD2M[i] = -1;
copyD2MSparse(m, d, d->mapD2M, D);
@@ -1591,7 +1591,8 @@ void* mj_arenaAllocByte(mjData* d, size_t bytes, size_t alignment) {
// internal: allocate size bytes on the provided stack shard
// declared inline so that modular arithmetic with specific alignments can be optimized out
static inline void* stackallocinternal(mjData* d, mjStackInfo* stack_info, size_t size, size_t alignment) {
static inline void* stackallocinternal(mjData* d, mjStackInfo* stack_info, size_t size,
size_t alignment, const char* caller, int line) {
// return NULL if empty
if (mjUNLIKELY(!size)) {
return NULL;
@@ -1614,10 +1615,19 @@ static inline void* stackallocinternal(mjData* d, mjStackInfo* stack_info, size_
size_t stack_available_bytes = stack_info->top - stack_info->limit;
size_t stack_required_bytes = stack_info->top - new_top_ptr;
if (mjUNLIKELY(stack_required_bytes > stack_available_bytes)) {
mju_error("mj_stackAlloc: insufficient memory: max = %zu, available = %zu, requested = %zu "
"(ne = %d, nf = %d, nefc = %d, ncon = %d)",
char info[1024];
if (caller) {
snprintf(info, sizeof(info), " at %s, line %d", caller, line);
} else {
info[0] = '\0';
}
mju_error("mj_stackAlloc: out of memory, stack overflow%s\n"
" max = %zu, available = %zu, requested = %zu\n"
" nefc = %d, ncon = %d",
info,
stack_info->bottom - stack_info->limit, stack_available_bytes, stack_required_bytes,
d->ne, d->nf, d->nefc, d->ncon);
d->nefc, d->ncon);
}
#ifdef ADDRESS_SANITIZER
@@ -1652,20 +1662,20 @@ static inline void* stackallocinternal(mjData* d, mjStackInfo* stack_info, size_
// internal: allocate size bytes in mjData
// declared inline so that modular arithmetic with specific alignments can be optimized out
static inline void* stackalloc(mjData* d, size_t size, size_t alignment) {
static inline void* stackalloc(mjData* d, size_t size, size_t alignment,
const char* caller, int line) {
// single threaded allocation
if (!d->threadpool) {
mjStackInfo stack_info = get_stack_info_from_data(d);
void* result = stackallocinternal(d, &stack_info, size, alignment);
void* result = stackallocinternal(d, &stack_info, size, alignment, caller, line);
d->pstack = stack_info.bottom - stack_info.top;
return result;
}
// multi threaded allocation
size_t thread_id = mju_threadPoolCurrentWorkerId((mjThreadPool*)d->threadpool);
mjStackInfo* stack_info = mju_getStackInfoForThread(d, thread_id);
return stackallocinternal(d, stack_info, size, alignment);
return stackallocinternal(d, stack_info, size, alignment, caller, line);
}
@@ -1677,7 +1687,7 @@ __attribute__((always_inline))
static inline void markstackinternal(mjData* d, mjStackInfo* stack_info) {
size_t top_old = stack_info->top;
mjStackFrame* s =
(mjStackFrame*) stackallocinternal(d, stack_info, sizeof(mjStackFrame), _Alignof(mjStackFrame));
(mjStackFrame*) stackallocinternal(d, stack_info, sizeof(mjStackFrame), _Alignof(mjStackFrame), NULL, 0);
s->pbase = stack_info->stack_base;
s->pstack = top_old;
#ifdef ADDRESS_SANITIZER
@@ -1779,7 +1789,15 @@ size_t mj_stackBytesAvailable(mjData* d) {
// allocate bytes on the stack
void* mj_stackAllocByte(mjData* d, size_t bytes, size_t alignment) {
return stackalloc(d, bytes, alignment);
return stackalloc(d, bytes, alignment, NULL, 0);
}
// allocate bytes on the stack, with caller information
void* mj_stackAllocInfo(mjData* d, size_t bytes, size_t alignment,
const char* caller, int line) {
return stackalloc(d, bytes, alignment, caller, line);
}
@@ -1789,7 +1807,7 @@ mjtNum* mj_stackAllocNum(mjData* d, size_t size) {
if (mjUNLIKELY(size >= SIZE_MAX / sizeof(mjtNum))) {
mjERROR("requested size is too large (more than 2^64 bytes).");
}
return (mjtNum*) stackalloc(d, size * sizeof(mjtNum), _Alignof(mjtNum));
return (mjtNum*) stackalloc(d, size * sizeof(mjtNum), _Alignof(mjtNum), NULL, 0);
}
@@ -1799,7 +1817,7 @@ int* mj_stackAllocInt(mjData* d, size_t size) {
if (mjUNLIKELY(size >= SIZE_MAX / sizeof(int))) {
mjERROR("requested size is too large (more than 2^64 bytes).");
}
return (int*) stackalloc(d, size * sizeof(int), _Alignof(int));
return (int*) stackalloc(d, size * sizeof(int), _Alignof(int), NULL, 0);
}