Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

vm.c File Reference

#include "vm_local.h"

Include dependency graph for vm.c:

Include dependency graph

Go to the source code of this file.

Defines

#define MAX_STACK   256
#define MAX_VM   3
#define STACK_MASK   (MAX_STACK-1)
#define STACK_SIZE   0x20000

Functions

int ParseHex (const char *text)
void * VM_ArgPtr (int intValue)
int QDECL VM_Call (vm_t *vm, int callnum,...)
void VM_Clear (void)
vm_tVM_Create (const char *module, int(*systemCalls)(int *), vmInterpret_t interpret)
void VM_Debug (int level)
int QDECL VM_DllSyscall (int arg,...)
void * VM_ExplicitArgPtr (vm_t *vm, int intValue)
void VM_Free (vm_t *vm)
void VM_Init (void)
void VM_LoadSymbols (vm_t *vm)
void VM_LogSyscalls (int *args)
int QDECL VM_ProfileSort (const void *a, const void *b)
vm_tVM_Restart (vm_t *vm)
const char * VM_SymbolForCompiledPointer (vm_t *vm, void *code)
int VM_SymbolToValue (vm_t *vm, const char *symbol)
vmSymbol_tVM_ValueToFunctionSymbol (vm_t *vm, int value)
const char * VM_ValueToSymbol (vm_t *vm, int value)
void * VM_VM2C (vmptr_t p, int length)
void VM_VmInfo_f (void)
void VM_VmProfile_f (void)

Variables

vm_tcurrentVM = NULL
vm_tlastVM = NULL
int vm_debugLevel
vm_t vmTable [MAX_VM]


Define Documentation

#define MAX_STACK   256
 

Definition at line 665 of file vm.c.

#define MAX_VM   3
 

Definition at line 43 of file vm.c.

#define STACK_MASK   (MAX_STACK-1)
 

Definition at line 666 of file vm.c.

#define STACK_SIZE   0x20000
 

Definition at line 433 of file vm.c.


Function Documentation

int ParseHex const char *  text  ) 
 

Definition at line 183 of file vm.c.

References c, and value.

00183                                  {
00184     int     value;
00185     int     c;
00186 
00187     value = 0;
00188     while ( ( c = *text++ ) != 0 ) {
00189         if ( c >= '0' && c <= '9' ) {
00190             value = value * 16 + c - '0';
00191             continue;
00192         }
00193         if ( c >= 'a' && c <= 'f' ) {
00194             value = value * 16 + 10 + c - 'a';
00195             continue;
00196         }
00197         if ( c >= 'A' && c <= 'F' ) {
00198             value = value * 16 + 10 + c - 'A';
00199             continue;
00200         }
00201     }
00202 
00203     return value;
00204 }

void* VM_ArgPtr int  intValue  ) 
 

Definition at line 607 of file vm.c.

References currentVM, vm_s::dataBase, and vm_s::dataMask.

00607                                 {
00608     if ( !intValue ) {
00609         return NULL;
00610     }
00611     // bk001220 - currentVM is missing on reconnect
00612     if ( currentVM==NULL )
00613       return NULL;
00614 
00615     if ( currentVM->entryPoint ) {
00616         return (void *)(currentVM->dataBase + intValue);
00617     }
00618     else {
00619         return (void *)(currentVM->dataBase + (intValue & currentVM->dataMask));
00620     }
00621 }

int QDECL VM_Call vm_t vm,
int  callnum,
  ...
 

Definition at line 668 of file vm.c.

References Com_Error(), Com_Printf(), vm_s::compiled, currentVM, ERR_FATAL, i, lastVM, QDECL, r, va_arg, va_end, va_list, va_start, VM_CallCompiled(), VM_CallInterpreted(), and vm_t.

