struct pvm_object pvm_copy_object( struct pvm_object in_object ) { // TODO ERROR throw! if(in_object.data->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_INTERNAL) panic("internal object copy?!"); //ref_inc_o( in_object.data->_class ); //increment if class is refcounted struct pvm_object in_class = in_object.data->_class; int da_size = in_object.data->_da_size; struct pvm_object out = pvm_object_create_dynamic( in_class, da_size ); int i = da_size/sizeof(struct pvm_object); for(; i >= 0; i-- ) { if(da_po_ptr((in_object.data)->da)[i].data) ref_inc_o( da_po_ptr((in_object.data)->da)[i] ); } memcpy( out.data->da, in_object.data->da, da_size ); // TODO: check for special cases - copy c'tor? return out; }
void pvm_set_ofield( struct pvm_object op, unsigned int slot, struct pvm_object value ) { verify_o(op); verify_o(value); if( PHANTOM_OBJECT_STORAGE_FLAG_IS_INTERNAL & ((op.data)->_flags) ) { if( PHANTOM_OBJECT_STORAGE_FLAG_IS_RESIZEABLE & ((op.data)->_flags) ) { pvm_set_array_ofield( op.data, slot, value ); return; } pvm_exec_panic( "attempt to save to internal" ); } if( PHANTOM_OBJECT_STORAGE_FLAG_IS_IMMUTABLE & (op.data->_flags) ) pvm_exec_panic( "attempt to set_ofield for immutable" ); if( slot >= da_po_limit(op.data) ) { pvm_exec_panic( "slot index out of bounds" ); } if(da_po_ptr((op.data)->da)[slot].data) ref_dec_o(da_po_ptr((op.data)->da)[slot]); //decr old value da_po_ptr((op.data)->da)[slot] = value; }
void pvm_pop_array(struct pvm_object_storage *array, struct pvm_object value_to_pop ) { struct data_area_4_array *da = (struct data_area_4_array *)&(array->da); verify_p(array); if( !(PHANTOM_OBJECT_STORAGE_FLAG_IS_INTERNAL & (array->_flags) ) || !( PHANTOM_OBJECT_STORAGE_FLAG_IS_RESIZEABLE & (array->_flags) ) ) pvm_exec_panic( "attempt to do an array op to non-array" ); if( PHANTOM_OBJECT_STORAGE_FLAG_IS_IMMUTABLE & (array->_flags) ) pvm_exec_panic( "attempt to pop_array for immutable" ); //swap with last and decrement used_slots struct pvm_object *p = da_po_ptr((da->page.data)->da); unsigned int slot; for( slot = 0; slot < da->used_slots; slot++ ) { if ( ( p[slot] ).data == value_to_pop.data ) //please don't leak refcnt { if (slot != da->used_slots-1) { p[slot] = p[da->used_slots-1]; } da->used_slots--; return; } } pvm_exec_panic( "attempt to remove non existing element from array" ); }
struct pvm_object pvm_create_interface_object( int n_methods, struct pvm_object parent_class ) { struct pvm_object ret = create_interface_worker( n_methods ); struct pvm_object * data_area = (struct pvm_object *)ret.data->da; if(pvm_is_null( parent_class )) pvm_exec_panic( "create interface: parent is null" ); struct pvm_object_storage *base_i = ((struct data_area_4_class*)parent_class.data->da)->object_default_interface.data; int base_icount = da_po_limit(base_i); if(base_icount > n_methods) { // root classes have N_SYS_METHODS slots in interface, don't cry about that if( n_methods > N_SYS_METHODS ) printf( " create interface: child has less methods (%d) than parent (%d)\n", n_methods, base_icount ); base_icount = n_methods; } int i = 0; // copy methods from parent for( ; i < base_icount; i++ ) { pvm_object_t baseMethod = (da_po_ptr(base_i->da))[i]; ref_inc_o(baseMethod); data_area[i] = baseMethod; } // fill others with nulls for( ; i < n_methods; i++ ) data_area[i] = pvm_get_null_object(); // null return ret; }
// TODO BUG XXX - races possible, read obj, then other thread writes // to slot (derements refctr and kills object), then we attempt to // use it (even increment refctr) -> death. Need atomic (to slot write? to refcnt dec?) // refcnt incr here struct pvm_object pvm_get_ofield( struct pvm_object op, unsigned int slot ) { verify_o(op); if( PHANTOM_OBJECT_STORAGE_FLAG_IS_INTERNAL & ((op.data)->_flags) ) { if( PHANTOM_OBJECT_STORAGE_FLAG_IS_RESIZEABLE & ((op.data)->_flags) ) { return pvm_get_array_ofield( op.data, slot ); } pvm_exec_panic( "attempt to load from internal" ); } if( slot >= da_po_limit(op.data) ) { pvm_exec_panic( "load: slot index out of bounds" ); } verify_o(da_po_ptr((op.data)->da)[slot]); return da_po_ptr((op.data)->da)[slot]; }