#include "block.h"
#include "core/platform.h"
#include "../mem/heap.h"
#include "../ops/ops.h"
#include "../table/sym.h"
__attribute__((weak))
ray_t* ray_alloc(size_t size) {
if (size < 32) size = 32;
size = (size + 4095) & ~(size_t)4095;
void* p = ray_vm_alloc(size);
if (!p) return ray_error("oom", NULL);
return (ray_t*)p;
}
size_t ray_block_size(ray_t* v) {
if (ray_is_atom(v)) return 32;
if (v->type == RAY_LIST) return 32 + (size_t)ray_len(v) * sizeof(ray_t*);
if (v->type == RAY_TABLE || v->type == RAY_DICT) return 32 + 2 * sizeof(ray_t*);
if (v->type == RAY_SEL) {
int64_t nrows = ray_len(v);
if (nrows < 0) return 32;
uint32_t n_segs = (uint32_t)((nrows + RAY_MORSEL_ELEMS - 1) / RAY_MORSEL_ELEMS);
uint32_t n_words = (uint32_t)((nrows + 63) / 64);
size_t dsz = sizeof(ray_sel_meta_t);
dsz += (n_segs + 7u) & ~(size_t)7;
dsz += ((size_t)n_segs * 2 + 7u) & ~(size_t)7;
dsz += (size_t)n_words * 8;
return 32 + dsz;
}
int8_t t = ray_type(v);
if (t <= 0 || t >= RAY_TYPE_COUNT) return 32;
return 32 + (size_t)ray_len(v) * ray_sym_elem_size(t, v->attrs);
}
ray_t* ray_block_copy(ray_t* src) {
size_t sz = ray_block_size(src);
ray_t* dst = ray_alloc(sz);
if (!dst) return ray_error("oom", NULL);
uint8_t new_mmod = dst->mmod;
uint8_t new_order = dst->order;
memcpy(dst, src, sz);
dst->mmod = new_mmod;
dst->order = new_order;
ray_atomic_store(&dst->rc, 1);
if (!ray_retain_owned_refs(dst)) {
ray_free(dst);
return ray_error("oom", NULL);
}
return dst;
}