Referenced by CIN_PlayCinematic(), CL_CGameRendering(), CL_CharEvent(), CL_Disconnect(), CL_Frame(), CL_GameCommand(), CL_InitCGame(), CL_InitUI(), CL_KeyEvent(), CL_MouseEvent(), CL_ShutdownCGame(), CL_ShutdownUI(), Con_MessageMode3_f(), Con_MessageMode4_f(), SCR_DrawScreenField(), SV_BotFrame(), SV_ClientEnterWorld(), SV_ClientThink(), SV_DirectConnect(), SV_DropClient(), SV_ExecuteClientCommand(), SV_Frame(), SV_GameCommand(), SV_InitGameVM(), SV_MapRestart_f(), SV_RestartGameProgs(), SV_ShutdownGameProgs(), SV_SpawnServer(), SV_UpdateUserinfo_f(), UI_GameCommand(), and UI_usesUniqueCDKey().

00668                                                 {
00669     vm_t    *oldVM;
00670     int     r;
00671     int i;
00672     int args[16];
00673     va_list ap;
00674 
00675 
00676     if ( !vm ) {
00677         Com_Error( ERR_FATAL, "VM_Call with NULL vm" );
00678     }
00679 
00680     oldVM = currentVM;
00681     currentVM = vm;
00682     lastVM = vm;
00683 
00684     if ( vm_debugLevel ) {
00685       Com_Printf( "VM_Call( %i )\n", callnum );
00686     }
00687 
00688     // if we have a dll loaded, call it directly
00689     if ( vm->entryPoint ) {
00690         //rcg010207 -  see dissertation at top of VM_DllSyscall() in this file.
00691         va_start(ap, callnum);
00692         for (i = 0; i < sizeof (args) / sizeof (args[i]); i++) {
00693             args[i] = va_arg(ap, int);
00694         }
00695         va_end(ap);
00696 
00697         r = vm->entryPoint( callnum,  args[0],  args[1],  args[2], args[3],
00698                             args[4],  args[5],  args[6], args[7],
00699                             args[8],  args[9], args[10], args[11],
00700                             args[12], args[13], args[14], args[15]);
00701     } else if ( vm->compiled ) {
00702         r = VM_CallCompiled( vm, &callnum );
00703     } else {
00704         r = VM_CallInterpreted( vm, &callnum );
00705     }
00706 
00707     if ( oldVM != NULL ) // bk001220 - assert(currentVM!=NULL) for oldVM==NULL
00708       currentVM = oldVM;
00709     return r;
00710 }

Here is the call graph for this function:

void VM_Clear void   ) 
 

Definition at line 595 of file vm.c.

References Com_Memset(), currentVM, vm_s::dllHandle, i, lastVM, Sys_UnloadDll(), vm_t, and vmTable.

Referenced by Hunk_Clear().

00595                     {
00596     int i;
00597     for (i=0;i<MAX_VM; i++) {
00598         if ( vmTable[i].dllHandle ) {
00599             Sys_UnloadDll( vmTable[i].dllHandle );
00600         }
00601         Com_Memset( &vmTable[i], 0, sizeof( vm_t ) );
00602     }
00603     currentVM = NULL;
00604     lastVM = NULL;
00605 }

Here is the call graph for this function:

vm_t* VM_Create const char *  module,
int(*)(int *)  systemCalls,
vmInterpret_t  interpret
 

Definition at line 435 of file vm.c.

References byte, vm_s::codeLength, Com_Error(), Com_Memcpy(), Com_Printf(), Com_sprintf(), vm_s::compiled, Cvar_VariableValue(), vm_s::dataBase, vm_s::dataMask, vm_s::dllHandle, ERR_FATAL, vm_s::fqpath, FS_FreeFile(), FS_ReadFile(), h_high, header, Hunk_Alloc(), Hunk_MemoryRemaining(), i, vm_s::instructionPointers, vm_s::instructionPointersLength, length(), LittleLong(), vm_s::name, name, vm_s::programStack, Q_stricmp(), Q_strncpyz(), vm_s::stackBottom, Sys_LoadDll(), vm_s::systemCall, VM_Compile(), VM_DllSyscall(), VM_Free(), VM_LoadSymbols(), VM_MAGIC, VM_PrepareInterpreter(), vm_t, and vmTable.

Referenced by CL_InitCGame(), CL_InitUI(), SV_InitGameProgs(), and VM_Restart().

