MIRROR: javascript for 馃悳's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 253 lines 6.7 kB view raw
1#ifndef ANT_OBJECT_H 2#define ANT_OBJECT_H 3 4#include "types.h" 5#include "sugar.h" 6#include "shapes.h" 7 8#include <utarray.h> 9#include <stdbool.h> 10#include <stddef.h> 11#include <stdint.h> 12#include <stdlib.h> 13 14typedef struct { 15 ant_value_t (*getter)(ant_t *, ant_value_t, const char *, size_t); 16 bool (*setter)(ant_t *, ant_value_t, const char *, size_t, ant_value_t); 17 bool (*deleter)(ant_t *, ant_value_t, const char *, size_t); 18} ant_exotic_ops_t; 19 20typedef struct promise_handler { 21 ant_value_t onFulfilled; 22 ant_value_t onRejected; 23 ant_value_t nextPromise; 24 struct coroutine *await_coro; 25} promise_handler_t; 26 27typedef struct { 28 ant_value_t value; 29 ant_value_t trigger_parent; 30 31 struct ant_object *gc_pending_next; 32 promise_handler_t inline_handler; 33 34 UT_array *handlers; 35 uint32_t promise_id; 36 uint16_t handler_count; 37 uint8_t state; 38 39 bool trigger_queued; 40 bool has_rejection_handler; 41 bool processing; 42 bool unhandled_reported; 43 bool gc_pending_rooted; 44} ant_promise_state_t; 45 46typedef struct { 47 ant_value_t target; 48 ant_value_t handler; 49 bool revoked; 50} ant_proxy_state_t; 51 52typedef struct { 53 uint8_t slot; 54 ant_value_t value; 55} ant_extra_slot_t; 56 57typedef struct { 58 ant_value_t token; 59 ant_value_t value; 60 ant_value_t getter; 61 ant_value_t setter; 62 63 uint32_t hash; 64 uint8_t kind; 65 uint8_t occupied; 66} ant_private_entry_t; 67 68typedef struct { 69 ant_private_entry_t *entries; 70 uint32_t count; 71 uint32_t cap; 72} ant_private_table_t; 73 74typedef struct { 75 void *ptr; 76 uint32_t tag; 77} ant_native_entry_t; 78 79typedef struct { 80 ant_extra_slot_t *extra_slots; 81 ant_native_entry_t *native_entries; 82 ant_private_table_t private_table; 83 ant_proxy_state_t *proxy_state; 84 85 uint8_t native_count; 86 uint8_t native_cap; 87 uint8_t extra_count; 88 uint8_t flags; 89} ant_object_sidecar_t; 90 91_Static_assert( 92 _Alignof(ant_object_sidecar_t) > ant_sidecar, 93 "object sidecar pointer uses low-bit tag" 94); 95 96typedef struct ant_prop_ref { 97 ant_object_t *obj; 98 uint32_t slot; 99 bool valid; 100} ant_prop_ref_t; 101 102typedef struct ant_object { 103 struct ant_object *next; 104 105 ant_value_t proto; 106 ant_shape_t *shape; 107 ant_value_t *overflow_prop; 108 109 const ant_exotic_ops_t *exotic_ops; 110 ant_value_t (*exotic_keys)(ant_t *, ant_value_t); 111 112 ant_promise_state_t *promise_state; 113 ant_extra_slot_t *extra_slots; 114 115 void (*finalizer)(ant_t *, struct ant_object *); 116 ant_value_t inobj[ANT_INOBJ_MAX_SLOTS]; 117 ant_native_entry_t native; 118 119 union { 120 struct { ant_value_t *data; uint32_t len; uint32_t cap; } array; 121 struct { sv_closure_t *closure; } func; 122 struct { ant_value_t value; } data; 123 } u; 124 125 uint32_t prop_count; 126 uint32_t propref_count; 127 128 uint8_t mark_epoch; 129 uint8_t type_tag; 130 uint8_t inobj_limit; 131 uint8_t extra_count; 132 uint8_t overflow_cap; 133 134 uint8_t extensible: 1; 135 uint8_t frozen: 1; 136 uint8_t sealed: 1; 137 uint8_t is_exotic: 1; 138 uint8_t is_constructor: 1; 139 uint8_t fast_array: 1; 140 uint8_t may_have_holes: 1; 141 uint8_t may_have_dense_elements: 1; 142 uint8_t gc_permanent: 1; 143 uint8_t generation: 1; 144 uint8_t in_remember_set: 1; 145} ant_object_t; 146 147static inline bool ant_object_has_sidecar(const ant_object_t *obj) { 148 return obj && (((uintptr_t)obj->extra_slots & ant_sidecar) != 0); 149} 150 151static inline ant_object_sidecar_t *ant_object_sidecar(const ant_object_t *obj) { 152 if (!ant_object_has_sidecar(obj)) return NULL; 153 return (ant_object_sidecar_t *)((uintptr_t)obj->extra_slots & ~ant_sidecar); 154} 155 156static inline ant_extra_slot_t *ant_object_extra_slots_ptr(const ant_object_t *obj) { 157 if (!obj) return NULL; 158 uintptr_t raw = (uintptr_t)obj->extra_slots; 159 if ((raw & ant_sidecar) == 0) return obj->extra_slots; 160 return ((ant_object_sidecar_t *)(raw & ~ant_sidecar))->extra_slots; 161} 162 163static inline uint8_t ant_object_extra_count(const ant_object_t *obj) { 164 if (!obj) return 0; 165 uintptr_t raw = (uintptr_t)obj->extra_slots; 166 if ((raw & ant_sidecar) == 0) return obj->extra_count; 167 return ((ant_object_sidecar_t *)(raw & ~ant_sidecar))->extra_count; 168} 169 170static inline ant_extra_slot_t *ant_object_extra_slots(const ant_object_t *obj, uint8_t *count) { 171 if (!obj) { 172 if (count) *count = 0; 173 return NULL; 174 } 175 176 uintptr_t raw = (uintptr_t)obj->extra_slots; 177 if ((raw & ant_sidecar) == 0) { 178 if (count) *count = obj->extra_count; 179 return obj->extra_slots; 180 } 181 182 ant_object_sidecar_t *sidecar = (ant_object_sidecar_t *)(raw & ~ant_sidecar); 183 if (count) *count = sidecar->extra_count; 184 return sidecar->extra_slots; 185} 186 187static inline ant_extra_slot_t *ant_object_extra_slot(const ant_object_t *obj, uint8_t slot) { 188 if (!obj) return NULL; 189 190 uint8_t count = obj->extra_count; 191 ant_extra_slot_t *entries = obj->extra_slots; 192 193 uintptr_t raw = (uintptr_t)obj->extra_slots; 194 if ((raw & ant_sidecar) != 0) { 195 ant_object_sidecar_t *sidecar = (ant_object_sidecar_t *)(raw & ~ant_sidecar); 196 count = sidecar->extra_count; 197 entries = sidecar->extra_slots; 198 } 199 200 for (uint8_t i = 0; i < count; i++) 201 if (entries[i].slot == slot) return &entries[i]; 202 203 return NULL; 204} 205 206static inline ant_object_sidecar_t *ant_object_ensure_sidecar(ant_object_t *obj) { 207 if (!obj) return NULL; 208 209 ant_object_sidecar_t *sidecar = ant_object_sidecar(obj); 210 if (sidecar) return sidecar; 211 212 sidecar = (ant_object_sidecar_t *)calloc(1, sizeof(*sidecar)); 213 if (!sidecar) return NULL; 214 215 sidecar->extra_slots = obj->extra_slots; 216 sidecar->extra_count = obj->extra_count; 217 218 obj->extra_slots = (ant_extra_slot_t *)((uintptr_t)sidecar | ant_sidecar); 219 obj->extra_count = 0; 220 221 return sidecar; 222} 223 224static inline ant_proxy_state_t *ant_object_proxy_state(const ant_object_t *obj) { 225 ant_object_sidecar_t *sidecar = ant_object_sidecar(obj); 226 return sidecar ? sidecar->proxy_state : NULL; 227} 228 229static inline ant_private_table_t *ant_object_private_table(const ant_object_t *obj) { 230 ant_object_sidecar_t *sidecar = ant_object_sidecar(obj); 231 return sidecar ? (ant_private_table_t *)&sidecar->private_table : NULL; 232} 233 234static inline uint32_t ant_object_inobj_limit(const ant_object_t *obj) { 235 if (!obj) return ANT_INOBJ_MAX_SLOTS; 236 uint32_t limit = obj->inobj_limit; 237 return (limit > ANT_INOBJ_MAX_SLOTS) ? ANT_INOBJ_MAX_SLOTS : limit; 238} 239 240static inline ant_value_t ant_object_prop_get_unchecked(const ant_object_t *obj, uint32_t slot) { 241 uint32_t inobj_limit = ant_object_inobj_limit(obj); 242 return (slot < inobj_limit) 243 ? obj->inobj[slot] 244 : obj->overflow_prop[slot - inobj_limit]; 245} 246 247static inline void ant_object_prop_set_unchecked(ant_object_t *obj, uint32_t slot, ant_value_t value) { 248 uint32_t inobj_limit = ant_object_inobj_limit(obj); 249 if (slot < inobj_limit) obj->inobj[slot] = value; 250 else obj->overflow_prop[slot - inobj_limit] = value; 251} 252 253#endif