1479
1477
Tcl_HashEntry *hePtr =
1480
1478
Tcl_FindHashEntry(iPtr->lineBCPtr, (char *) codePtr);
1483
1481
ExtCmdLoc *eclPtr = Tcl_GetHashValue(hePtr);
1487
CmdFrame *ctxPtr = TclStackAlloc(interp,sizeof(CmdFrame));
1490
if (invoker->type == TCL_LOCATION_BC) {
1492
* Note: Type BC => ctx.data.eval.path is not used.
1493
* ctx.data.tebc.codePtr used instead
1496
TclGetSrcInfoForPc(ctxPtr);
1497
if (ctxPtr->type == TCL_LOCATION_SOURCE) {
1499
* The reference made by 'TclGetSrcInfoForPc' is
1503
Tcl_DecrRefCount(ctxPtr->data.eval.path);
1504
ctxPtr->data.eval.path = NULL;
1508
if (word < ctxPtr->nline) {
1510
* Note: We do not care if the line[word] is -1. This
1511
* is a difference and requires a recompile (location
1512
* changed from absolute to relative, literal is used
1513
* fixed and through variable)
1516
* test info-32.0 using literal of info-24.8
1517
* (dict with ... vs set body ...).
1520
redo = ((eclPtr->type == TCL_LOCATION_SOURCE)
1521
&& (eclPtr->start != ctxPtr->line[word]))
1522
|| ((eclPtr->type == TCL_LOCATION_BC)
1523
&& (ctxPtr->type == TCL_LOCATION_SOURCE));
1526
TclStackFree(interp, ctxPtr);
1483
CmdFrame *ctxPtr = TclStackAlloc(interp,sizeof(CmdFrame));
1487
if (invoker->type == TCL_LOCATION_BC) {
1489
* Note: Type BC => ctx.data.eval.path is not used.
1490
* ctx.data.tebc.codePtr used instead
1493
TclGetSrcInfoForPc(ctxPtr);
1494
if (ctxPtr->type == TCL_LOCATION_SOURCE) {
1496
* The reference made by 'TclGetSrcInfoForPc' is
1500
Tcl_DecrRefCount(ctxPtr->data.eval.path);
1501
ctxPtr->data.eval.path = NULL;
1505
if (word < ctxPtr->nline) {
1507
* Note: We do not care if the line[word] is -1. This
1508
* is a difference and requires a recompile (location
1509
* changed from absolute to relative, literal is used
1510
* fixed and through variable)
1513
* test info-32.0 using literal of info-24.8
1514
* (dict with ... vs set body ...).
1517
redo = ((eclPtr->type == TCL_LOCATION_SOURCE)
1518
&& (eclPtr->start != ctxPtr->line[word]))
1519
|| ((eclPtr->type == TCL_LOCATION_BC)
1520
&& (ctxPtr->type == TCL_LOCATION_SOURCE));
1523
TclStackFree(interp, ctxPtr);
1530
1526
goto recompileObj;
2413
2409
bcFramePtr->data.tebc.pc = (char *) pc;
2414
2410
iPtr->cmdFramePtr = bcFramePtr;
2415
TclArgumentBCEnter((Tcl_Interp*) iPtr, objv, objc,
2416
codePtr, bcFramePtr,
2417
pc - codePtr->codeStart);
2411
if (iPtr->flags & INTERP_DEBUG_FRAME) {
2412
TclArgumentBCEnter((Tcl_Interp *) iPtr, objv, objc,
2413
codePtr, bcFramePtr, pc - codePtr->codeStart);
2418
2415
DECACHE_STACK_INFO();
2419
2416
result = TclEvalObjvInternal(interp, objc, objv,
2420
2417
/* call from TEBC */(char *) -1, -1, 0);
2421
2418
CACHE_STACK_INFO();
2422
TclArgumentBCRelease((Tcl_Interp*) iPtr, objv, objc,
2424
pc - codePtr->codeStart);
2419
if (iPtr->flags & INTERP_DEBUG_FRAME) {
2420
TclArgumentBCRelease((Tcl_Interp *) iPtr, objv, objc,
2421
codePtr, pc - codePtr->codeStart);
2425
2423
iPtr->cmdFramePtr = iPtr->cmdFramePtr->nextPtr;
2427
2425
if (result == TCL_OK) {
8150
8190
* Summary statistics, total and current source and ByteCode sizes.
8153
fprintf(stdout, "\n----------------------------------------------------------------\n");
8155
"Compilation and execution statistics for interpreter 0x%p\n",
8193
Tcl_AppendPrintfToObj(objPtr, "\n----------------------------------------------------------------\n");
8194
Tcl_AppendPrintfToObj(objPtr,
8195
"Compilation and execution statistics for interpreter %#lx\n",
8158
fprintf(stdout, "\nNumber ByteCodes executed %ld\n",
8198
Tcl_AppendPrintfToObj(objPtr, "\nNumber ByteCodes executed %ld\n",
8159
8199
statsPtr->numExecutions);
8160
fprintf(stdout, "Number ByteCodes compiled %ld\n",
8200
Tcl_AppendPrintfToObj(objPtr, "Number ByteCodes compiled %ld\n",
8161
8201
statsPtr->numCompilations);
8162
fprintf(stdout, " Mean executions/compile %.1f\n",
8202
Tcl_AppendPrintfToObj(objPtr, " Mean executions/compile %.1f\n",
8163
8203
statsPtr->numExecutions / (float)statsPtr->numCompilations);
8165
fprintf(stdout, "\nInstructions executed %.0f\n",
8205
Tcl_AppendPrintfToObj(objPtr, "\nInstructions executed %.0f\n",
8166
8206
numInstructions);
8167
fprintf(stdout, " Mean inst/compile %.0f\n",
8207
Tcl_AppendPrintfToObj(objPtr, " Mean inst/compile %.0f\n",
8168
8208
numInstructions / statsPtr->numCompilations);
8169
fprintf(stdout, " Mean inst/execution %.0f\n",
8209
Tcl_AppendPrintfToObj(objPtr, " Mean inst/execution %.0f\n",
8170
8210
numInstructions / statsPtr->numExecutions);
8172
fprintf(stdout, "\nTotal ByteCodes %ld\n",
8212
Tcl_AppendPrintfToObj(objPtr, "\nTotal ByteCodes %ld\n",
8173
8213
statsPtr->numCompilations);
8174
fprintf(stdout, " Source bytes %.6g\n",
8214
Tcl_AppendPrintfToObj(objPtr, " Source bytes %.6g\n",
8175
8215
statsPtr->totalSrcBytes);
8176
fprintf(stdout, " Code bytes %.6g\n",
8216
Tcl_AppendPrintfToObj(objPtr, " Code bytes %.6g\n",
8177
8217
totalCodeBytes);
8178
fprintf(stdout, " ByteCode bytes %.6g\n",
8218
Tcl_AppendPrintfToObj(objPtr, " ByteCode bytes %.6g\n",
8179
8219
statsPtr->totalByteCodeBytes);
8180
fprintf(stdout, " Literal bytes %.6g\n",
8220
Tcl_AppendPrintfToObj(objPtr, " Literal bytes %.6g\n",
8181
8221
totalLiteralBytes);
8182
fprintf(stdout, " table %lu + bkts %lu + entries %lu + objects %lu + strings %.6g\n",
8222
Tcl_AppendPrintfToObj(objPtr, " table %lu + bkts %lu + entries %lu + objects %lu + strings %.6g\n",
8183
8223
(unsigned long) sizeof(LiteralTable),
8184
8224
(unsigned long) (iPtr->literalTable.numBuckets * sizeof(LiteralEntry *)),
8185
8225
(unsigned long) (statsPtr->numLiteralsCreated * sizeof(LiteralEntry)),
8186
8226
(unsigned long) (statsPtr->numLiteralsCreated * sizeof(Tcl_Obj)),
8187
8227
statsPtr->totalLitStringBytes);
8188
fprintf(stdout, " Mean code/compile %.1f\n",
8228
Tcl_AppendPrintfToObj(objPtr, " Mean code/compile %.1f\n",
8189
8229
totalCodeBytes / statsPtr->numCompilations);
8190
fprintf(stdout, " Mean code/source %.1f\n",
8230
Tcl_AppendPrintfToObj(objPtr, " Mean code/source %.1f\n",
8191
8231
totalCodeBytes / statsPtr->totalSrcBytes);
8193
fprintf(stdout, "\nCurrent (active) ByteCodes %ld\n",
8233
Tcl_AppendPrintfToObj(objPtr, "\nCurrent (active) ByteCodes %ld\n",
8194
8234
numCurrentByteCodes);
8195
fprintf(stdout, " Source bytes %.6g\n",
8235
Tcl_AppendPrintfToObj(objPtr, " Source bytes %.6g\n",
8196
8236
statsPtr->currentSrcBytes);
8197
fprintf(stdout, " Code bytes %.6g\n",
8237
Tcl_AppendPrintfToObj(objPtr, " Code bytes %.6g\n",
8198
8238
currentCodeBytes);
8199
fprintf(stdout, " ByteCode bytes %.6g\n",
8239
Tcl_AppendPrintfToObj(objPtr, " ByteCode bytes %.6g\n",
8200
8240
statsPtr->currentByteCodeBytes);
8201
fprintf(stdout, " Literal bytes %.6g\n",
8241
Tcl_AppendPrintfToObj(objPtr, " Literal bytes %.6g\n",
8202
8242
currentLiteralBytes);
8203
fprintf(stdout, " table %lu + bkts %lu + entries %lu + objects %lu + strings %.6g\n",
8243
Tcl_AppendPrintfToObj(objPtr, " table %lu + bkts %lu + entries %lu + objects %lu + strings %.6g\n",
8204
8244
(unsigned long) sizeof(LiteralTable),
8205
8245
(unsigned long) (iPtr->literalTable.numBuckets * sizeof(LiteralEntry *)),
8206
8246
(unsigned long) (iPtr->literalTable.numEntries * sizeof(LiteralEntry)),
8207
8247
(unsigned long) (iPtr->literalTable.numEntries * sizeof(Tcl_Obj)),
8208
8248
statsPtr->currentLitStringBytes);
8209
fprintf(stdout, " Mean code/source %.1f\n",
8249
Tcl_AppendPrintfToObj(objPtr, " Mean code/source %.1f\n",
8210
8250
currentCodeBytes / statsPtr->currentSrcBytes);
8211
fprintf(stdout, " Code + source bytes %.6g (%0.1f mean code/src)\n",
8251
Tcl_AppendPrintfToObj(objPtr, " Code + source bytes %.6g (%0.1f mean code/src)\n",
8212
8252
(currentCodeBytes + statsPtr->currentSrcBytes),
8213
8253
(currentCodeBytes / statsPtr->currentSrcBytes) + 1.0);
8222
8262
numSharedMultX = 0;
8223
fprintf(stdout, "\nTcl_IsShared object check (all objects):\n");
8224
fprintf(stdout, " Object had refcount <=1 (not shared) %ld\n",
8263
Tcl_AppendPrintfToObj(objPtr, "\nTcl_IsShared object check (all objects):\n");
8264
Tcl_AppendPrintfToObj(objPtr, " Object had refcount <=1 (not shared) %ld\n",
8225
8265
tclObjsShared[1]);
8226
8266
for (i = 2; i < TCL_MAX_SHARED_OBJ_STATS; i++) {
8227
fprintf(stdout, " refcount ==%d %ld\n",
8267
Tcl_AppendPrintfToObj(objPtr, " refcount ==%d %ld\n",
8228
8268
i, tclObjsShared[i]);
8229
8269
numSharedMultX += tclObjsShared[i];
8231
fprintf(stdout, " refcount >=%d %ld\n",
8271
Tcl_AppendPrintfToObj(objPtr, " refcount >=%d %ld\n",
8232
8272
i, tclObjsShared[0]);
8233
8273
numSharedMultX += tclObjsShared[0];
8234
fprintf(stdout, " Total shared objects %d\n",
8274
Tcl_AppendPrintfToObj(objPtr, " Total shared objects %d\n",
8235
8275
numSharedMultX);
8268
8308
sharingBytesSaved = (objBytesIfUnshared + strBytesIfUnshared)
8269
8309
- currentLiteralBytes;
8271
fprintf(stdout, "\nTotal objects (all interps) %ld\n",
8311
Tcl_AppendPrintfToObj(objPtr, "\nTotal objects (all interps) %ld\n",
8272
8312
tclObjsAlloced);
8273
fprintf(stdout, "Current objects %ld\n",
8313
Tcl_AppendPrintfToObj(objPtr, "Current objects %ld\n",
8274
8314
(tclObjsAlloced - tclObjsFreed));
8275
fprintf(stdout, "Total literal objects %ld\n",
8315
Tcl_AppendPrintfToObj(objPtr, "Total literal objects %ld\n",
8276
8316
statsPtr->numLiteralsCreated);
8278
fprintf(stdout, "\nCurrent literal objects %d (%0.1f%% of current objects)\n",
8318
Tcl_AppendPrintfToObj(objPtr, "\nCurrent literal objects %d (%0.1f%% of current objects)\n",
8279
8319
globalTablePtr->numEntries,
8280
8320
Percent(globalTablePtr->numEntries, tclObjsAlloced-tclObjsFreed));
8281
fprintf(stdout, " ByteCode literals %ld (%0.1f%% of current literals)\n",
8321
Tcl_AppendPrintfToObj(objPtr, " ByteCode literals %ld (%0.1f%% of current literals)\n",
8282
8322
numByteCodeLits,
8283
8323
Percent(numByteCodeLits, globalTablePtr->numEntries));
8284
fprintf(stdout, " Literals reused > 1x %d\n",
8324
Tcl_AppendPrintfToObj(objPtr, " Literals reused > 1x %d\n",
8285
8325
numSharedMultX);
8286
fprintf(stdout, " Mean reference count %.2f\n",
8326
Tcl_AppendPrintfToObj(objPtr, " Mean reference count %.2f\n",
8287
8327
((double) refCountSum) / globalTablePtr->numEntries);
8288
fprintf(stdout, " Mean len, str reused >1x %.2f\n",
8328
Tcl_AppendPrintfToObj(objPtr, " Mean len, str reused >1x %.2f\n",
8289
8329
(numSharedMultX ? strBytesSharedMultX/numSharedMultX : 0.0));
8290
fprintf(stdout, " Mean len, str used 1x %.2f\n",
8330
Tcl_AppendPrintfToObj(objPtr, " Mean len, str used 1x %.2f\n",
8291
8331
(numSharedOnce ? strBytesSharedOnce/numSharedOnce : 0.0));
8292
fprintf(stdout, " Total sharing savings %.6g (%0.1f%% of bytes if no sharing)\n",
8332
Tcl_AppendPrintfToObj(objPtr, " Total sharing savings %.6g (%0.1f%% of bytes if no sharing)\n",
8293
8333
sharingBytesSaved,
8294
8334
Percent(sharingBytesSaved, objBytesIfUnshared+strBytesIfUnshared));
8295
fprintf(stdout, " Bytes with sharing %.6g\n",
8335
Tcl_AppendPrintfToObj(objPtr, " Bytes with sharing %.6g\n",
8296
8336
currentLiteralBytes);
8297
fprintf(stdout, " table %lu + bkts %lu + entries %lu + objects %lu + strings %.6g\n",
8337
Tcl_AppendPrintfToObj(objPtr, " table %lu + bkts %lu + entries %lu + objects %lu + strings %.6g\n",
8298
8338
(unsigned long) sizeof(LiteralTable),
8299
8339
(unsigned long) (iPtr->literalTable.numBuckets * sizeof(LiteralEntry *)),
8300
8340
(unsigned long) (iPtr->literalTable.numEntries * sizeof(LiteralEntry)),
8301
8341
(unsigned long) (iPtr->literalTable.numEntries * sizeof(Tcl_Obj)),
8302
8342
statsPtr->currentLitStringBytes);
8303
fprintf(stdout, " Bytes if no sharing %.6g = objects %.6g + strings %.6g\n",
8343
Tcl_AppendPrintfToObj(objPtr, " Bytes if no sharing %.6g = objects %.6g + strings %.6g\n",
8304
8344
(objBytesIfUnshared + strBytesIfUnshared),
8305
8345
objBytesIfUnshared, strBytesIfUnshared);
8306
fprintf(stdout, " String sharing savings %.6g = unshared %.6g - shared %.6g\n",
8346
Tcl_AppendPrintfToObj(objPtr, " String sharing savings %.6g = unshared %.6g - shared %.6g\n",
8307
8347
(strBytesIfUnshared - statsPtr->currentLitStringBytes),
8308
8348
strBytesIfUnshared, statsPtr->currentLitStringBytes);
8309
fprintf(stdout, " Literal mgmt overhead %ld (%0.1f%% of bytes with sharing)\n",
8349
Tcl_AppendPrintfToObj(objPtr, " Literal mgmt overhead %ld (%0.1f%% of bytes with sharing)\n",
8310
8350
literalMgmtBytes,
8311
8351
Percent(literalMgmtBytes, currentLiteralBytes));
8312
fprintf(stdout, " table %lu + buckets %lu + entries %lu\n",
8352
Tcl_AppendPrintfToObj(objPtr, " table %lu + buckets %lu + entries %lu\n",
8313
8353
(unsigned long) sizeof(LiteralTable),
8314
8354
(unsigned long) (iPtr->literalTable.numBuckets * sizeof(LiteralEntry *)),
8315
8355
(unsigned long) (iPtr->literalTable.numEntries * sizeof(LiteralEntry)));
8318
8358
* Breakdown of current ByteCode space requirements.
8321
fprintf(stdout, "\nBreakdown of current ByteCode requirements:\n");
8322
fprintf(stdout, " Bytes Pct of Avg per\n");
8323
fprintf(stdout, " total ByteCode\n");
8324
fprintf(stdout, "Total %12.6g 100.00%% %8.1f\n",
8361
Tcl_AppendPrintfToObj(objPtr, "\nBreakdown of current ByteCode requirements:\n");
8362
Tcl_AppendPrintfToObj(objPtr, " Bytes Pct of Avg per\n");
8363
Tcl_AppendPrintfToObj(objPtr, " total ByteCode\n");
8364
Tcl_AppendPrintfToObj(objPtr, "Total %12.6g 100.00%% %8.1f\n",
8325
8365
statsPtr->currentByteCodeBytes,
8326
8366
statsPtr->currentByteCodeBytes / numCurrentByteCodes);
8327
fprintf(stdout, "Header %12.6g %8.1f%% %8.1f\n",
8367
Tcl_AppendPrintfToObj(objPtr, "Header %12.6g %8.1f%% %8.1f\n",
8328
8368
currentHeaderBytes,
8329
8369
Percent(currentHeaderBytes, statsPtr->currentByteCodeBytes),
8330
8370
currentHeaderBytes / numCurrentByteCodes);
8331
fprintf(stdout, "Instructions %12.6g %8.1f%% %8.1f\n",
8371
Tcl_AppendPrintfToObj(objPtr, "Instructions %12.6g %8.1f%% %8.1f\n",
8332
8372
statsPtr->currentInstBytes,
8333
8373
Percent(statsPtr->currentInstBytes,statsPtr->currentByteCodeBytes),
8334
8374
statsPtr->currentInstBytes / numCurrentByteCodes);
8335
fprintf(stdout, "Literal ptr array %12.6g %8.1f%% %8.1f\n",
8375
Tcl_AppendPrintfToObj(objPtr, "Literal ptr array %12.6g %8.1f%% %8.1f\n",
8336
8376
statsPtr->currentLitBytes,
8337
8377
Percent(statsPtr->currentLitBytes,statsPtr->currentByteCodeBytes),
8338
8378
statsPtr->currentLitBytes / numCurrentByteCodes);
8339
fprintf(stdout, "Exception table %12.6g %8.1f%% %8.1f\n",
8379
Tcl_AppendPrintfToObj(objPtr, "Exception table %12.6g %8.1f%% %8.1f\n",
8340
8380
statsPtr->currentExceptBytes,
8341
8381
Percent(statsPtr->currentExceptBytes,statsPtr->currentByteCodeBytes),
8342
8382
statsPtr->currentExceptBytes / numCurrentByteCodes);
8343
fprintf(stdout, "Auxiliary data %12.6g %8.1f%% %8.1f\n",
8383
Tcl_AppendPrintfToObj(objPtr, "Auxiliary data %12.6g %8.1f%% %8.1f\n",
8344
8384
statsPtr->currentAuxBytes,
8345
8385
Percent(statsPtr->currentAuxBytes,statsPtr->currentByteCodeBytes),
8346
8386
statsPtr->currentAuxBytes / numCurrentByteCodes);
8347
fprintf(stdout, "Command map %12.6g %8.1f%% %8.1f\n",
8387
Tcl_AppendPrintfToObj(objPtr, "Command map %12.6g %8.1f%% %8.1f\n",
8348
8388
statsPtr->currentCmdMapBytes,
8349
8389
Percent(statsPtr->currentCmdMapBytes,statsPtr->currentByteCodeBytes),
8350
8390
statsPtr->currentCmdMapBytes / numCurrentByteCodes);
8452
8492
* Instruction counts.
8455
fprintf(stdout, "\nInstruction counts:\n");
8495
Tcl_AppendPrintfToObj(objPtr, "\nInstruction counts:\n");
8456
8496
for (i = 0; i <= LAST_INST_OPCODE; i++) {
8457
if (statsPtr->instructionCount[i] == 0) {
8458
fprintf(stdout, "%20s %8ld %6.1f%%\n",
8459
tclInstructionTable[i].name,
8460
statsPtr->instructionCount[i],
8497
Tcl_AppendPrintfToObj(objPtr, "%20s %8ld ",
8498
tclInstructionTable[i].name, statsPtr->instructionCount[i]);
8499
if (statsPtr->instructionCount[i]) {
8500
Tcl_AppendPrintfToObj(objPtr, "%6.1f%%\n",
8461
8501
Percent(statsPtr->instructionCount[i], numInstructions));
8465
fprintf(stdout, "\nInstructions NEVER executed:\n");
8466
for (i = 0; i <= LAST_INST_OPCODE; i++) {
8467
if (statsPtr->instructionCount[i] == 0) {
8468
fprintf(stdout, "%20s\n", tclInstructionTable[i].name);
8503
Tcl_AppendPrintfToObj(objPtr, "0\n");
8472
8507
#ifdef TCL_MEM_DEBUG
8473
fprintf(stdout, "\nHeap Statistics:\n");
8474
TclDumpMemoryInfo(stdout);
8508
Tcl_AppendPrintfToObj(objPtr, "\nHeap Statistics:\n");
8509
TclDumpMemoryInfo((ClientData) objPtr, 1);
8476
fprintf(stdout, "\n----------------------------------------------------------------\n");
8511
Tcl_AppendPrintfToObj(objPtr, "\n----------------------------------------------------------------\n");
8514
Tcl_SetObjResult(interp, objPtr);
8516
Tcl_Channel outChan;
8517
char *str = Tcl_GetStringFromObj(objv[1], &length);
8520
if (strcmp(str, "stdout") == 0) {
8521
outChan = Tcl_GetStdChannel(TCL_STDOUT);
8522
} else if (strcmp(str, "stderr") == 0) {
8523
outChan = Tcl_GetStdChannel(TCL_STDERR);
8525
outChan = Tcl_OpenFileChannel(NULL, str, "w", 0664);
8528
outChan = Tcl_GetStdChannel(TCL_STDOUT);
8530
if (outChan != NULL) {
8531
Tcl_WriteObj(outChan, objPtr);
8534
Tcl_DecrRefCount(objPtr);
8479
8537
#endif /* TCL_COMPILE_STATS */