00436                                           {
00437     vm_t        *vm;
00438     vmHeader_t  *header;
00439     int         length;
00440     int         dataLength;
00441     int         i, remaining;
00442     char        filename[MAX_QPATH];
00443 
00444     if ( !module || !module[0] || !systemCalls ) {
00445         Com_Error( ERR_FATAL, "VM_Create: bad parms" );
00446     }
00447 
00448     remaining = Hunk_MemoryRemaining();
00449 
00450     // see if we already have the VM
00451     for ( i = 0 ; i < MAX_VM ; i++ ) {
00452         if (!Q_stricmp(vmTable[i].name, module)) {
00453             vm = &vmTable[i];
00454             return vm;
00455         }
00456     }
00457 
00458     // find a free vm
00459     for ( i = 0 ; i < MAX_VM ; i++ ) {
00460         if ( !vmTable[i].name[0] ) {
00461             break;
00462         }
00463     }
00464 
00465     if ( i == MAX_VM ) {
00466         Com_Error( ERR_FATAL, "VM_Create: no free vm_t" );
00467     }
00468 
00469     vm = &vmTable[i];
00470 
00471     Q_strncpyz( vm->name, module, sizeof( vm->name ) );
00472     vm->systemCall = systemCalls;
00473 
00474     // never allow dll loading with a demo
00475     if ( interpret == VMI_NATIVE ) {
00476         if ( Cvar_VariableValue( "fs_restrict" ) ) {
00477             interpret = VMI_COMPILED;
00478         }
00479     }
00480 
00481     if ( interpret == VMI_NATIVE ) {
00482         // try to load as a system dll
00483         Com_Printf( "Loading dll file %s.\n", vm->name );
00484         vm->dllHandle = Sys_LoadDll( module, vm->fqpath , &vm->entryPoint, VM_DllSyscall );
00485         if ( vm->dllHandle ) {
00486             return vm;
00487         }
00488 
00489         Com_Printf( "Failed to load dll, looking for qvm.\n" );
00490         interpret = VMI_COMPILED;
00491     }
00492 
00493     // load the image
00494     Com_sprintf( filename, sizeof(filename), "vm/%s.qvm", vm->name );
00495     Com_Printf( "Loading vm file %s.\n", filename );
00496     length = FS_ReadFile( filename, (void **)&header );
00497     if ( !header ) {
00498         Com_Printf( "Failed.\n" );
00499         VM_Free( vm );
00500         return NULL;
00501     }
00502 
00503     // byte swap the header
00504     for ( i = 0 ; i < sizeof( *header ) / 4 ; i++ ) {
00505         ((int *)header)[i] = LittleLong( ((int *)header)[i] );
00506     }
00507 
00508     // validate
00509     if ( header->vmMagic != VM_MAGIC
00510         || header->bssLength < 0 
00511         || header->dataLength < 0 
00512         || header->litLength < 0 
00513         || header->codeLength <= 0 ) {
00514         VM_Free( vm );
00515         Com_Error( ERR_FATAL, "%s has bad header", filename );
00516     }
00517 
00518     // round up to next power of 2 so all data operations can
00519     // be mask protected
00520     dataLength = header->dataLength + header->litLength + header->bssLength;
00521     for ( i = 0 ; dataLength > ( 1 << i ) ; i++ ) {
00522     }
00523     dataLength = 1 << i;
00524 
00525     // allocate zero filled space for initialized and uninitialized data
00526     vm->dataBase = Hunk_Alloc( dataLength, h_high );
00527     vm->dataMask = dataLength - 1;
00528 
00529     // copy the intialized data
00530     Com_Memcpy( vm->dataBase, (byte *)header + header->dataOffset, header->dataLength + header->litLength );
00531 
00532     // byte swap the longs
00533     for ( i = 0 ; i < header->dataLength ; i += 4 ) {
00534         *(int *)(vm->dataBase + i) = LittleLong( *(int *)(vm->dataBase + i ) );
00535     }
00536 
00537     // allocate space for the jump targets, which will be filled in by the compile/prep functions
00538     vm->instructionPointersLength = header->instructionCount * 4;
00539     vm->instructionPointers = Hunk_Alloc( vm->instructionPointersLength, h_high );
00540 
00541     // copy or compile the instructions
00542     vm->codeLength = header->codeLength;
00543 
00544     if ( interpret >= VMI_COMPILED ) {
00545         vm->compiled = qtrue;
00546         VM_Compile( vm, header );
00547     } else {
00548         vm->compiled = qfalse;
00549         VM_PrepareInterpreter( vm, header );
00550     }
00551 
00552     // free the original file
00553     FS_FreeFile( header );
00554 
00555     // load the map file
00556     VM_LoadSymbols( vm );
00557 
00558     // the stack is implicitly at the end of the image
00559     vm->programStack = vm->dataMask + 1;
00560     vm->stackBottom = vm->programStack - STACK_SIZE;
00561 
00562     Com_Printf("%s loaded in %d bytes on the hunk\n", module, remaining - Hunk_MemoryRemaining());
00563 
00564     return vm;
00565 }

