static struct GC_ms_entry* markObject(GC_word* addr, struct GC_ms_entry* mark_stack_ptr, struct GC_ms_entry* mark_stack_limit, GC_word env) { Object* obj = (Object*) addr; if (obj == NULL || obj->clazz == NULL || obj->clazz->object.clazz != java_lang_Class) { // According to the comments in gc_mark.h the GC sometimes calls the mark_proc with unused objects. // Such objects have been cleared except for the first word which points to a free list link field. // A valid RovoVM Object must point to a Class and the Class of the Object's Class must be java.lang.Class. return mark_stack_ptr; } mark_stack_ptr = GC_MARK_AND_PUSH(obj->clazz, mark_stack_ptr, mark_stack_limit, NULL); if (obj->clazz == java_lang_Class) { // Class* Class* clazz = (Class*) obj; mark_stack_ptr = GC_MARK_AND_PUSH(clazz->_data, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH((void*) clazz->name, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->classLoader, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->superclass, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->componentType, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->_interfaces, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->_fields, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->_methods, mark_stack_ptr, mark_stack_limit, NULL); void** start = (void**) (((char*) clazz) + offsetof(Class, data)); void** end = (void**) (((char*) start) + clazz->classRefCount * sizeof(Object*)); mark_stack_ptr = markRegion(start, end, mark_stack_ptr, mark_stack_limit); } else if (CLASS_IS_ARRAY(obj->clazz)) { if (!CLASS_IS_PRIMITIVE(obj->clazz->componentType)) { // Array of objects. Mark all values in the array. ObjectArray* array = (ObjectArray*) obj; void** start = (void**) (((char*) array) + offsetof(ObjectArray, values)); void** end = (void**) (((char*) start) + sizeof(Object*) * array->length); mark_stack_ptr = markRegion(start, end, mark_stack_ptr, mark_stack_limit); } } else { // Object* - for each Class in the hierarchy of obj's Class we mark the first instanceRefCount*sizeof(Object*) bytes Class* clazz = obj->clazz; while (clazz != NULL) { void** start = (void**) (((char*) obj) + clazz->instanceDataOffset); void** end = (void**) (((char*) start) + clazz->instanceRefCount * sizeof(Object*)); if (clazz == java_lang_ref_Reference) { // Don't mark the referent field void** referent_start = (void**) (((char*) obj) + java_lang_ref_Reference_referent->offset); void** referent_end = (void**) (((char*) referent_start) + sizeof(Object*)); mark_stack_ptr = markRegion(start, referent_start, mark_stack_ptr, mark_stack_limit); mark_stack_ptr = markRegion(referent_end, end, mark_stack_ptr, mark_stack_limit); } else { mark_stack_ptr = markRegion(start, end, mark_stack_ptr, mark_stack_limit); } clazz = clazz->superclass; } } return mark_stack_ptr; }
/* * UnselectRegion - remove selected region */ void UnselectRegion( void ) { if( !SelRgn.selected ) { return; } SelRgn.selected = FALSE; EditFlags.Dragging = FALSE; #ifdef __WIN__ updateRegion(); #else markRegion( FALSE ); DCDisplayAllLines(); #endif } /* UnselectRegion */
/* * updateRegion - update marked region */ static void updateRegion( void ) { #ifdef __WIN__ if( !SelRgn.selected ) { int min_line, max_line; min_line = last_start_line; if( min_line > last_start_line ) min_line = last_start_line; max_line = last_start_line; if( max_line < last_end_line ) max_line = last_end_line; DCDisplaySomeLines( min_line - LeftTopPos.line, max_line - LeftTopPos.line ); last_start_line = last_end_line = 1; return; } else { int min_start, max_start; int min_end, max_end; min_start = SelRgn.start.line; if( min_start > last_start_line ) min_start = last_start_line; max_start = SelRgn.start.line; if( max_start < last_start_line ) max_start = last_start_line; min_end = SelRgn.end.line; if( min_end > last_end_line ) min_end = last_end_line; max_end = SelRgn.end.line; if( max_end < last_end_line ) max_end = last_end_line; DCDisplaySomeLines( min_start - LeftTopPos.line, max_start - LeftTopPos.line ); DCDisplaySomeLines( min_end - LeftTopPos.line, max_end - LeftTopPos.line ); } last_start_line = SelRgn.start.line; last_end_line = SelRgn.end.line; #else markRegion( true ); DCDisplayAllLines(); #endif } /* updateRegion */
/* * updateRegion - update marked region */ static void updateRegion( void ) { #ifdef __WIN__ if( SelRgn.selected == FALSE ) { DCDisplaySomeLines( __min( last_start_line, last_end_line ) - LeftTopPos.line, __max( last_start_line, last_end_line ) - LeftTopPos.line ); last_start_line = last_end_line = 1; return; } else { DCDisplaySomeLines( __min( SelRgn.start.line, last_start_line ) - LeftTopPos.line, __max( SelRgn.start.line, last_start_line ) - LeftTopPos.line ); DCDisplaySomeLines( __min( SelRgn.end.line, last_end_line ) - LeftTopPos.line, __max( SelRgn.end.line, last_end_line ) - LeftTopPos.line ); } last_start_line = SelRgn.start.line; last_end_line = SelRgn.end.line; #else markRegion( TRUE ); DCDisplayAllLines(); #endif } /* updateRegion */
void updateMarked(void) { if (base + cursor > oldbase + oldcursor) { if (mark_min == mark_max) { mark_max = base + cursor; } else if (oldbase + oldcursor == mark_min) { if (base + cursor <= mark_max) { mark_min = base + cursor; unmarkRegion(oldbase + oldcursor, mark_min - 1); } else { unmarkRegion(oldbase + oldcursor, mark_max); mark_min = mark_max; mark_max = base + cursor; } } else { mark_max = base + cursor; } } else if (base + cursor < oldbase + oldcursor){ if (mark_min == mark_max) { mark_min = base + cursor; } else if (oldbase + oldcursor == mark_max) { if (base + cursor >= mark_min) { mark_max = base + cursor; unmarkRegion(mark_max + 1, oldbase + oldcursor); } else { unmarkRegion(mark_min, oldbase + oldcursor); markRegion(base + cursor, mark_min - 1); mark_max = mark_min; mark_min = base + cursor; } } else { mark_min = base + cursor; } } if (mark_max >= getfilesize()) mark_max = getfilesize() - 1; markSelectedRegion(); }
/* * UpdateDrag - update selected region */ void UpdateDrag( window_id id, int win_x, int win_y ) { int nx, ny, height; int moveCursor; SelRgn.selected = TRUE; moveCursor = 0; height = WindowAuxInfo( CurrentWindow, WIND_INFO_TEXT_LINES ); #ifdef __WIN__ if( id == CurrentWindow && InsideWindow( id, MouseX, MouseY ) ) { #else if( id == CurrentWindow && InsideWindow( id, win_x, win_y ) ) { #endif ny = LeftTopPos.line + win_y - 1; if( ny > CurrentFile->fcbs.tail->end_line ) { ny = CurrentFile->fcbs.tail->end_line; moveCursor = 1; } else if( ny < 1 ) { ny = 1; moveCursor = -1; } GoToLineRelCurs( ny ); win_x += LeftTopPos.column; nx = RealColumnOnCurrentLine( win_x ); GoToColumnOnCurrentLine( nx ); } else { #ifndef __WIN__ if( MouseRow >= WindowAuxInfo( CurrentWindow, WIND_INFO_Y2 ) ) { GoToLineRelCurs( LeftTopPos.line + height ); } else if( MouseRow <= WindowAuxInfo( CurrentWindow, WIND_INFO_Y1 ) ) { GoToLineRelCurs( LeftTopPos.line - 1 ); } else if( MouseCol <= WindowAuxInfo( CurrentWindow, WIND_INFO_X1 ) ) { GoToColumnOnCurrentLine( LeftTopPos.column - 1 ); } else if( MouseCol >= WindowAuxInfo( CurrentWindow, WIND_INFO_X2 ) ) { GoToColumnOnCurrentLine( LeftTopPos.column + WindowAuxInfo( CurrentWindow, WIND_INFO_WIDTH )); } #else { RECT rect; GetClientRect( CurrentWindow, &rect ); if( MouseY > rect.bottom ) { ny = LeftTopPos.line + height; if( ny > CurrentFile->fcbs.tail->end_line ) { ny = CurrentFile->fcbs.tail->end_line; moveCursor = 1; } GoToLineRelCurs( ny ); } else if( MouseY < 0 ) { ny = LeftTopPos.line - 1; if( ny < 1 ) { ny = 1; moveCursor = -1; } GoToLineRelCurs( ny ); } else if( MouseX < 0 ) { GoToColumnOnCurrentLine( LeftTopPos.column - 1 ); } else if( MouseX > rect.right ) { if( EditFlags.Modeless ) { GoToColumnOnCurrentLine( 1 + LeftTopPos.column + WindowAuxInfo( CurrentWindow, WIND_INFO_TEXT_COLS ) ); } else { GoToColumnOnCurrentLine( LeftTopPos.column + WindowAuxInfo( CurrentWindow, WIND_INFO_TEXT_COLS ) ); } } } #endif } if( moveCursor == -1 ) { GoToColumnOnCurrentLine( 1 ); } else if( moveCursor == 1 ) { GoToColumnOnCurrentLine( CurrentFile->fcbs.tail->lines.tail->len + 1 ); } } /* UpdateDrag */ /* * UpdateCursorDrag - update drag after cursor movement */ void UpdateCursorDrag( void ) { if( !EditFlags.Dragging ) { return; } if( SelRgn.end.line == CurrentPos.line && SelRgn.end.column == CurrentPos.column ) { return; } #ifndef __WIN__ markRegion( FALSE ); #endif SelRgn.end = CurrentPos; if( EditFlags.LineBased == FALSE ) { SelRgn.lines = FALSE; } else if( SelRgn.start.line != SelRgn.end.line ) { SelRgn.lines = TRUE; } else if( SelRgn.start.column == SelRgn.end.column ) { SelRgn.lines = TRUE; } else { SelRgn.lines = FALSE; } updateRegion(); } /* UpdateCursorDrag */ /* * SetSelRegionCols - set selected region on a line */ void SetSelRegionCols( linenum sl, int sc, int ec ) { vi_rc rc; line *line; fcb *fcb; char *data; SelRgn.lines = FALSE; SelRgn.selected = TRUE; SelRgn.start.line = SelRgn.end.line = sl; SelRgn.start.column = sc; SelRgn.end.column = ec + 1; SelRgn.start_col_v = 0; rc = CGimmeLinePtr( sl, &fcb, &line ); if( rc == ERR_NO_ERR ) { data = ( line->u.ld.nolinedata ) ? WorkLine->data : line->data; SelRgn.start_col_v = GetVirtualCursorPosition( data, SelRgn.start.column ); } updateRegion(); DCUpdate(); } /* SetSelRegionCols */
static struct GC_ms_entry* markObject(GC_word* addr, struct GC_ms_entry* mark_stack_ptr, struct GC_ms_entry* mark_stack_limit, GC_word env) { Object* obj = (Object*) addr; if (obj == NULL || obj->clazz == NULL || obj->clazz->object.clazz != java_lang_Class) { // According to the comments in gc_mark.h the GC sometimes calls the mark_proc with unused objects. // Such objects have been cleared except for the first word which points to a free list link field. // A valid RovoVM Object must point to a Class and the Class of the Object's Class must be java.lang.Class. return mark_stack_ptr; } // This mark procedure should never be called for array instances. assert(!CLASS_IS_ARRAY(obj->clazz)); mark_stack_ptr = GC_MARK_AND_PUSH(obj->clazz, mark_stack_ptr, mark_stack_limit, NULL); if (obj->clazz == java_lang_Class) { // Class* Class* clazz = (Class*) obj; mark_stack_ptr = GC_MARK_AND_PUSH(clazz->_data, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH((void*) clazz->name, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->typeInfo, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->vitable, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->itables, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->classLoader, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->superclass, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->componentType, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->_interfaces, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->_fields, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->_methods, mark_stack_ptr, mark_stack_limit, NULL); void** start = (void**) (((char*) clazz) + offsetof(Class, data)); void** end = (void**) (((char*) start) + clazz->classRefCount * sizeof(Object*)); mark_stack_ptr = markRegion(start, end, mark_stack_ptr, mark_stack_limit); } else { // Object* - for each Class in the hierarchy of obj's Class we mark the first instanceRefCount*sizeof(Object*) bytes Class* clazz = obj->clazz; while (clazz != NULL) { void** start = (void**) (((char*) obj) + clazz->instanceDataOffset); void** end = (void**) (((char*) start) + clazz->instanceRefCount * sizeof(Object*)); if (clazz == java_lang_ref_Reference) { // Don't mark the referent field void** referent_start = (void**) (((char*) obj) + java_lang_ref_Reference_referent->offset); void** referent_end = (void**) (((char*) referent_start) + sizeof(Object*)); mark_stack_ptr = markRegion(start, referent_start, mark_stack_ptr, mark_stack_limit); mark_stack_ptr = markRegion(referent_end, end, mark_stack_ptr, mark_stack_limit); } else { mark_stack_ptr = markRegion(start, end, mark_stack_ptr, mark_stack_limit); } // Some classes use longs and ints to store pointers to GC allocated memory. // For each such class we need to mark those fields here. // Note: java.lang.Thread, java.lang.reflect.Constructor, java.lang.reflect.Method, // java.lang.reflect.Field also contain such fields but we don't have // to mark those because the Thread, Method and Field C structures those // point to are also referenced by other roots (the threads list, Class structures) // that prevent GCing. if (clazz == java_lang_Throwable) { // The 'stackState' field in java.lang.Throwable is a long but contains // a pointer to an address on the GCed heap. void** field_start = (void**) (((char*) obj) + java_lang_Throwable_stackState->offset); void** field_end = (void**) (((char*) field_start) + sizeof(jlong)); mark_stack_ptr = markRegion(field_start, field_end, mark_stack_ptr, mark_stack_limit); } else if (clazz == org_robovm_rt_bro_Struct) { // The 'handle' field in org.robovm.rt.bro.Struct (actually in its // superclass NativeObject) is a long but contains a pointer. // Possibly to an address on the GCed heap. void** field_start = (void**) (((char*) obj) + org_robovm_rt_bro_Struct_handle->offset); void** field_end = (void**) (((char*) field_start) + sizeof(jlong)); mark_stack_ptr = markRegion(field_start, field_end, mark_stack_ptr, mark_stack_limit); } else if (clazz == java_nio_MemoryBlock) { // The 'address' field in java.nio.MemoryBlock is a long but contains a pointer. // Possibly to an address on the GCed heap. void** field_start = (void**) (((char*) obj) + java_nio_MemoryBlock_address->offset); void** field_end = (void**) (((char*) field_start) + sizeof(jlong)); mark_stack_ptr = markRegion(field_start, field_end, mark_stack_ptr, mark_stack_limit); } clazz = clazz->superclass; } } return mark_stack_ptr; }
void markSelectedRegion(void) { markRegion(mark_min, mark_max); }