From b2df30e5adb45bbbbdd44e958348149397eaa2d0 Mon Sep 17 00:00:00 2001 From: Miguel Sofer Date: Thu, 13 Jun 2002 19:47:57 +0000 Subject: consolidated opcodes in the bytecode engine, eliminating duplicated code. Added the new (but pre-existent in tcl.h) possible flag bit TCL_TRACE_READS to Tcl_(Obj)?SetVar.* --- ChangeLog | 15 ++ generic/tclExecute.c | 674 +++++++++++++++------------------------------------ generic/tclVar.c | 30 ++- 3 files changed, 232 insertions(+), 487 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8b96be7..d3aa4cc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2002-06-13 Miguel Sofer + + * generic/tclExecute.c (TclExecuteByteCode): consolidated variable + handling opcodes, replaced redundant code with some 'goto'. All + store/append/lappend opcodes on the same data type now share the + main code; same with incr opcodes. + * generic/tclVar.c: added the bit TCL_TRACE_READS to the possible + flags to Tcl_SetVar2Ex - it causes read traces to be fired prior + to setting the variable. This is used in the core for [lappend]. + + ***NOTE*** the usage of TCL_TRACE_READS in Tcl_(Obj)?GetVar.* is + not documented; there, it causes the call to create the variable + if it does not exist. The new usage in Tcl_(Obj)?SetVar.* remains + undocumented too ... + 2002-06-13 Vince Darley * tests/fCmd.test: diff --git a/generic/tclExecute.c b/generic/tclExecute.c index cd92324..13b4bfd 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclExecute.c,v 1.61 2002/06/11 12:38:22 msofer Exp $ + * RCS: @(#) $Id: tclExecute.c,v 1.62 2002/06/13 19:47:58 msofer Exp $ */ #include "tclInt.h" @@ -1001,6 +1001,7 @@ TclExecuteByteCode(interp, codePtr) * instructions and processCatch to * process break, continue, and errors. */ int result = TCL_OK; /* Return code returned after execution. */ + int storeFlags; #ifdef TCL_COMPILE_DEBUG int traceInstructions = (tclTraceExec == 3); #endif @@ -1507,21 +1508,42 @@ TclExecuteByteCode(interp, codePtr) TRACE_WITH_OBJ(("%u => ", opnd), valuePtr); ADJUST_PC(5); + case INST_LOAD_ARRAY_STK: + elemPtr = POP_OBJECT(); + goto doLoadStk; + case INST_LOAD_STK: case INST_LOAD_SCALAR_STK: + elemPtr = NULL; + + doLoadStk: objPtr = POP_OBJECT(); /* scalar / variable name */ DECACHE_STACK_INFO(); - valuePtr = Tcl_ObjGetVar2(interp, objPtr, NULL, TCL_LEAVE_ERR_MSG); + valuePtr = Tcl_ObjGetVar2(interp, objPtr, elemPtr, TCL_LEAVE_ERR_MSG); CACHE_STACK_INFO(); if (valuePtr == NULL) { - TRACE_WITH_OBJ(("\"%.30s\" => ERROR: ", O2S(objPtr)), - Tcl_GetObjResult(interp)); + if (elemPtr != NULL) { + TRACE_WITH_OBJ(("\"%.30s(%.30s)\" => ERROR: ", + O2S(objPtr), O2S(elemPtr)), + Tcl_GetObjResult(interp)); + TclDecrRefCount(elemPtr); + + } else { + TRACE_WITH_OBJ(("\"%.30s\" => ERROR: ", O2S(objPtr)), + Tcl_GetObjResult(interp)); + } TclDecrRefCount(objPtr); result = TCL_ERROR; goto checkForCatch; } PUSH_OBJECT(valuePtr); - TRACE_WITH_OBJ(("\"%.30s\" => ", O2S(objPtr)), valuePtr); + if (elemPtr != NULL) { + TRACE_WITH_OBJ(("\"%.30s(%.30s)\" => ", + O2S(objPtr), O2S(elemPtr)), valuePtr); + TclDecrRefCount(elemPtr); + } else { + TRACE_WITH_OBJ(("\"%.30s\" => ", O2S(objPtr)), valuePtr); + } TclDecrRefCount(objPtr); ADJUST_PC(1); @@ -1554,158 +1576,46 @@ TclExecuteByteCode(interp, codePtr) TclDecrRefCount(elemPtr); ADJUST_PC(pcAdjustment); - case INST_LOAD_ARRAY_STK: - elemPtr = POP_OBJECT(); - objPtr = POP_OBJECT(); /* array name */ - DECACHE_STACK_INFO(); - valuePtr = Tcl_ObjGetVar2(interp, objPtr, elemPtr, - TCL_LEAVE_ERR_MSG); - CACHE_STACK_INFO(); - if (valuePtr == NULL) { - TRACE_WITH_OBJ(("\"%.30s(%.30s)\" => ERROR: ", - O2S(objPtr), O2S(elemPtr)), - Tcl_GetObjResult(interp)); - TclDecrRefCount(objPtr); - TclDecrRefCount(elemPtr); - result = TCL_ERROR; - goto checkForCatch; - } - PUSH_OBJECT(valuePtr); - TRACE_WITH_OBJ(("\"%.30s(%.30s)\" => ", - O2S(objPtr), O2S(elemPtr)), valuePtr); - TclDecrRefCount(objPtr); - TclDecrRefCount(elemPtr); - ADJUST_PC(1); - - case INST_STORE_SCALAR4: + case INST_LAPPEND_SCALAR4: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; + storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_TRACE_READS); goto doStoreScalar; - case INST_STORE_SCALAR1: + case INST_LAPPEND_SCALAR1: opnd = TclGetUInt1AtPtr(pc+1); - pcAdjustment = 2; - - doStoreScalar: - valuePtr = POP_OBJECT(); - DECACHE_STACK_INFO(); - value2Ptr = TclSetIndexedScalar(interp, opnd, valuePtr, - TCL_LEAVE_ERR_MSG); - CACHE_STACK_INFO(); - if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("%u <- \"%.30s\" => ERROR: ", - opnd, O2S(valuePtr)), Tcl_GetObjResult(interp)); - TclDecrRefCount(valuePtr); - result = TCL_ERROR; - goto checkForCatch; - } - PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("%u <- \"%.30s\" => ", - opnd, O2S(valuePtr)), value2Ptr); - TclDecrRefCount(valuePtr); - ADJUST_PC(pcAdjustment); - - case INST_STORE_STK: - case INST_STORE_SCALAR_STK: - valuePtr = POP_OBJECT(); - objPtr = POP_OBJECT(); /* scalar / variable name */ - DECACHE_STACK_INFO(); - value2Ptr = Tcl_ObjSetVar2(interp, objPtr, NULL, valuePtr, - TCL_LEAVE_ERR_MSG); - CACHE_STACK_INFO(); - if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("\"%.30s\" <- \"%.30s\" => ERROR: ", - O2S(objPtr), O2S(valuePtr)), - Tcl_GetObjResult(interp)); - TclDecrRefCount(objPtr); - TclDecrRefCount(valuePtr); - result = TCL_ERROR; - goto checkForCatch; - } - PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("\"%.30s\" <- \"%.30s\" => ", - O2S(objPtr), O2S(valuePtr)), value2Ptr); - TclDecrRefCount(objPtr); - TclDecrRefCount(valuePtr); - ADJUST_PC(1); + pcAdjustment = 2; + storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_TRACE_READS); + goto doStoreScalar; - case INST_STORE_ARRAY4: + case INST_APPEND_SCALAR4: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; - goto doStoreArray; + storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE); + goto doStoreScalar; - case INST_STORE_ARRAY1: + case INST_APPEND_SCALAR1: opnd = TclGetUInt1AtPtr(pc+1); - pcAdjustment = 2; - - doStoreArray: - valuePtr = POP_OBJECT(); - elemPtr = POP_OBJECT(); - DECACHE_STACK_INFO(); - value2Ptr = TclSetElementOfIndexedArray(interp, opnd, - elemPtr, valuePtr, TCL_LEAVE_ERR_MSG); - CACHE_STACK_INFO(); - if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("%u \"%.30s\" <- \"%.30s\" => ERROR: ", - opnd, O2S(elemPtr), O2S(valuePtr)), - Tcl_GetObjResult(interp)); - TclDecrRefCount(elemPtr); - TclDecrRefCount(valuePtr); - result = TCL_ERROR; - goto checkForCatch; - } - PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("%u \"%.30s\" <- \"%.30s\" => ", - opnd, O2S(elemPtr), O2S(valuePtr)), value2Ptr); - TclDecrRefCount(elemPtr); - TclDecrRefCount(valuePtr); - ADJUST_PC(pcAdjustment); - - case INST_STORE_ARRAY_STK: - valuePtr = POP_OBJECT(); - elemPtr = POP_OBJECT(); - objPtr = POP_OBJECT(); /* array name */ - DECACHE_STACK_INFO(); - value2Ptr = Tcl_ObjSetVar2(interp, objPtr, elemPtr, valuePtr, - TCL_LEAVE_ERR_MSG); - CACHE_STACK_INFO(); - if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("\"%.30s(%.30s)\" <- \"%.30s\" => ERROR: ", - O2S(objPtr), O2S(elemPtr), O2S(valuePtr)), - Tcl_GetObjResult(interp)); - TclDecrRefCount(objPtr); - TclDecrRefCount(elemPtr); - TclDecrRefCount(valuePtr); - result = TCL_ERROR; - goto checkForCatch; - } - PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("\"%.30s(%.30s)\" <- \"%.30s\" => ", - O2S(objPtr), O2S(elemPtr), O2S(valuePtr)), - value2Ptr); - TclDecrRefCount(objPtr); - TclDecrRefCount(elemPtr); - TclDecrRefCount(valuePtr); - ADJUST_PC(1); - - /* - * START APPEND INSTRUCTIONS - */ + pcAdjustment = 2; + storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE); + goto doStoreScalar; - case INST_APPEND_SCALAR4: + case INST_STORE_SCALAR4: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; - goto doAppendScalar; + storeFlags = TCL_LEAVE_ERR_MSG; + goto doStoreScalar; - case INST_APPEND_SCALAR1: + case INST_STORE_SCALAR1: opnd = TclGetUInt1AtPtr(pc+1); pcAdjustment = 2; + storeFlags = TCL_LEAVE_ERR_MSG; - doAppendScalar: + doStoreScalar: valuePtr = POP_OBJECT(); DECACHE_STACK_INFO(); value2Ptr = TclSetIndexedScalar(interp, opnd, valuePtr, - TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE); + storeFlags); CACHE_STACK_INFO(); if (value2Ptr == NULL) { TRACE_WITH_OBJ(("%u <- \"%.30s\" => ERROR: ", @@ -1720,29 +1630,57 @@ TclExecuteByteCode(interp, codePtr) TclDecrRefCount(valuePtr); ADJUST_PC(pcAdjustment); + case INST_LAPPEND_STK: + valuePtr = POP_OBJECT(); /* value to append */ + elemPtr = NULL; + storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_TRACE_READS); + goto doStoreStk; + + case INST_LAPPEND_ARRAY_STK: + valuePtr = POP_OBJECT(); /* value to append */ + elemPtr = POP_OBJECT(); + storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_TRACE_READS); + goto doStoreStk; + case INST_APPEND_STK: + valuePtr = POP_OBJECT(); /* value to append */ + elemPtr = NULL; + storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE); + goto doStoreStk; + case INST_APPEND_ARRAY_STK: valuePtr = POP_OBJECT(); /* value to append */ - if (*pc == INST_APPEND_ARRAY_STK) { - elemPtr = POP_OBJECT(); - } else { - elemPtr = NULL; - } - objPtr = POP_OBJECT(); /* scalar name */ + elemPtr = POP_OBJECT(); + storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE); + goto doStoreStk; + + case INST_STORE_ARRAY_STK: + valuePtr = POP_OBJECT(); + elemPtr = POP_OBJECT(); + storeFlags = TCL_LEAVE_ERR_MSG; + goto doStoreStk; + case INST_STORE_STK: + case INST_STORE_SCALAR_STK: + valuePtr = POP_OBJECT(); + elemPtr = NULL; + storeFlags = TCL_LEAVE_ERR_MSG; + + doStoreStk: + objPtr = POP_OBJECT(); /* scalar or array variable name */ DECACHE_STACK_INFO(); value2Ptr = Tcl_ObjSetVar2(interp, objPtr, elemPtr, valuePtr, - TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE); + storeFlags); CACHE_STACK_INFO(); if (value2Ptr == NULL) { - if (elemPtr) { - TRACE_WITH_OBJ(("\"%.30s(%.30s)\" <-+ \"%.30s\" => ERROR: ", + if (elemPtr != NULL) { + TRACE_WITH_OBJ(("\"%.30s(%.30s)\" <- \"%.30s\" => ERROR: ", O2S(objPtr), O2S(elemPtr), O2S(valuePtr)), Tcl_GetObjResult(interp)); TclDecrRefCount(elemPtr); } else { - TRACE_WITH_OBJ(("\"%.30s\" <-+ \"%.30s\" => ERROR: ", - O2S(objPtr), O2S(valuePtr)), + TRACE_WITH_OBJ(("\"%.30s\" <- \"%.30s\" => ERROR: ", + O2S(objPtr), O2S(valuePtr)), Tcl_GetObjResult(interp)); } TclDecrRefCount(objPtr); @@ -1751,37 +1689,63 @@ TclExecuteByteCode(interp, codePtr) goto checkForCatch; } PUSH_OBJECT(value2Ptr); - if (elemPtr) { - TRACE_WITH_OBJ(("\"%.30s(%.30s)\" <-+ \"%.30s\" => ", - O2S(objPtr), O2S(elemPtr), O2S(valuePtr)), - value2Ptr); + if (elemPtr != NULL) { + TRACE_WITH_OBJ(("\"%.30s(%.30s)\" <- \"%.30s\" => ", + O2S(objPtr), O2S(elemPtr), O2S(valuePtr)), + value2Ptr); TclDecrRefCount(elemPtr); } else { - TRACE_WITH_OBJ(("\"%.30s\" <-+ \"%.30s\" => ", - O2S(objPtr), O2S(valuePtr)), value2Ptr); + TRACE_WITH_OBJ(("\"%.30s\" <- \"%.30s\" => ", + O2S(objPtr), O2S(valuePtr)), value2Ptr); } TclDecrRefCount(objPtr); TclDecrRefCount(valuePtr); ADJUST_PC(1); + case INST_LAPPEND_ARRAY4: + opnd = TclGetUInt4AtPtr(pc+1); + pcAdjustment = 5; + storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_TRACE_READS); + goto doStoreArray; + + case INST_LAPPEND_ARRAY1: + opnd = TclGetUInt1AtPtr(pc+1); + pcAdjustment = 2; + storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_TRACE_READS); + goto doStoreArray; + case INST_APPEND_ARRAY4: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; - goto doAppendArray; + storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE); + goto doStoreArray; case INST_APPEND_ARRAY1: opnd = TclGetUInt1AtPtr(pc+1); pcAdjustment = 2; + storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE); + goto doStoreArray; - doAppendArray: + case INST_STORE_ARRAY4: + opnd = TclGetUInt4AtPtr(pc+1); + pcAdjustment = 5; + storeFlags = TCL_LEAVE_ERR_MSG; + goto doStoreArray; + + case INST_STORE_ARRAY1: + opnd = TclGetUInt1AtPtr(pc+1); + pcAdjustment = 2; + storeFlags = TCL_LEAVE_ERR_MSG; + + doStoreArray: valuePtr = POP_OBJECT(); elemPtr = POP_OBJECT(); DECACHE_STACK_INFO(); value2Ptr = TclSetElementOfIndexedArray(interp, opnd, - elemPtr, valuePtr, TCL_LEAVE_ERR_MSG|TCL_APPEND_VALUE); + elemPtr, valuePtr, storeFlags); CACHE_STACK_INFO(); if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("%u \"%.30s\" <-+ \"%.30s\" => ERROR: ", + TRACE_WITH_OBJ(("%u \"%.30s\" <- \"%.30s\" => ERROR: ", opnd, O2S(elemPtr), O2S(valuePtr)), Tcl_GetObjResult(interp)); TclDecrRefCount(elemPtr); @@ -1790,16 +1754,12 @@ TclExecuteByteCode(interp, codePtr) goto checkForCatch; } PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("%u \"%.30s\" <-+ \"%.30s\" => ", + TRACE_WITH_OBJ(("%u \"%.30s\" <- \"%.30s\" => ", opnd, O2S(elemPtr), O2S(valuePtr)), value2Ptr); TclDecrRefCount(elemPtr); TclDecrRefCount(valuePtr); ADJUST_PC(pcAdjustment); - /* - * END APPEND INSTRUCTIONS - */ - case INST_LIST: /* * Pop the opnd (objc) top stack elements into a new list obj @@ -1816,172 +1776,6 @@ TclExecuteByteCode(interp, codePtr) TRACE_WITH_OBJ(("%u => ", opnd), valuePtr); ADJUST_PC(5); - /* - * START LAPPEND INSTRUCTIONS - */ - - case INST_LAPPEND_SCALAR4: - opnd = TclGetUInt4AtPtr(pc+1); - pcAdjustment = 5; - goto doLappendScalar; - - case INST_LAPPEND_SCALAR1: - opnd = TclGetUInt1AtPtr(pc+1); - pcAdjustment = 2; - - doLappendScalar: - valuePtr = POP_OBJECT(); - DECACHE_STACK_INFO(); - value2Ptr = TclSetIndexedScalar(interp, opnd, valuePtr, - TCL_LEAVE_ERR_MSG|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); - CACHE_STACK_INFO(); - if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("%u <- \"%.30s\" => ERROR: ", - opnd, O2S(valuePtr)), Tcl_GetObjResult(interp)); - TclDecrRefCount(valuePtr); - result = TCL_ERROR; - goto checkForCatch; - } - PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("%u <- \"%.30s\" => ", - opnd, O2S(valuePtr)), value2Ptr); - TclDecrRefCount(valuePtr); - ADJUST_PC(pcAdjustment); - - case INST_LAPPEND_STK: - case INST_LAPPEND_ARRAY_STK: - { - /* - * This compile function for this should be refactored - * to make better use of existing LOAD/STORE instructions. - */ - Tcl_Obj *newValuePtr; - int createdNewObj = 0; - - value2Ptr = POP_OBJECT(); /* value to append */ - if (*pc == INST_LAPPEND_ARRAY_STK) { - elemPtr = POP_OBJECT(); - } else { - elemPtr = NULL; - } - objPtr = POP_OBJECT(); /* scalar name */ - - DECACHE_STACK_INFO(); - /* - * Currently value of the list. - * Use the TCL_TRACE_READS flag to ensure that if we have an - * array with no elements set yet, but with a read trace on it, - * we will create the variable and get read traces triggered. - */ - valuePtr = Tcl_ObjGetVar2(interp, objPtr, elemPtr, - TCL_TRACE_READS); - CACHE_STACK_INFO(); - if (valuePtr == NULL) { - TclNewObj(valuePtr); - createdNewObj = 1; - } else if (Tcl_IsShared(valuePtr)) { - valuePtr = Tcl_DuplicateObj(valuePtr); - createdNewObj = 1; - } - - DECACHE_STACK_INFO(); - result = Tcl_ListObjAppendElement(interp, valuePtr, value2Ptr); - CACHE_STACK_INFO(); - if (result != TCL_OK) { - if (elemPtr) { - TRACE_WITH_OBJ(("\"%.30s(%.30s)\" <- \"%.30s\" => ERROR: ", - O2S(objPtr), O2S(elemPtr), O2S(valuePtr)), - Tcl_GetObjResult(interp)); - TclDecrRefCount(elemPtr); - } else { - TRACE_WITH_OBJ(("\"%.30s\" <-+ \"%.30s\" => ERROR: ", - O2S(objPtr), O2S(value2Ptr)), - Tcl_GetObjResult(interp)); - } - TclDecrRefCount(objPtr); - TclDecrRefCount(value2Ptr); - if (createdNewObj) { - TclDecrRefCount(valuePtr); - } - result = TCL_ERROR; - goto checkForCatch; - } - - DECACHE_STACK_INFO(); - newValuePtr = Tcl_ObjSetVar2(interp, objPtr, elemPtr, valuePtr, - TCL_LEAVE_ERR_MSG); - CACHE_STACK_INFO(); - if (newValuePtr == NULL) { - if (elemPtr) { - TRACE_WITH_OBJ(("\"%.30s(%.30s)\" <- \"%.30s\" => ERROR: ", - O2S(objPtr), O2S(elemPtr), O2S(valuePtr)), - Tcl_GetObjResult(interp)); - TclDecrRefCount(elemPtr); - } else { - TRACE_WITH_OBJ(("\"%.30s\" <-+ \"%.30s\" => ERROR: ", - O2S(objPtr), O2S(value2Ptr)), - Tcl_GetObjResult(interp)); - } - TclDecrRefCount(objPtr); - TclDecrRefCount(value2Ptr); - if (createdNewObj) { - TclDecrRefCount(valuePtr); - } - result = TCL_ERROR; - goto checkForCatch; - } - PUSH_OBJECT(newValuePtr); - if (elemPtr) { - TRACE_WITH_OBJ(("\"%.30s(%.30s)\" <- \"%.30s\" => ", - O2S(objPtr), O2S(elemPtr), O2S(valuePtr)), - value2Ptr); - TclDecrRefCount(elemPtr); - } else { - TRACE_WITH_OBJ(("\"%.30s\" <-+ \"%.30s\" => ", - O2S(objPtr), O2S(valuePtr)), value2Ptr); - } - TclDecrRefCount(objPtr); - TclDecrRefCount(value2Ptr); - ADJUST_PC(1); - } - - case INST_LAPPEND_ARRAY4: - opnd = TclGetUInt4AtPtr(pc+1); - pcAdjustment = 5; - goto doLappendArray; - - case INST_LAPPEND_ARRAY1: - opnd = TclGetUInt1AtPtr(pc+1); - pcAdjustment = 2; - - doLappendArray: - valuePtr = POP_OBJECT(); - elemPtr = POP_OBJECT(); - DECACHE_STACK_INFO(); - value2Ptr = TclSetElementOfIndexedArray(interp, opnd, - elemPtr, valuePtr, - TCL_LEAVE_ERR_MSG|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); - CACHE_STACK_INFO(); - if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("%u \"%.30s\" <-+ \"%.30s\" => ERROR: ", - opnd, O2S(elemPtr), O2S(valuePtr)), - Tcl_GetObjResult(interp)); - TclDecrRefCount(elemPtr); - TclDecrRefCount(valuePtr); - result = TCL_ERROR; - goto checkForCatch; - } - PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("%u \"%.30s\" <-+ \"%.30s\" => ", - opnd, O2S(elemPtr), O2S(valuePtr)), value2Ptr); - TclDecrRefCount(elemPtr); - TclDecrRefCount(valuePtr); - ADJUST_PC(pcAdjustment); - - /* - * END (L)APPEND INSTRUCTIONS - */ - case INST_INCR_SCALAR1: opnd = TclGetUInt1AtPtr(pc+1); valuePtr = POP_OBJECT(); @@ -2001,25 +1795,39 @@ TclExecuteByteCode(interp, codePtr) } FORCE_LONG(valuePtr, i, w); } + TclDecrRefCount(valuePtr); + pcAdjustment = 2; + goto doIncrScalarImm; + + case INST_INCR_SCALAR1_IMM: + opnd = TclGetUInt1AtPtr(pc+1); + i = TclGetInt1AtPtr(pc+2); + pcAdjustment = 3; + + doIncrScalarImm: DECACHE_STACK_INFO(); value2Ptr = TclIncrIndexedScalar(interp, opnd, i); CACHE_STACK_INFO(); if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("%u (by %ld) => ERROR: ", opnd, i), + TRACE_WITH_OBJ(("%u %ld => ERROR: ", opnd, i), Tcl_GetObjResult(interp)); - TclDecrRefCount(valuePtr); result = TCL_ERROR; goto checkForCatch; } PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("%u (by %ld) => ", opnd, i), value2Ptr); - TclDecrRefCount(valuePtr); - ADJUST_PC(2); + TRACE_WITH_OBJ(("%u %ld => ", opnd, i), value2Ptr); + ADJUST_PC(pcAdjustment); + + case INST_INCR_ARRAY_STK: + elemPtr = POP_OBJECT(); + goto doIncrStkGetIncr; case INST_INCR_SCALAR_STK: case INST_INCR_STK: + elemPtr = NULL; + + doIncrStkGetIncr: valuePtr = POP_OBJECT(); - objPtr = POP_OBJECT(); /* scalar name */ if (valuePtr->typePtr == &tclIntType) { i = valuePtr->internalRep.longValue; #ifndef TCL_WIDE_INT_IS_LONG @@ -2029,38 +1837,74 @@ TclExecuteByteCode(interp, codePtr) } else { REQUIRE_WIDE_OR_INT(result, valuePtr, i, w); if (result != TCL_OK) { - TRACE_WITH_OBJ(("\"%.30s\" (by %s) => ERROR converting increment amount to int: ", - O2S(objPtr), O2S(valuePtr)), - Tcl_GetObjResult(interp)); + objPtr = POP_OBJECT(); /* scalar name */ + if (elemPtr != NULL) { + TRACE_WITH_OBJ(("\"%.30s(%.30s)\" (by %s) => ERROR converting increment amount to int: ", + O2S(objPtr), O2S(elemPtr), O2S(valuePtr)), + Tcl_GetObjResult(interp)); + TclDecrRefCount(elemPtr); + } else { + TRACE_WITH_OBJ(("\"%.30s\" (by %s) => ERROR converting increment amount to int: ", + O2S(objPtr), O2S(valuePtr)), + Tcl_GetObjResult(interp)); + } TclDecrRefCount(objPtr); TclDecrRefCount(valuePtr); goto checkForCatch; } FORCE_LONG(valuePtr, i, w); } + TclDecrRefCount(valuePtr); + pcAdjustment = 1; + goto doIncrStk; + + case INST_INCR_ARRAY_STK_IMM: + elemPtr = POP_OBJECT(); + goto doIncrStkImm; + + case INST_INCR_SCALAR_STK_IMM: + case INST_INCR_STK_IMM: + elemPtr = NULL; + + doIncrStkImm: + i = TclGetInt1AtPtr(pc+1); + pcAdjustment = 2; + + doIncrStk: + objPtr = POP_OBJECT(); /* variable name */ DECACHE_STACK_INFO(); - value2Ptr = TclIncrVar2(interp, objPtr, (Tcl_Obj *) NULL, i, + value2Ptr = TclIncrVar2(interp, objPtr, elemPtr, i, TCL_LEAVE_ERR_MSG); CACHE_STACK_INFO(); if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("\"%.30s\" (by %ld) => ERROR: ", - O2S(objPtr), i), Tcl_GetObjResult(interp)); - TclDecrRefCount(objPtr); - TclDecrRefCount(valuePtr); + if (elemPtr != NULL) { + TRACE_WITH_OBJ(("\"%.30s(%.30s)\" (by %ld) => ERROR: ", + O2S(objPtr), O2S(elemPtr), i), + Tcl_GetObjResult(interp)); + TclDecrRefCount(elemPtr); + } else { + TRACE_WITH_OBJ(("\"%.30s\" %ld => ERROR: ", + O2S(objPtr), i), Tcl_GetObjResult(interp)); + } result = TCL_ERROR; + TclDecrRefCount(objPtr); goto checkForCatch; } PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("\"%.30s\" (by %ld) => ", O2S(objPtr), i), - value2Ptr); + if (elemPtr != NULL) { + TRACE_WITH_OBJ(("\"%.30s(%.30s)\" (by %ld) => ", + O2S(objPtr), O2S(elemPtr), i), value2Ptr); + TclDecrRefCount(elemPtr); + } else { + TRACE_WITH_OBJ(("\"%.30s\" %ld => ", O2S(objPtr), i), + value2Ptr); + } TclDecrRefCount(objPtr); - TclDecrRefCount(valuePtr); - ADJUST_PC(1); + ADJUST_PC(pcAdjustment); case INST_INCR_ARRAY1: opnd = TclGetUInt1AtPtr(pc+1); valuePtr = POP_OBJECT(); - elemPtr = POP_OBJECT(); if (valuePtr->typePtr == &tclIntType) { i = valuePtr->internalRep.longValue; #ifndef TCL_WIDE_INT_IS_LONG @@ -2070,6 +1914,7 @@ TclExecuteByteCode(interp, codePtr) } else { REQUIRE_WIDE_OR_INT(result, valuePtr, i, w); if (result != TCL_OK) { + elemPtr = POP_OBJECT(); TRACE_WITH_OBJ(("%u \"%.30s\" (by %s) => ERROR converting increment amount to int: ", opnd, O2S(elemPtr), O2S(valuePtr)), Tcl_GetObjResult(interp)); @@ -2079,111 +1924,16 @@ TclExecuteByteCode(interp, codePtr) } FORCE_LONG(valuePtr, i, w); } - DECACHE_STACK_INFO(); - value2Ptr = TclIncrElementOfIndexedArray(interp, opnd, - elemPtr, i); - CACHE_STACK_INFO(); - if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("%u \"%.30s\" (by %ld) => ERROR: ", - opnd, O2S(elemPtr), i), - Tcl_GetObjResult(interp)); - TclDecrRefCount(elemPtr); - TclDecrRefCount(valuePtr); - result = TCL_ERROR; - goto checkForCatch; - } - PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("%u \"%.30s\" (by %ld) => ", - opnd, O2S(elemPtr), i), value2Ptr); - TclDecrRefCount(elemPtr); TclDecrRefCount(valuePtr); - ADJUST_PC(2); - - case INST_INCR_ARRAY_STK: - valuePtr = POP_OBJECT(); - elemPtr = POP_OBJECT(); - objPtr = POP_OBJECT(); /* array name */ - if (valuePtr->typePtr == &tclIntType) { - i = valuePtr->internalRep.longValue; -#ifndef TCL_WIDE_INT_IS_LONG - } else if (valuePtr->typePtr == &tclWideIntType) { - i = Tcl_WideAsLong(valuePtr->internalRep.wideValue); -#endif /* TCL_WIDE_INT_IS_LONG */ - } else { - REQUIRE_WIDE_OR_INT(result, valuePtr, i, w); - if (result != TCL_OK) { - TRACE_WITH_OBJ(("\"%.30s(%.30s)\" (by %s) => ERROR converting increment amount to int: ", - O2S(objPtr), O2S(elemPtr), O2S(valuePtr)), - Tcl_GetObjResult(interp)); - TclDecrRefCount(objPtr); - TclDecrRefCount(elemPtr); - TclDecrRefCount(valuePtr); - goto checkForCatch; - } - FORCE_LONG(valuePtr, i, w); - } - DECACHE_STACK_INFO(); - value2Ptr = TclIncrVar2(interp, objPtr, elemPtr, i, - TCL_LEAVE_ERR_MSG); - CACHE_STACK_INFO(); - if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("\"%.30s(%.30s)\" (by %ld) => ERROR: ", - O2S(objPtr), O2S(elemPtr), i), - Tcl_GetObjResult(interp)); - TclDecrRefCount(objPtr); - TclDecrRefCount(elemPtr); - TclDecrRefCount(valuePtr); - result = TCL_ERROR; - goto checkForCatch; - } - PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("\"%.30s(%.30s)\" (by %ld) => ", - O2S(objPtr), O2S(elemPtr), i), value2Ptr); - TclDecrRefCount(objPtr); - TclDecrRefCount(elemPtr); - TclDecrRefCount(valuePtr); - ADJUST_PC(1); - - case INST_INCR_SCALAR1_IMM: - opnd = TclGetUInt1AtPtr(pc+1); - i = TclGetInt1AtPtr(pc+2); - DECACHE_STACK_INFO(); - value2Ptr = TclIncrIndexedScalar(interp, opnd, i); - CACHE_STACK_INFO(); - if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("%u %ld => ERROR: ", opnd, i), - Tcl_GetObjResult(interp)); - result = TCL_ERROR; - goto checkForCatch; - } - PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("%u %ld => ", opnd, i), value2Ptr); - ADJUST_PC(3); - - case INST_INCR_SCALAR_STK_IMM: - case INST_INCR_STK_IMM: - objPtr = POP_OBJECT(); /* variable name */ - i = TclGetInt1AtPtr(pc+1); - DECACHE_STACK_INFO(); - value2Ptr = TclIncrVar2(interp, objPtr, (Tcl_Obj *) NULL, i, - TCL_LEAVE_ERR_MSG); - CACHE_STACK_INFO(); - if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("\"%.30s\" %ld => ERROR: ", - O2S(objPtr), i), Tcl_GetObjResult(interp)); - result = TCL_ERROR; - TclDecrRefCount(objPtr); - goto checkForCatch; - } - PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("\"%.30s\" %ld => ", O2S(objPtr), i), - value2Ptr); - TclDecrRefCount(objPtr); - ADJUST_PC(2); + pcAdjustment = 2; + goto doIncrArrayImm; case INST_INCR_ARRAY1_IMM: opnd = TclGetUInt1AtPtr(pc+1); i = TclGetInt1AtPtr(pc+2); + pcAdjustment = 3; + + doIncrArrayImm: elemPtr = POP_OBJECT(); DECACHE_STACK_INFO(); value2Ptr = TclIncrElementOfIndexedArray(interp, opnd, @@ -2201,32 +1951,8 @@ TclExecuteByteCode(interp, codePtr) TRACE_WITH_OBJ(("%u \"%.30s\" (by %ld) => ", opnd, O2S(elemPtr), i), value2Ptr); TclDecrRefCount(elemPtr); - ADJUST_PC(3); - - case INST_INCR_ARRAY_STK_IMM: - i = TclGetInt1AtPtr(pc+1); - elemPtr = POP_OBJECT(); - objPtr = POP_OBJECT(); /* array name */ - DECACHE_STACK_INFO(); - value2Ptr = TclIncrVar2(interp, objPtr, elemPtr, i, - TCL_LEAVE_ERR_MSG); - CACHE_STACK_INFO(); - if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("\"%.30s(%.30s)\" (by %ld) => ERROR: ", - O2S(objPtr), O2S(elemPtr), i), - Tcl_GetObjResult(interp)); - TclDecrRefCount(objPtr); - TclDecrRefCount(elemPtr); - result = TCL_ERROR; - goto checkForCatch; - } - PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("\"%.30s(%.30s)\" (by %ld) => ", - O2S(objPtr), O2S(elemPtr), i), value2Ptr); - TclDecrRefCount(objPtr); - TclDecrRefCount(elemPtr); - ADJUST_PC(2); - + ADJUST_PC(pcAdjustment); + /* * END INCR INSTRUCTIONS */ diff --git a/generic/tclVar.c b/generic/tclVar.c index 6857a9f..133b387 100644 --- a/generic/tclVar.c +++ b/generic/tclVar.c @@ -15,7 +15,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclVar.c,v 1.51 2002/03/29 00:02:42 dgp Exp $ + * RCS: @(#) $Id: tclVar.c,v 1.52 2002/06/13 19:47:58 msofer Exp $ */ #include "tclInt.h" @@ -1243,12 +1243,18 @@ Tcl_SetVar2Ex(interp, part1, part2, newValuePtr, flags) } /* - * At this point, if we were appending, we used to call read traces: we - * treated append as a read-modify-write. However, it seemed unlikely to - * us that a real program would be interested in such reads being done - * during a set operation. + * Invoke any read traces that have been set for the variable if it + * is requested; this is only done in the core when lappending. */ + if ((flags & TCL_TRACE_READS) && ((varPtr->tracePtr != NULL) + || ((arrayPtr != NULL) && (arrayPtr->tracePtr != NULL)))) { + if (TCL_ERROR == CallTraces(iPtr, arrayPtr, varPtr, part1, part2, + TCL_TRACE_READS, (flags & TCL_LEAVE_ERR_MSG))) { + return NULL; + } + } + /* * Set the variable's new value. If appending, append the new value to * the variable, either as a list element or as a string. Also, if @@ -1448,12 +1454,11 @@ TclSetIndexedScalar(interp, localIndex, newValuePtr, flags) } /* - * Invoke any read traces that have been set for the variable if we - * are appending, but only in the lappend case. + * Invoke any read traces that have been set for the variable if it + * is requested; this is only done in the core when lappending. */ - if ((flags & TCL_APPEND_VALUE) && (flags & TCL_LIST_ELEMENT) - && (varPtr->tracePtr != NULL)) { + if ((flags & TCL_TRACE_READS) && (varPtr->tracePtr != NULL)) { if (TCL_ERROR == CallTraces(iPtr, /*arrayPtr*/ NULL, varPtr, varName, NULL, TCL_TRACE_READS, (flags & TCL_LEAVE_ERR_MSG))) { return NULL; @@ -1749,12 +1754,11 @@ TclSetElementOfIndexedArray(interp, localIndex, elemPtr, newValuePtr, flags) } /* - * Invoke any read traces that have been set for the element variable if - * we are appending, but only in the lappend case. + * Invoke any read traces that have been set for the variable if it + * is requested; this is only done in the core when lappending. */ - if ((flags & TCL_APPEND_VALUE) && (flags & TCL_LIST_ELEMENT) - && ((varPtr->tracePtr != NULL) + if ((flags & TCL_TRACE_READS) && ((varPtr->tracePtr != NULL) || ((arrayPtr != NULL) && (arrayPtr->tracePtr != NULL)))) { if (TCL_ERROR == CallTraces(iPtr, arrayPtr, varPtr, arrayName, elem, TCL_TRACE_READS, (flags & TCL_LEAVE_ERR_MSG))) { -- cgit v0.12