Here is the call graph for this function:

void VM_Debug int  level  ) 
 

Definition at line 57 of file vm.c.

References vm_debugLevel.

Referenced by CL_CGameRendering(), and VM_CallInterpreted().

00057                            {
00058     vm_debugLevel = level;
00059 }

int QDECL VM_DllSyscall int  arg,
  ...
 

Definition at line 327 of file vm.c.

References currentVM, i, QDECL, vm_s::systemCall, va_arg, va_end, va_list, and va_start.

Referenced by VM_Create().

00327                                         {
00328 #if ((defined __linux__) && (defined __powerpc__))
00329   // rcg010206 - see commentary above
00330   int args[16];
00331   int i;
00332   va_list ap;
00333   
00334   args[0] = arg;
00335   
00336   va_start(ap, arg);
00337   for (i = 1; i < sizeof (args) / sizeof (args[i]); i++)
00338     args[i] = va_arg(ap, int);
00339   va_end(ap);
00340   
00341   return currentVM->systemCall( args );
00342 #else // original id code
00343     return currentVM->systemCall( &arg );
00344 #endif
00345 }

void* VM_ExplicitArgPtr vm_t vm,
int  intValue
 

Definition at line 623 of file vm.c.

References currentVM, vm_s::dataBase, vm_s::dataMask, and vm_t.

Referenced by SV_DirectConnect(), SV_MapRestart_f(), and SV_SpawnServer().

00623                                                   {
00624     if ( !intValue ) {
00625         return NULL;
00626     }
00627 
00628     // bk010124 - currentVM is missing on reconnect here as well?
00629     if ( currentVM==NULL )
00630       return NULL;
00631 
00632     //
00633     if ( vm->entryPoint ) {
00634         return (void *)(vm->dataBase + intValue);
00635     }
00636     else {
00637         return (void *)(vm->dataBase + (intValue & vm->dataMask));
00638     }
00639 }

void VM_Free vm_t vm  ) 
 

Definition at line 572 of file vm.c.

References vm_s::codeBase, Com_Memset(), currentVM, vm_s::dataBase, vm_s::dllHandle, vm_s::instructionPointers, lastVM, Sys_UnloadDll(), vm_t, and Z_Free().

Referenced by CL_ShutdownCGame(), CL_ShutdownUI(), SV_ShutdownGameProgs(), VM_Create(), and VM_Restart().

00572                          {
00573 
00574     if ( vm->dllHandle ) {
00575         Sys_UnloadDll( vm->dllHandle );
00576         Com_Memset( vm, 0, sizeof( *vm ) );
00577     }
00578 #if 0   // now automatically freed by hunk
00579     if ( vm->codeBase ) {
00580         Z_Free( vm->codeBase );
00581     }
00582     if ( vm->dataBase ) {
00583         Z_Free( vm->dataBase );
00584     }
00585     if ( vm->instructionPointers ) {
00586         Z_Free( vm->instructionPointers );
00587     }
00588 #endif
00589     Com_Memset( vm, 0, sizeof( *vm ) );
00590 
00591     currentVM = NULL;
00592     lastVM = NULL;
00593 }

