static void free_binary(ErtsIOQBinary *b, int driver) { if (driver) driver_free_binary(&b->driver); else if (erts_refc_dectest(&b->nif.intern.refc, 0) == 0) erts_bin_free(&b->nif); }
static int iol2v_state_destructor(Binary *data) { iol2v_state_t *state = ERTS_MAGIC_BIN_UNALIGNED_DATA(data); DESTROY_SAVED_ESTACK(&state->estack); if (state->acc != NULL) { erts_bin_free(state->acc); } return 1; }
void enif_release_resource(void* obj) { ErlNifResource* resource = DATA_TO_RESOURCE(obj); ErtsBinary* bin = ERTS_MAGIC_BIN_FROM_DATA(resource); ASSERT(ERTS_MAGIC_BIN_DESTRUCTOR(bin) == &nif_resource_dtor); #ifdef DEBUG erts_refc_dec(&resource->nif_refc, 0); #endif if (erts_refc_dectest(&bin->binary.refc, 0) == 0) { erts_bin_free(&bin->binary); } }
static void decrement_refc(BeamCodeHeader* code_hdr) { struct erl_off_heap_header* oh = code_hdr->literals_off_heap; while (oh) { Binary* bptr; ASSERT(thing_subtag(oh->thing_word) == REFC_BINARY_SUBTAG); bptr = ((ProcBin*)oh)->val; if (erts_refc_dectest(&bptr->refc, 0) == 0) { erts_bin_free(bptr); } oh = oh->next; } }
void enif_release_binary(ErlNifBinary* bin) { if (bin->ref_bin != NULL) { Binary* refbin = bin->ref_bin; ASSERT(bin->bin_term == THE_NON_VALUE); if (erts_refc_dectest(&refbin->refc, 0) == 0) { erts_bin_free(refbin); } } #ifdef DEBUG bin->data = NULL; bin->bin_term = THE_NON_VALUE; bin->ref_bin = NULL; #endif }
static void decrement_refc(BeamInstr* code) { struct erl_off_heap_header* oh = (struct erl_off_heap_header *) code[MI_LITERALS_OFF_HEAP]; while (oh) { Binary* bptr; ASSERT(thing_subtag(oh->thing_word) == REFC_BINARY_SUBTAG); bptr = ((ProcBin*)oh)->val; if (erts_refc_dectest(&bptr->refc, 0) == 0) { erts_bin_free(bptr); } oh = oh->next; } }
void erts_cleanup_offheap(ErlOffHeap *offheap) { union erl_off_heap_ptr u; for (u.hdr = offheap->first; u.hdr; u.hdr = u.hdr->next) { switch (thing_subtag(u.hdr->thing_word)) { case REFC_BINARY_SUBTAG: if (erts_refc_dectest(&u.pb->val->refc, 0) == 0) { erts_bin_free(u.pb->val); } break; case FUN_SUBTAG: if (erts_refc_dectest(&u.fun->fe->refc, 0) == 0) { erts_erase_fun_entry(u.fun->fe); } break; default: ASSERT(is_external_header(u.hdr->thing_word)); erts_deref_node_entry(u.ext->node); break; } } }
static BIF_RETTYPE iol2v_continue(iol2v_state_t *state) { Eterm iterator; DECLARE_ESTACK(s); ESTACK_CHANGE_ALLOCATOR(s, ERTS_ALC_T_SAVED_ESTACK); state->bytereds_available = ERTS_BIF_REDS_LEFT(state->process) * IOL2V_SMALL_BIN_LIMIT; state->bytereds_spent = 0; if (state->estack.start) { ESTACK_RESTORE(s, &state->estack); } iterator = state->input_list; for(;;) { if (state->bytereds_spent >= state->bytereds_available) { ESTACK_SAVE(s, &state->estack); state->input_list = iterator; return iol2v_yield(state); } while (is_list(iterator)) { Eterm *cell; Eterm head; cell = list_val(iterator); head = CAR(cell); if (is_binary(head)) { if (!iol2v_append_binary(state, head)) { goto l_badarg; } iterator = CDR(cell); } else if (is_small(head)) { Eterm seq_end; if (!iol2v_append_byte_seq(state, iterator, &seq_end)) { goto l_badarg; } iterator = seq_end; } else if (is_list(head) || is_nil(head)) { Eterm tail = CDR(cell); if (!is_nil(tail)) { ESTACK_PUSH(s, tail); } state->bytereds_spent += 1; iterator = head; } else { goto l_badarg; } if (state->bytereds_spent >= state->bytereds_available) { ESTACK_SAVE(s, &state->estack); state->input_list = iterator; return iol2v_yield(state); } } if (is_binary(iterator)) { if (!iol2v_append_binary(state, iterator)) { goto l_badarg; } } else if (!is_nil(iterator)) { goto l_badarg; } if(ESTACK_ISEMPTY(s)) { break; } iterator = ESTACK_POP(s); } if (state->acc_size != 0) { iol2v_enqueue_result(state, iol2v_promote_acc(state)); } BUMP_REDS(state->process, state->bytereds_spent / IOL2V_SMALL_BIN_LIMIT); CLEAR_SAVED_ESTACK(&state->estack); DESTROY_ESTACK(s); BIF_RET(state->result_head); l_badarg: CLEAR_SAVED_ESTACK(&state->estack); DESTROY_ESTACK(s); if (state->acc != NULL) { erts_bin_free(state->acc); state->acc = NULL; } BIF_ERROR(state->process, BADARG); }