2
0

blitz_object.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. #include "blitz.h"
  2. #define REG_GROW 256
  3. int bbCountInstances = 0;
  4. static BBClass **reg_base,**reg_put,**reg_end;
  5. static BBInterface **ireg_base,**ireg_put,**ireg_end;
  6. static BBDebugScope debugScope={
  7. BBDEBUGSCOPE_USERTYPE,
  8. "Object",
  9. BBDEBUGDECL_END
  10. };
  11. BBClass bbObjectClass={
  12. 0, //super
  13. bbObjectFree, //free
  14. &debugScope, //debug_scope
  15. 8, //instance_size
  16. bbObjectCtor,
  17. bbObjectDtor,
  18. bbObjectToString,
  19. bbObjectCompare,
  20. bbObjectSendMessage,
  21. 0, //interface
  22. 0, //extra
  23. 0, //obj_size
  24. 0, //instance_count
  25. sizeof(void*) //fields_offset
  26. };
  27. BBObject bbNullObject={
  28. 0 //clas
  29. //BBGC_MANYREFS //refs
  30. };
  31. BBObject *bbObjectNew( BBClass *clas ){
  32. int flags=( clas->dtor!=bbObjectDtor ) ? BBGC_FINALIZE : 0;
  33. BBObject *o=(BBObject*)bbGCAllocObject( clas->instance_size,clas,flags );
  34. clas->ctor( o );
  35. return o;
  36. }
  37. BBObject *bbObjectAtomicNew( BBClass *clas ){
  38. int flags=( clas->dtor!=bbObjectDtor ) ? BBGC_FINALIZE | BBGC_ATOMIC : BBGC_ATOMIC;
  39. BBObject *o=(BBObject*)bbGCAllocObject( clas->instance_size,clas,flags );
  40. clas->ctor( o );
  41. return o;
  42. }
  43. BBObject *bbObjectNewNC( BBClass *clas ){
  44. int flags=( clas->dtor!=bbObjectDtor ) ? BBGC_FINALIZE : 0;
  45. BBObject *o=(BBObject*)bbGCAllocObject( clas->instance_size,clas,flags );
  46. return o;
  47. }
  48. BBObject *bbObjectAtomicNewNC( BBClass *clas ){
  49. int flags=( clas->dtor!=bbObjectDtor ) ? BBGC_FINALIZE | BBGC_ATOMIC : BBGC_ATOMIC;
  50. BBObject *o=(BBObject*)bbGCAllocObject( clas->instance_size,clas,flags );
  51. return o;
  52. }
  53. void bbObjectFree( BBObject *o ){
  54. BBClass *clas=o->clas;
  55. if (bbCountInstances) {
  56. bbAtomicAdd(&clas->instance_count, -1);
  57. }
  58. clas->dtor( o );
  59. }
  60. void bbObjectCtor( BBObject *o ){
  61. o->clas=&bbObjectClass;
  62. }
  63. void bbObjectDtor( BBObject *o ){
  64. }
  65. BBString *bbObjectToString( BBObject *o ){
  66. char buf[32];
  67. sprintf( buf,"%p",o );
  68. return bbStringFromCString( buf );
  69. }
  70. int bbObjectCompare( BBObject *x,BBObject *y ){
  71. return (char*)x-(char*)y;
  72. }
  73. BBObject *bbObjectSendMessage( BBObject * o, BBObject *m,BBObject *s ){
  74. return &bbNullObject;
  75. }
  76. void bbObjectReserved(){
  77. bbExThrowCString( "Illegal call to reserved method" );
  78. }
  79. BBObject *bbObjectStringcast( BBObject *o ){
  80. if (o->clas == (BBClass *)&bbStringClass) {
  81. return o;
  82. } else {
  83. return (BBObject *)&bbEmptyString;
  84. }
  85. }
  86. int bbObjectIsString( BBObject *o ){
  87. return o->clas == (BBClass *)&bbStringClass;
  88. }
  89. BBObject *bbObjectArraycast( BBObject *o ){
  90. if (o->clas == (BBClass *)&bbArrayClass) {
  91. return o;
  92. } else {
  93. return (BBObject *)&bbEmptyArray;
  94. }
  95. }
  96. int bbObjectIsArray( BBObject *o ){
  97. return o->clas == (BBClass *)&bbArrayClass;
  98. }
  99. BBObject *bbObjectDowncast( BBObject *o,BBClass *t ){
  100. BBClass *p=o->clas;
  101. while( p && p!=t ) p=p->super;
  102. return p ? o : (t==(BBClass *)&bbStringClass) ? (BBObject *)&bbEmptyString : (t==(BBClass *)&bbArrayClass) ? (BBObject *)&bbEmptyArray : &bbNullObject;
  103. }
  104. void bbObjectRegisterType( BBClass *clas ){
  105. if( reg_put==reg_end ){
  106. int len=reg_put-reg_base,new_len=len+REG_GROW;
  107. reg_base=(BBClass**)bbMemExtend( reg_base,len*sizeof(BBClass*),new_len*sizeof(BBClass*) );
  108. reg_end=reg_base+new_len;
  109. reg_put=reg_base+len;
  110. }
  111. *reg_put++=clas;
  112. }
  113. BBClass **bbObjectRegisteredTypes( int *count ){
  114. *count=reg_put-reg_base;
  115. return reg_base;
  116. }
  117. void bbObjectDumpInstanceCounts(char * buf, int size, int includeZeros) {
  118. int i;
  119. int count = 0;
  120. int offset = 0;
  121. BBClass ** classes = bbObjectRegisteredTypes(&count);
  122. offset += snprintf(buf, size, "=== Instance count dump (%4d) ===\n", count);
  123. if (bbStringClass.instance_count > 0 || includeZeros) {
  124. offset += snprintf(buf + offset, size - offset, "%s\t%d\n", bbStringClass.debug_scope->name, bbStringClass.instance_count);
  125. }
  126. if (bbArrayClass.instance_count > 0 || includeZeros) {
  127. offset += snprintf(buf + offset, size - offset, "%s\t%d\n", bbArrayClass.debug_scope->name, bbArrayClass.instance_count);
  128. }
  129. for (i = 0; i < count; i++) {
  130. BBClass * clas = classes[i];
  131. if (offset < size && (clas->instance_count > 0 || includeZeros)) {
  132. offset += snprintf(buf + offset, size - offset, "%s\t%d\n", clas->debug_scope->name, clas->instance_count);
  133. }
  134. }
  135. if (offset < size) {
  136. snprintf(buf + offset, size - offset, "=== End ===\n");
  137. }
  138. }
  139. void bbObjectRegisterInterface( BBInterface * ifc ){
  140. if( ireg_put==ireg_end ){
  141. int len=ireg_put-ireg_base,new_len=len+REG_GROW;
  142. ireg_base=(BBInterface**)bbMemExtend( ireg_base,len*sizeof(BBInterface*),new_len*sizeof(BBInterface*) );
  143. ireg_end=ireg_base+new_len;
  144. ireg_put=ireg_base+len;
  145. }
  146. *ireg_put++=ifc;
  147. }
  148. BBInterface **bbObjectRegisteredInterfaces( int *count ){
  149. *count=ireg_put-ireg_base;
  150. return ireg_base;
  151. }
  152. BBObject * bbInterfaceDowncast(BBOBJECT o, BBINTERFACE ifc) {
  153. int i;
  154. BBCLASS superclas = o->clas;
  155. while (superclas) {
  156. BBCLASS clas = superclas;
  157. superclas = clas->super;
  158. BBINTERFACETABLE table = clas->itable;
  159. if (table) {
  160. BBINTERFACEOFFSETS offsets = table->ifc_offsets;
  161. for (i = table->ifc_size; i; i--) {
  162. if (offsets->ifc == ifc) {
  163. return o;
  164. }
  165. offsets++;
  166. }
  167. }
  168. }
  169. return &bbNullObject;
  170. }
  171. void * bbObjectInterface(BBOBJECT o, BBINTERFACE ifc) {
  172. int i;
  173. BBCLASS superclas = o->clas;
  174. while (superclas) {
  175. BBCLASS clas = superclas;
  176. superclas = clas->super;
  177. BBINTERFACETABLE table = clas->itable;
  178. if (table) {
  179. BBINTERFACEOFFSETS offsets = table->ifc_offsets;
  180. for (i = table->ifc_size; i; i--) {
  181. if (offsets->ifc == ifc) {
  182. return (char*) table->ifc_vtable + offsets->offset;
  183. }
  184. offsets++;
  185. }
  186. }
  187. }
  188. return &bbNullObject;
  189. }
  190. static struct avl_root *struct_root = 0;
  191. int struct_node_compare(const void *x, const void *y) {
  192. struct struct_node * node_x = (struct struct_node *)x;
  193. struct struct_node * node_y = (struct struct_node *)y;
  194. return strcmp(node_x->scope->name, node_y->scope->name);
  195. }
  196. void bbObjectRegisterStruct( BBDebugScope *p ) {
  197. struct struct_node * node = (struct struct_node *)malloc(sizeof(struct struct_node));
  198. node->scope = p;
  199. struct struct_node * old_node = (struct struct_node *)avl_map(&node->link, struct_node_compare, &struct_root);
  200. if (&node->link != &old_node->link) {
  201. // this object already exists here...
  202. // delete the new node, since we don't need it
  203. // note : should never happen as structs should only ever be registered once.
  204. free(node);
  205. }
  206. }
  207. BBDebugScope * bbObjectStructInfo( char * name ) {
  208. // create something to look up
  209. struct struct_node node;
  210. BBDebugScope scope;
  211. scope.name = name;
  212. node.scope = &scope;
  213. struct struct_node * found = (struct struct_node *)tree_search((struct tree_root_np *)&node, struct_node_compare, (struct tree_root_np *)struct_root);
  214. if (found) {
  215. return found->scope;
  216. }
  217. return 0;
  218. }
  219. BBObject * bbNullObjectTest( BBObject *o ) {
  220. if (o == &bbNullObject) brl_blitz_NullObjectError();
  221. return o;
  222. }
  223. static struct avl_root *enum_root = 0;
  224. int enum_node_compare(const void *x, const void *y) {
  225. struct enum_node * node_x = (struct enum_node *)x;
  226. struct enum_node * node_y = (struct enum_node *)y;
  227. return strcmp(node_x->scope->name, node_y->scope->name);
  228. }
  229. void bbObjectRegisterEnum( BBDebugScope *p ) {
  230. struct enum_node * node = (struct enum_node *)malloc(sizeof(struct enum_node));
  231. node->scope = p;
  232. struct enum_node * old_node = (struct enum_node *)avl_map(&node->link, enum_node_compare, &enum_root);
  233. if (&node->link != &old_node->link) {
  234. // this object already exists here...
  235. // delete the new node, since we don't need it
  236. // note : should never happen as structs should only ever be registered once.
  237. free(node);
  238. }
  239. }
  240. BBDebugScope * bbObjectEnumInfo( char * name ) {
  241. // create something to look up
  242. struct enum_node node;
  243. BBDebugScope scope;
  244. scope.name = name;
  245. node.scope = &scope;
  246. struct enum_node * found = (struct enum_node *)tree_search((struct tree_root_np *)&node, enum_node_compare, (struct tree_root_np *)enum_root);
  247. if (found) {
  248. return found->scope;
  249. }
  250. return 0;
  251. }
  252. #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
  253. extern void * bbObjectToFieldOffset(BBOBJECT o);
  254. #else
  255. void * bbObjectToFieldOffset(BBOBJECT o) {
  256. if ( !o->clas ) {
  257. return &bbNullObject;
  258. }
  259. return (void*)(((unsigned char*)o) + o->clas->fields_offset);
  260. }
  261. #endif