Here is the call graph for this function:

void VM_Init void   ) 
 

Definition at line 66 of file vm.c.

References Cmd_AddCommand(), Com_Memset(), CVAR_ARCHIVE, Cvar_Get(), VM_VmInfo_f(), VM_VmProfile_f(), and vmTable.

Referenced by Com_Init().

00066                      {
00067     Cvar_Get( "vm_cgame", "2", CVAR_ARCHIVE );  // !@# SHIP WITH SET TO 2
00068     Cvar_Get( "vm_game", "2", CVAR_ARCHIVE );   // !@# SHIP WITH SET TO 2
00069     Cvar_Get( "vm_ui", "2", CVAR_ARCHIVE );     // !@# SHIP WITH SET TO 2
00070 
00071     Cmd_AddCommand ("vmprofile", VM_VmProfile_f );
00072     Cmd_AddCommand ("vminfo", VM_VmInfo_f );
00073 
00074     Com_Memset( vmTable, 0, sizeof( vmTable ) );
00075 }

Here is the call graph for this function:

void VM_LoadSymbols vm_t vm  ) 
 

Definition at line 211 of file vm.c.

References com_developer, COM_Parse(), Com_Printf(), Com_sprintf(), COM_StripExtension(), count, FS_FreeFile(), FS_ReadFile(), h_high, Hunk_Alloc(), vm_s::instructionPointers, vm_s::instructionPointersLength, cvar_s::integer, vm_s::name, name, vmSymbol_s::next, vm_s::numSymbols, ParseHex(), Q_strncpyz(), segment, strlen(), vm_s::symbols, symbols, token, value, vm_t, and vmSymbol_t.

Referenced by VM_Create().

00211                                 {
00212     int     len;
00213     char    *mapfile, *text_p, *token;
00214     char    name[MAX_QPATH];
00215     char    symbols[MAX_QPATH];
00216     vmSymbol_t  **prev, *sym;
00217     int     count;
00218     int     value;
00219     int     chars;
00220     int     segment;
00221     int     numInstructions;
00222 
00223     // don't load symbols if not developer
00224     if ( !com_developer->integer ) {
00225         return;
00226     }
00227 
00228     COM_StripExtension( vm->name, name );
00229     Com_sprintf( symbols, sizeof( symbols ), "vm/%s.map", name );
00230     len = FS_ReadFile( symbols, (void **)&mapfile );
00231     if ( !mapfile ) {
00232         Com_Printf( "Couldn't load symbol file: %s\n", symbols );
00233         return;
00234     }
00235 
00236     numInstructions = vm->instructionPointersLength >> 2;
00237 
00238     // parse the symbols
00239     text_p = mapfile;
00240     prev = &vm->symbols;
00241     count = 0;
00242 
00243     while ( 1 ) {
00244         token = COM_Parse( &text_p );
00245         if ( !token[0] ) {
00246             break;
00247         }
00248         segment = ParseHex( token );
00249         if ( segment ) {
00250             COM_Parse( &text_p );
00251             COM_Parse( &text_p );
00252             continue;       // only load code segment values
00253         }
00254 
00255         token = COM_Parse( &text_p );
00256         if ( !token[0] ) {
00257             Com_Printf( "WARNING: incomplete line at end of file\n" );
00258             break;
00259         }
00260         value = ParseHex( token );
00261 
00262         token = COM_Parse( &text_p );
00263         if ( !token[0] ) {
00264             Com_Printf( "WARNING: incomplete line at end of file\n" );
00265             break;
00266         }
00267         chars = strlen( token );
00268         sym = Hunk_Alloc( sizeof( *sym ) + chars, h_high );
00269         *prev = sym;
00270         prev = &sym->next;
00271         sym->next = NULL;
00272 
00273         // convert value from an instruction number to a code offset
00274         if ( value >= 0 && value < numInstructions ) {
00275             value = vm->instructionPointers[value];
00276         }
00277 
00278         sym->symValue = value;
00279         Q_strncpyz( sym->symName, token, chars + 1 );
00280 
00281         count++;
00282     }
00283 
00284     vm->numSymbols = count;
00285     Com_Printf( "%i symbols parsed from %s\n", count, symbols );
00286     FS_FreeFile( mapfile );
00287 }

