Home | History | Annotate | Download | only in back
      1 /*
      2  * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
      3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      4  *
      5  * This code is free software; you can redistribute it and/or modify it
      6  * under the terms of the GNU General Public License version 2 only, as
      7  * published by the Free Software Foundation.  Oracle designates this
      8  * particular file as subject to the "Classpath" exception as provided
      9  * by Oracle in the LICENSE file that accompanied this code.
     10  *
     11  * This code is distributed in the hope that it will be useful, but WITHOUT
     12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  * version 2 for more details (a copy is included in the LICENSE file that
     15  * accompanied this code).
     16  *
     17  * You should have received a copy of the GNU General Public License version
     18  * 2 along with this work; if not, write to the Free Software Foundation,
     19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     20  *
     21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     22  * or visit www.oracle.com if you need additional information or have any
     23  * questions.
     24  */
     25 
     26 #include <setjmp.h>
     27 
     28 #include "util.h"
     29 #include "SDE.h"
     30 
     31 #ifdef __APPLE__
     32 /* use setjmp/longjmp versions that do not save/restore the signal mask */
     33 #define setjmp _setjmp
     34 #define longjmp _longjmp
     35 #endif
     36 
     37 /**
     38  * This SourceDebugExtension code does not
     39  * allow concurrent translation - due to caching method.
     40  * A separate thread setting the default stratum ID
     41  * is, however, fine.
     42  */
     43 
     44 #define INIT_SIZE_FILE 10
     45 #define INIT_SIZE_LINE 100
     46 #define INIT_SIZE_STRATUM 3
     47 
     48 #define BASE_STRATUM_NAME "Java"
     49 
     50 #define null NULL
     51 #define true JNI_TRUE
     52 #define false JNI_FALSE
     53 #define String char *
     54 #define private static
     55 
     56 typedef struct {
     57   int fileId;
     58   String sourceName;
     59   String sourcePath; // do not read - use accessor
     60   int isConverted;
     61 } FileTableRecord;
     62 
     63 typedef struct {
     64     int jplsStart;
     65     int jplsEnd;
     66     int jplsLineInc;
     67     int njplsStart;
     68     int njplsEnd;
     69     int fileId;
     70 } LineTableRecord;
     71 
     72 typedef struct {
     73     String id;
     74     int fileIndex;
     75     int lineIndex;
     76 } StratumTableRecord;
     77 
     78 /* back-end wide value for default stratum */
     79 private String globalDefaultStratumId = null;
     80 
     81 /* reference type default */
     82 private String defaultStratumId = null;
     83 
     84 private jclass cachedClass = NULL;
     85 
     86 private FileTableRecord* fileTable;
     87 private LineTableRecord* lineTable;
     88 private StratumTableRecord* stratumTable;
     89 
     90 private int fileTableSize;
     91 private int lineTableSize;
     92 private int stratumTableSize;
     93 
     94 private int fileIndex;
     95 private int lineIndex;
     96 private int stratumIndex = 0;
     97 private int currentFileId;
     98 
     99 private int defaultStratumIndex;
    100 private int baseStratumIndex;
    101 private char* sdePos;
    102 
    103 private char* jplsFilename = null;
    104 private char* NullString = null;
    105 
    106 /* mangled in parse, cannot be parsed.  Must be kept. */
    107 private String sourceDebugExtension;
    108 
    109 private jboolean sourceMapIsValid;
    110 
    111 private jmp_buf jmp_buf_env;
    112 
    113 private int stratumTableIndex(String stratumId);
    114 private int stiLineTableIndex(int sti, int jplsLine);
    115 private int stiLineNumber(int sti, int lti, int jplsLine);
    116 private void decode(void);
    117 private void ignoreWhite(void);
    118 private jboolean isValid(void);
    119 
    120     private void
    121     loadDebugInfo(JNIEnv *env, jclass clazz) {
    122 
    123         if (!isSameObject(env, clazz, cachedClass)) {
    124             /* Not the same - swap out the info */
    125 
    126             /* Delete existing info */
    127             if ( cachedClass != null ) {
    128                 tossGlobalRef(env, &cachedClass);
    129                 cachedClass = null;
    130             }
    131             if ( sourceDebugExtension!=null ) {
    132                 jvmtiDeallocate(sourceDebugExtension);
    133             }
    134             sourceDebugExtension = null;
    135 
    136             /* Init info */
    137             lineTable = null;
    138             fileTable = null;
    139             stratumTable = null;
    140             lineTableSize = 0;
    141             fileTableSize = 0;
    142             stratumTableSize = 0;
    143             fileIndex = 0;
    144             lineIndex = 0;
    145             stratumIndex = 0;
    146             currentFileId = 0;
    147             defaultStratumId = null;
    148             defaultStratumIndex = -1;
    149             baseStratumIndex = -2; /* so as not to match -1 above */
    150             sourceMapIsValid = false;
    151 
    152             if (getSourceDebugExtension(clazz, &sourceDebugExtension) ==
    153                 JVMTI_ERROR_NONE) {
    154                 sdePos = sourceDebugExtension;
    155                 if (setjmp(jmp_buf_env) == 0) {
    156                     /* this is the initial (non-error) case, do parse */
    157                     decode();
    158                 }
    159             }
    160 
    161             cachedClass = null;
    162             saveGlobalRef(env, clazz, &cachedClass);
    163         }
    164     }
    165 
    166     /* Return 1 if match, 0 if no match */
    167     private int
    168     patternMatch(char *classname, const char *pattern) {
    169         int pattLen;
    170         int compLen;
    171         char *start;
    172         int offset;
    173 
    174         if (pattern == NULL || classname == NULL) {
    175             return 0;
    176         }
    177         pattLen = (int)strlen(pattern);
    178 
    179         if ((pattern[0] != '*') && (pattern[pattLen-1] != '*')) {
    180             return strcmp(pattern, classname) == 0;
    181         }
    182 
    183         compLen = pattLen - 1;
    184         offset = (int)strlen(classname) - compLen;
    185         if (offset < 0) {
    186             return 0;
    187         }
    188         if (pattern[0] == '*') {
    189             pattern++;
    190             start = classname + offset;
    191         }  else {
    192             start = classname;
    193         }
    194         return strncmp(pattern, start, compLen) == 0;
    195     }
    196 
    197     /**
    198      * Return 1 if p1 is a SourceName for stratum sti,
    199      * else, return 0.
    200      */
    201     private int
    202     searchOneSourceName(int sti, char *p1) {
    203         int fileIndexStart = stratumTable[sti].fileIndex;
    204         /* one past end */
    205         int fileIndexEnd = stratumTable[sti+1].fileIndex;
    206         int ii;
    207         for (ii = fileIndexStart; ii < fileIndexEnd; ++ii) {
    208             if (patternMatch(fileTable[ii].sourceName, p1)) {
    209               return 1;
    210             }
    211         }
    212         return 0;
    213     }
    214 
    215     /**
    216      * Return 1 if p1 is a SourceName for any stratum
    217      * else, return 0.
    218      */
    219     int searchAllSourceNames(JNIEnv *env,
    220                              jclass clazz,
    221                              char *p1) {
    222         int ii;
    223         loadDebugInfo(env, clazz);
    224         if (!isValid()) {
    225           return 0; /* no SDE or not SourceMap */
    226         }
    227 
    228         for (ii = 0; ii < stratumIndex - 1; ++ii) {
    229             if (searchOneSourceName(ii, p1) == 1) {
    230                 return 1;
    231             }
    232         }
    233         return 0;
    234     }
    235 
    236     /**
    237      * Convert a line number table, as returned by the JVMTI
    238      * function GetLineNumberTable, to one for another stratum.
    239      * Conversion is by overwrite.
    240      * Actual line numbers are not returned - just a unique
    241      * number (file ID in top 16 bits, line number in
    242      * bottom 16 bits) - this is all stepping needs.
    243      */
    244     void
    245     convertLineNumberTable(JNIEnv *env, jclass clazz,
    246                            jint *entryCountPtr,
    247                            jvmtiLineNumberEntry **tablePtr) {
    248         jvmtiLineNumberEntry *fromEntry = *tablePtr;
    249         jvmtiLineNumberEntry *toEntry = *tablePtr;
    250         int cnt = *entryCountPtr;
    251         int lastLn = 0;
    252         int sti;
    253 
    254         loadDebugInfo(env, clazz);
    255         if (!isValid()) {
    256             return; /* no SDE or not SourceMap - return unchanged */
    257         }
    258         sti = stratumTableIndex(globalDefaultStratumId);
    259         if (sti == baseStratumIndex) {
    260             return; /* Java stratum - return unchanged */
    261         }
    262         LOG_MISC(("SDE is re-ordering the line table"));
    263         for (; cnt-->0; ++fromEntry) {
    264             int jplsLine = fromEntry->line_number;
    265             int lti = stiLineTableIndex(sti, jplsLine);
    266             if (lti >= 0) {
    267                 int fileId = lineTable[lti].fileId;
    268                 int ln = stiLineNumber(sti, lti, jplsLine);
    269                 ln += (fileId << 16); /* create line hash */
    270                 if (ln != lastLn) {
    271                     lastLn = ln;
    272                     toEntry->start_location = fromEntry->start_location;
    273                     toEntry->line_number = ln;
    274                     ++toEntry;
    275                 }
    276             }
    277         }
    278         /*LINTED*/
    279         *entryCountPtr = (int)(toEntry - *tablePtr);
    280     }
    281 
    282     /**
    283      * Set back-end wide default stratum ID .
    284      */
    285     void
    286     setGlobalStratumId(char *id) {
    287         globalDefaultStratumId = id;
    288     }
    289 
    290 
    291     private void syntax(String msg) {
    292         char buf[200];
    293         (void)snprintf(buf, sizeof(buf),
    294                 "bad SourceDebugExtension syntax - position %d - %s\n",
    295                 /*LINTED*/
    296                 (int)(sdePos-sourceDebugExtension),
    297                 msg);
    298         JDI_ASSERT_FAILED(buf);
    299 
    300         longjmp(jmp_buf_env, 1);  /* abort parse */
    301     }
    302 
    303     private char sdePeek(void) {
    304         if (*sdePos == 0) {
    305             syntax("unexpected EOF");
    306         }
    307         return *sdePos;
    308     }
    309 
    310     private char sdeRead(void) {
    311         if (*sdePos == 0) {
    312             syntax("unexpected EOF");
    313         }
    314         return *sdePos++;
    315     }
    316 
    317     private void sdeAdvance(void) {
    318         sdePos++;
    319     }
    320 
    321     private void assureLineTableSize(void) {
    322         if (lineIndex >= lineTableSize) {
    323             size_t allocSize;
    324             LineTableRecord* new_lineTable;
    325             int new_lineTableSize;
    326 
    327             new_lineTableSize = lineTableSize == 0?
    328                                   INIT_SIZE_LINE :
    329                                   lineTableSize * 2;
    330             allocSize = new_lineTableSize * (int)sizeof(LineTableRecord);
    331             new_lineTable = jvmtiAllocate((jint)allocSize);
    332             if ( new_lineTable == NULL ) {
    333                 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY, "SDE line table");
    334             }
    335             if ( lineTable!=NULL ) {
    336                 (void)memcpy(new_lineTable, lineTable,
    337                         lineTableSize * (int)sizeof(LineTableRecord));
    338                 jvmtiDeallocate(lineTable);
    339             }
    340             lineTable     = new_lineTable;
    341             lineTableSize = new_lineTableSize;
    342         }
    343     }
    344 
    345     private void assureFileTableSize(void) {
    346         if (fileIndex >= fileTableSize) {
    347             size_t allocSize;
    348             FileTableRecord* new_fileTable;
    349             int new_fileTableSize;
    350 
    351             new_fileTableSize = fileTableSize == 0?
    352                                   INIT_SIZE_FILE :
    353                                   fileTableSize * 2;
    354             allocSize = new_fileTableSize * (int)sizeof(FileTableRecord);
    355             new_fileTable = jvmtiAllocate((jint)allocSize);
    356             if ( new_fileTable == NULL ) {
    357                 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY, "SDE file table");
    358             }
    359             if ( fileTable!=NULL ) {
    360                 (void)memcpy(new_fileTable, fileTable,
    361                         fileTableSize * (int)sizeof(FileTableRecord));
    362                 jvmtiDeallocate(fileTable);
    363             }
    364             fileTable     = new_fileTable;
    365             fileTableSize = new_fileTableSize;
    366         }
    367     }
    368 
    369     private void assureStratumTableSize(void) {
    370         if (stratumIndex >= stratumTableSize) {
    371             size_t allocSize;
    372             StratumTableRecord* new_stratumTable;
    373             int new_stratumTableSize;
    374 
    375             new_stratumTableSize = stratumTableSize == 0?
    376                                   INIT_SIZE_STRATUM :
    377                                   stratumTableSize * 2;
    378             allocSize = new_stratumTableSize * (int)sizeof(StratumTableRecord);
    379             new_stratumTable = jvmtiAllocate((jint)allocSize);
    380             if ( new_stratumTable == NULL ) {
    381                 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY, "SDE stratum table");
    382             }
    383             if ( stratumTable!=NULL ) {
    384                 (void)memcpy(new_stratumTable, stratumTable,
    385                         stratumTableSize * (int)sizeof(StratumTableRecord));
    386                 jvmtiDeallocate(stratumTable);
    387             }
    388             stratumTable     = new_stratumTable;
    389             stratumTableSize = new_stratumTableSize;
    390         }
    391     }
    392 
    393     private String readLine(void) {
    394         char *initialPos;
    395         char ch;
    396 
    397         ignoreWhite();
    398         initialPos = sdePos;
    399         while (((ch = *sdePos) != '\n') && (ch != '\r')) {
    400             if (ch == 0) {
    401                 syntax("unexpected EOF");
    402             }
    403             ++sdePos;
    404         }
    405         *sdePos++ = 0; /* null terminate string - mangles SDE */
    406 
    407         /* check for CR LF */
    408         if ((ch == '\r') && (*sdePos == '\n')) {
    409             ++sdePos;
    410         }
    411         ignoreWhite(); /* leading white */
    412         return initialPos;
    413     }
    414 
    415     private int defaultStratumTableIndex(void) {
    416         if ((defaultStratumIndex == -1) && (defaultStratumId != null)) {
    417             defaultStratumIndex =
    418                 stratumTableIndex(defaultStratumId);
    419         }
    420         return defaultStratumIndex;
    421     }
    422 
    423     private int stratumTableIndex(String stratumId) {
    424         int i;
    425 
    426         if (stratumId == null) {
    427             return defaultStratumTableIndex();
    428         }
    429         for (i = 0; i < (stratumIndex-1); ++i) {
    430             if (strcmp(stratumTable[i].id, stratumId) == 0) {
    431                 return i;
    432             }
    433         }
    434         return defaultStratumTableIndex();
    435     }
    436 
    437 
    438 /*****************************
    439  * below functions/methods are written to compile under either Java or C
    440  *
    441  * Needed support functions:
    442  *   sdePeek()
    443  *   sdeRead()
    444  *   sdeAdvance()
    445  *   readLine()
    446  *   assureLineTableSize()
    447  *   assureFileTableSize()
    448  *   assureStratumTableSize()
    449  *   syntax(String)
    450  *
    451  *   stratumTableIndex(String)
    452  *
    453  * Needed support variables:
    454  *   lineTable
    455  *   lineIndex
    456  *   fileTable
    457  *   fileIndex
    458  *   currentFileId
    459  *
    460  * Needed types:
    461  *   String
    462  *
    463  * Needed constants:
    464  *   NullString
    465  */
    466 
    467     private void ignoreWhite(void) {
    468         char ch;
    469 
    470         while (((ch = sdePeek()) == ' ') || (ch == '\t')) {
    471             sdeAdvance();
    472         }
    473     }
    474 
    475     private void ignoreLine(void) {
    476         char ch;
    477 
    478         do {
    479            ch = sdeRead();
    480         } while ((ch != '\n') && (ch != '\r'));
    481 
    482         /* check for CR LF */
    483         if ((ch == '\r') && (sdePeek() == '\n')) {
    484             sdeAdvance();
    485         }
    486         ignoreWhite(); /* leading white */
    487     }
    488 
    489     private int readNumber(void) {
    490         int value = 0;
    491         char ch;
    492 
    493         ignoreWhite();
    494         while (((ch = sdePeek()) >= '0') && (ch <= '9')) {
    495             sdeAdvance();
    496             value = (value * 10) + ch - '0';
    497         }
    498         ignoreWhite();
    499         return value;
    500     }
    501 
    502     private void storeFile(int fileId, String sourceName, String sourcePath) {
    503         assureFileTableSize();
    504         fileTable[fileIndex].fileId = fileId;
    505         fileTable[fileIndex].sourceName = sourceName;
    506         fileTable[fileIndex].sourcePath = sourcePath;
    507         ++fileIndex;
    508     }
    509 
    510     private void fileLine(void) {
    511         int hasAbsolute = 0; /* acts as boolean */
    512         int fileId;
    513         String sourceName;
    514         String sourcePath = null;
    515 
    516         /* is there an absolute filename? */
    517         if (sdePeek() == '+') {
    518             sdeAdvance();
    519             hasAbsolute = 1;
    520         }
    521         fileId = readNumber();
    522         sourceName = readLine();
    523         if (hasAbsolute == 1) {
    524             sourcePath = readLine();
    525         }
    526         storeFile(fileId, sourceName, sourcePath);
    527     }
    528 
    529     private void storeLine(int jplsStart, int jplsEnd, int jplsLineInc,
    530                   int njplsStart, int njplsEnd, int fileId) {
    531         assureLineTableSize();
    532         lineTable[lineIndex].jplsStart = jplsStart;
    533         lineTable[lineIndex].jplsEnd = jplsEnd;
    534         lineTable[lineIndex].jplsLineInc = jplsLineInc;
    535         lineTable[lineIndex].njplsStart = njplsStart;
    536         lineTable[lineIndex].njplsEnd = njplsEnd;
    537         lineTable[lineIndex].fileId = fileId;
    538         ++lineIndex;
    539     }
    540 
    541     /**
    542      * Parse line translation info.  Syntax is
    543      *     <NJ-start-line> [ # <file-id> ] [ , <line-count> ] :
    544      *                 <J-start-line> [ , <line-increment> ] CR
    545      */
    546     private void lineLine(void) {
    547         int lineCount = 1;
    548         int lineIncrement = 1;
    549         int njplsStart;
    550         int jplsStart;
    551 
    552         njplsStart = readNumber();
    553 
    554         /* is there a fileID? */
    555         if (sdePeek() == '#') {
    556             sdeAdvance();
    557             currentFileId = readNumber();
    558         }
    559 
    560         /* is there a line count? */
    561         if (sdePeek() == ',') {
    562             sdeAdvance();
    563             lineCount = readNumber();
    564         }
    565 
    566         if (sdeRead() != ':') {
    567             syntax("expected ':'");
    568         }
    569         jplsStart = readNumber();
    570         if (sdePeek() == ',') {
    571             sdeAdvance();
    572             lineIncrement = readNumber();
    573         }
    574         ignoreLine(); /* flush the rest */
    575 
    576         storeLine(jplsStart,
    577                   jplsStart + (lineCount * lineIncrement) -1,
    578                   lineIncrement,
    579                   njplsStart,
    580                   njplsStart + lineCount -1,
    581                   currentFileId);
    582     }
    583 
    584     /**
    585      * Until the next stratum section, everything after this
    586      * is in stratumId - so, store the current indicies.
    587      */
    588     private void storeStratum(String stratumId) {
    589         /* remove redundant strata */
    590         if (stratumIndex > 0) {
    591             if ((stratumTable[stratumIndex-1].fileIndex
    592                                             == fileIndex) &&
    593                 (stratumTable[stratumIndex-1].lineIndex
    594                                             == lineIndex)) {
    595                 /* nothing changed overwrite it */
    596                 --stratumIndex;
    597             }
    598         }
    599         /* store the results */
    600         assureStratumTableSize();
    601         stratumTable[stratumIndex].id = stratumId;
    602         stratumTable[stratumIndex].fileIndex = fileIndex;
    603         stratumTable[stratumIndex].lineIndex = lineIndex;
    604         ++stratumIndex;
    605         currentFileId = 0;
    606     }
    607 
    608     /**
    609      * The beginning of a stratum's info
    610      */
    611     private void stratumSection(void) {
    612         storeStratum(readLine());
    613     }
    614 
    615     private void fileSection(void) {
    616         ignoreLine();
    617         while (sdePeek() != '*') {
    618             fileLine();
    619         }
    620     }
    621 
    622     private void lineSection(void) {
    623         ignoreLine();
    624         while (sdePeek() != '*') {
    625             lineLine();
    626         }
    627     }
    628 
    629     /**
    630      * Ignore a section we don't know about.
    631      */
    632     private void ignoreSection(void) {
    633         ignoreLine();
    634         while (sdePeek() != '*') {
    635             ignoreLine();
    636         }
    637     }
    638 
    639     /**
    640      * A base "Java" stratum is always available, though
    641      * it is not in the SourceDebugExtension.
    642      * Create the base stratum.
    643      */
    644     private void createJavaStratum(void) {
    645         baseStratumIndex = stratumIndex;
    646         storeStratum(BASE_STRATUM_NAME);
    647         storeFile(1, jplsFilename, NullString);
    648         /* JPL line numbers cannot exceed 65535 */
    649         storeLine(1, 65536, 1, 1, 65536, 1);
    650         storeStratum("Aux"); /* in case they don't declare */
    651     }
    652 
    653     /**
    654      * Decode a SourceDebugExtension which is in SourceMap format.
    655      * This is the entry point into the recursive descent parser.
    656      */
    657     private void decode(void) {
    658         /* check for "SMAP" - allow EOF if not ours */
    659         if (strlen(sourceDebugExtension) <= 4 ||
    660             (sdeRead() != 'S') ||
    661             (sdeRead() != 'M') ||
    662             (sdeRead() != 'A') ||
    663             (sdeRead() != 'P')) {
    664             return; /* not our info */
    665         }
    666         ignoreLine(); /* flush the rest */
    667         jplsFilename = readLine();
    668         defaultStratumId = readLine();
    669         createJavaStratum();
    670         while (true) {
    671             if (sdeRead() != '*') {
    672                 syntax("expected '*'");
    673             }
    674             switch (sdeRead()) {
    675                 case 'S':
    676                     stratumSection();
    677                     break;
    678                 case 'F':
    679                     fileSection();
    680                     break;
    681                 case 'L':
    682                     lineSection();
    683                     break;
    684                 case 'E':
    685                     /* set end points */
    686                     storeStratum("*terminator*");
    687                     sourceMapIsValid = true;
    688                     return;
    689                 default:
    690                     ignoreSection();
    691             }
    692         }
    693     }
    694 
    695     /***************** query functions ***********************/
    696 
    697     private int stiLineTableIndex(int sti, int jplsLine) {
    698         int i;
    699         int lineIndexStart;
    700         int lineIndexEnd;
    701 
    702         lineIndexStart = stratumTable[sti].lineIndex;
    703         /* one past end */
    704         lineIndexEnd = stratumTable[sti+1].lineIndex;
    705         for (i = lineIndexStart; i < lineIndexEnd; ++i) {
    706             if ((jplsLine >= lineTable[i].jplsStart) &&
    707                             (jplsLine <= lineTable[i].jplsEnd)) {
    708                 return i;
    709             }
    710         }
    711         return -1;
    712     }
    713 
    714     private int stiLineNumber(int sti, int lti, int jplsLine) {
    715         return lineTable[lti].njplsStart +
    716                 (((jplsLine - lineTable[lti].jplsStart) /
    717                                    lineTable[lti].jplsLineInc));
    718     }
    719 
    720     private int fileTableIndex(int sti, int fileId) {
    721         int i;
    722         int fileIndexStart = stratumTable[sti].fileIndex;
    723         /* one past end */
    724         int fileIndexEnd = stratumTable[sti+1].fileIndex;
    725         for (i = fileIndexStart; i < fileIndexEnd; ++i) {
    726             if (fileTable[i].fileId == fileId) {
    727                 return i;
    728             }
    729         }
    730         return -1;
    731     }
    732 
    733     private int stiFileTableIndex(int sti, int lti) {
    734         return fileTableIndex(sti, lineTable[lti].fileId);
    735     }
    736 
    737     private jboolean isValid(void) {
    738         return sourceMapIsValid;
    739     }
    740