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_get_array_ofield(struct pvm_object_storage *o, unsigned int slot ) { verify_p(o); if( !(PHANTOM_OBJECT_STORAGE_FLAG_IS_INTERNAL & (o->_flags) ) || !( PHANTOM_OBJECT_STORAGE_FLAG_IS_RESIZEABLE & (o->_flags) ) ) pvm_exec_panic( "attempt to do an array op to non-array" ); struct data_area_4_array *da = (struct data_area_4_array *)&(o->da); if( slot >= da->used_slots ) pvm_exec_panic( "load: array index out of bounds" ); return pvm_get_ofield( da->page, slot); }
static void throw_bounds( int ip, int max_IP, char *where ) { char errtext[200]; snprintf(errtext, sizeof(errtext)-1, "%s: IP out of bounds (IP=%d, max=%d)", where, ip, max_IP ); pvm_exec_panic( errtext ); }
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 need semaphores here void pvm_set_array_ofield(struct pvm_object_storage *o, unsigned int slot, struct pvm_object value ) { verify_p(o); verify_o(value); if( !(PHANTOM_OBJECT_STORAGE_FLAG_IS_INTERNAL & (o->_flags) ) || !( PHANTOM_OBJECT_STORAGE_FLAG_IS_RESIZEABLE & (o->_flags) ) ) pvm_exec_panic( "attempt to do an array op to non-array" ); if( PHANTOM_OBJECT_STORAGE_FLAG_IS_IMMUTABLE & (o->_flags) ) pvm_exec_panic( "attempt to set_array_ofield for immutable" ); struct data_area_4_array *da = (struct data_area_4_array *)&(o->da); // need resize? if( pvm_is_null(da->page) || slot >= da->page_size ) { const int step = 1024; int new_page_size = slot < (step/2) ? (slot * 2) : (slot+step); if(new_page_size < 16) new_page_size = 16; if( (!pvm_is_null(da->page)) && da->page_size > 0 ) //da->page = pvm_object_storage::create_page( new_page_size, da->page.data()->da_po_ptr(), da->page_size ); da->page = pvm_create_page_object( new_page_size, (void *)&(da->page.data->da), da->page_size ); else da->page = pvm_create_page_object( new_page_size, 0, 0 ); da->page_size = new_page_size; } if( slot >= da->used_slots ) { // set to null all new slots except for indexed //for( int i = da->used_slots; i < index; i++ ) //da->page.save(i, pvm_object()); da->used_slots = slot+1; } pvm_set_ofield( da->page, slot, value ); }
// 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]; }
void pvm_call_frame_init_code(struct data_area_4_call_frame *cf, struct pvm_object code) { if( !(code.data->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_CODE) ) pvm_exec_panic("exec: not a code object"); struct data_area_4_code *da = (struct data_area_4_code *)&(code.data->da); cf->code = da->code; cf->IP_max = da->code_size; cf->IP = 0; //cf->cs = code; // for gc only - work without }