Here is the call graph for this function:

void VM_LogSyscalls int *  args  ) 
 

Definition at line 815 of file vm.c.

References currentVM, vm_s::dataBase, f, fopen(), and fprintf().

00815                                  {
00816     static  int     callnum;
00817     static  FILE    *f;
00818 
00819     if ( !f ) {
00820         f = fopen("syscalls.log", "w" );
00821     }
00822     callnum++;
00823     fprintf(f, "%i: %i (%i) = %i %i %i %i\n", callnum, args - (int *)currentVM->dataBase,
00824         args[0], args[1], args[2], args[3], args[4] );
00825 }

Here is the call graph for this function:

int QDECL VM_ProfileSort const void *  a,
const void *  b
[static]
 

Definition at line 714 of file vm.c.

References vmSymbol_s::profileCount, QDECL, and vmSymbol_t.

Referenced by VM_VmProfile_f().

00714                                                                 {
00715     vmSymbol_t  *sa, *sb;
00716 
00717     sa = *(vmSymbol_t **)a;
00718     sb = *(vmSymbol_t **)b;
00719 
00720     if ( sa->profileCount < sb->profileCount ) {
00721         return -1;
00722     }
00723     if ( sa->profileCount > sb->profileCount ) {
00724         return 1;
00725     }
00726     return 0;
00727 }

vm_t* VM_Restart vm_t vm  ) 
 

Definition at line 355 of file vm.c.

References byte, Com_Error(), Com_Memcpy(), Com_Memset(), Com_Printf(), Com_sprintf(), vm_s::dataBase, vm_s::dllHandle, ERR_DROP, ERR_FATAL, FS_FreeFile(), FS_ReadFile(), header, i, int(), length(), LittleLong(), vm_s::name, name, Q_strncpyz(), vm_s::systemCall, VM_Create(), VM_Free(), VM_MAGIC, vm_t, and VMI_NATIVE.

Referenced by SV_RestartGameProgs().

00355                              {
00356     vmHeader_t  *header;
00357     int         length;
00358     int         dataLength;
00359     int         i;
00360     char        filename[MAX_QPATH];
00361 
00362     // DLL's can't be restarted in place
00363     if ( vm->dllHandle ) {
00364         char    name[MAX_QPATH];
00365         int         (*systemCall)( int *parms );
00366         
00367         systemCall = vm->systemCall;    
00368         Q_strncpyz( name, vm->name, sizeof( name ) );
00369 
00370         VM_Free( vm );
00371 
00372         vm = VM_Create( name, systemCall, VMI_NATIVE );
00373         return vm;
00374     }
00375 
00376     // load the image
00377     Com_Printf( "VM_Restart()\n", filename );
00378     Com_sprintf( filename, sizeof(filename), "vm/%s.qvm", vm->name );
00379     Com_Printf( "Loading vm file %s.\n", filename );
00380     length = FS_ReadFile( filename, (void **)&header );
00381     if ( !header ) {
00382         Com_Error( ERR_DROP, "VM_Restart failed.\n" );
00383     }
00384 
00385     // byte swap the header
00386     for ( i = 0 ; i < sizeof( *header ) / 4 ; i++ ) {
00387         ((int *)header)[i] = LittleLong( ((int *)header)[i] );
00388     }
00389 
00390     // validate
00391     if ( header->vmMagic != VM_MAGIC
00392         || header->bssLength < 0 
00393         || header->dataLength < 0 
00394         || header->litLength < 0 
00395         || header->codeLength <= 0 ) {
00396         VM_Free( vm );
00397         Com_Error( ERR_FATAL, "%s has bad header", filename );
00398     }
00399 
00400     // round up to next power of 2 so all data operations can
00401     // be mask protected
00402     dataLength = header->dataLength + header->litLength + header->bssLength;
00403     for ( i = 0 ; dataLength > ( 1 << i ) ; i++ ) {
00404     }
00405     dataLength = 1 << i;
00406 
00407     // clear the data
00408     Com_Memset( vm->dataBase, 0, dataLength );
00409 
00410     // copy the intialized data
00411     Com_Memcpy( vm->dataBase, (byte *)header + header->dataOffset, header->dataLength + header->litLength );
00412 
00413     // byte swap the longs
00414     for ( i = 0 ; i < header->dataLength ; i += 4 ) {
00415         *(int *)(vm->dataBase + i) = LittleLong( *(int *)(vm->dataBase + i ) );
00416     }
00417 
00418     // free the original file
00419     FS_FreeFile( header );
00420 
00421     return vm;
00422 }

Here is the call graph for this function:

const char* VM_SymbolForCompiledPointer vm_t vm,
void *  code
 

Definition at line 154 of file vm.c.

References code, vm_s::codeBase, vm_s::codeLength, i, vm_s::instructionPointers, vm_t, and VM_ValueToSymbol().

00154                                                                 {
00155     int         i;
00156 
00157     if ( code < (void *)vm->codeBase ) {
00158         return "Before code block";
00159     }
00160     if ( code >= (void *)(vm->codeBase + vm->codeLength) ) {
00161         return "After code block";
00162     }
00163 
00164     // find which original instruction it is after
00165     for ( i = 0 ; i < vm->codeLength ; i++ ) {
00166         if ( (void *)vm->instructionPointers[i] > code ) {
00167             break;
00168         }
00169     }
00170     i--;
00171 
00172     // now look up the bytecode instruction pointer
00173     return VM_ValueToSymbol( vm, i );
00174 }

Here is the call graph for this function:

int VM_SymbolToValue vm_t vm,
const char *  symbol
 

Definition at line 137 of file vm.c.

References vmSymbol_s::next, strcmp(), vm_s::symbols, vmSymbol_s::symName, vmSymbol_s::symValue, vm_t, and vmSymbol_t.

00137                                                      {
00138     vmSymbol_t  *sym;
00139 
00140     for ( sym = vm->symbols ; sym ; sym = sym->next ) {
00141         if ( !strcmp( symbol, sym->symName ) ) {
00142             return sym->symValue;
00143         }
00144     }
00145     return 0;
00146 }

Here is the call graph for this function:

vmSymbol_t* VM_ValueToFunctionSymbol vm_t vm,
int  value
 

Definition at line 115 of file vm.c.

References vmSymbol_s::next, vm_s::symbols, vmSymbol_s::symValue, vm_t, and vmSymbol_t.

Referenced by VM_CallInterpreted().

00115                                                             {
00116     vmSymbol_t  *sym;
00117     static vmSymbol_t   nullSym;
00118 
00119     sym = vm->symbols;
00120     if ( !sym ) {
00121         return &nullSym;
00122     }
00123 
00124     while ( sym->next && sym->next->symValue <= value ) {
00125         sym = sym->next;
00126     }
00127 
00128     return sym;
00129 }

const char* VM_ValueToSymbol vm_t vm,
int  value
 

Definition at line 85 of file vm.c.

References Com_sprintf(), vmSymbol_s::next, vm_s::symbols, vmSymbol_s::symName, vmSymbol_s::symValue, value, vm_t, and vmSymbol_t.

Referenced by VM_CallInterpreted(), VM_StackTrace(), and VM_SymbolForCompiledPointer().

00085                                                     {
00086     vmSymbol_t  *sym;
00087     static char     text[MAX_TOKEN_CHARS];
00088 
00089     sym = vm->symbols;
00090     if ( !sym ) {
00091         return "NO SYMBOLS";
00092     }
00093 
00094     // find the symbol
00095     while ( sym->next && sym->next->symValue <= value ) {
00096         sym = sym->next;
00097     }
00098 
00099     if ( value == sym->symValue ) {
00100         return sym->symName;
00101     }
00102 
00103     Com_sprintf( text, sizeof( text ), "%s+%i", sym->symName, value - sym->symValue );
00104 
00105     return text;
00106 }

Here is the call graph for this function:

void* VM_VM2C vmptr_t  p,
int  length
 

Definition at line 53 of file vm.c.

00053                                           {
00054     return (void *)p;
00055 }

void VM_VmInfo_f void   ) 
 

Definition at line 782 of file vm.c.

References vm_s::codeLength, Com_Printf(), vm_s::compiled, vm_s::dataMask, vm_s::dllHandle, i, vm_s::instructionPointersLength, vm_s::name, vm_t, and vmTable.

Referenced by VM_Init().

00782                          {
00783     vm_t    *vm;
00784     int     i;
00785 
00786     Com_Printf( "Registered virtual machines:\n" );
00787     for ( i = 0 ; i < MAX_VM ; i++ ) {
00788         vm = &vmTable[i];
00789         if ( !vm->name[0] ) {
00790             break;
00791         }
00792         Com_Printf( "%s : ", vm->name );
00793         if ( vm->dllHandle ) {
00794             Com_Printf( "native\n" );
00795             continue;
00796         }
00797         if ( vm->compiled ) {
00798             Com_Printf( "compiled on load\n" );
00799         } else {
00800             Com_Printf( "interpreted\n" );
00801         }
00802         Com_Printf( "    code length : %7i\n", vm->codeLength );
00803         Com_Printf( "    table length: %7i\n", vm->instructionPointersLength );
00804         Com_Printf( "    data length : %7i\n", vm->dataMask + 1 );
00805     }
00806 }

Here is the call graph for this function:

void VM_VmProfile_f void   ) 
 

Definition at line 735 of file vm.c.

References Com_Printf(), i, vmSymbol_s::next, vm_s::numSymbols, vmSymbol_s::profileCount, qsort(), vm_s::symbols, vmSymbol_s::symName, VM_ProfileSort(), vm_t, vmSymbol_t, Z_Free(), and Z_Malloc().

Referenced by VM_Init().

00735                             {
00736     vm_t        *vm;
00737     vmSymbol_t  **sorted, *sym;
00738     int         i;
00739     double      total;
00740 
00741     if ( !lastVM ) {
00742         return;
00743     }
00744 
00745     vm = lastVM;
00746 
00747     if ( !vm->numSymbols ) {
00748         return;
00749     }
00750 
00751     sorted = Z_Malloc( vm->numSymbols * sizeof( *sorted ) );
00752     sorted[0] = vm->symbols;
00753     total = sorted[0]->profileCount;
00754     for ( i = 1 ; i < vm->numSymbols ; i++ ) {
00755         sorted[i] = sorted[i-1]->next;
00756         total += sorted[i]->profileCount;
00757     }
00758 
00759     qsort( sorted, vm->numSymbols, sizeof( *sorted ), VM_ProfileSort );
00760 
00761     for ( i = 0 ; i < vm->numSymbols ; i++ ) {
00762         int     perc;
00763 
00764         sym = sorted[i];
00765 
00766         perc = 100 * (float) sym->profileCount / total;
00767         Com_Printf( "%2i%% %9i %s\n", perc, sym->profileCount, sym->symName );
00768         sym->profileCount = 0;
00769     }
00770 
00771     Com_Printf("    %9.0f total\n", total );
00772 
00773     Z_Free( sorted );
00774 }

Here is the call graph for this function:


Variable Documentation

vm_t* currentVM = NULL
 

Definition at line 39 of file vm.c.

Referenced by callAsmCall(), VM_ArgPtr(), VM_Call(), VM_CallCompiled(), VM_Clear(), VM_DllSyscall(), VM_ExplicitArgPtr(), VM_Free(), and VM_LogSyscalls().

vm_t* lastVM = NULL
 

Definition at line 40 of file vm.c.

Referenced by VM_Call(), VM_Clear(), and VM_Free().

int vm_debugLevel
 

Definition at line 41 of file vm.c.

Referenced by VM_CallInterpreted(), and VM_Debug().

vm_t vmTable[MAX_VM]
 

Definition at line 44 of file vm.c.

Referenced by VM_Clear(), VM_Create(), VM_Init(), and VM_VmInfo_f().


Generated on Thu Aug 25 14:56:10 2005 for Quake III Arena by  doxygen 1.3.9.1