📄 tclcompile.c
字号:
* None. * * Side effects: * Generates a panic. * *---------------------------------------------------------------------- */static voidUpdateStringOfByteCode(objPtr) register Tcl_Obj *objPtr; /* ByteCode object with string rep that * needs updating. */{ /* * This procedure is never invoked since the internal representation of * a bytecode object is never modified. */ panic("UpdateStringOfByteCode should never be called.");}/* *---------------------------------------------------------------------- * * TclInitCompileEnv -- * * Initializes a CompileEnv compilation environment structure for the * compilation of a string in an interpreter. * * Results: * None. * * Side effects: * The CompileEnv structure is initialized. * *---------------------------------------------------------------------- */voidTclInitCompileEnv(interp, envPtr, string) Tcl_Interp *interp; /* The interpreter for which a CompileEnv * structure is initialized. */ register CompileEnv *envPtr; /* Points to the CompileEnv structure to * initialize. */ char *string; /* The source string to be compiled. */{ Interp *iPtr = (Interp *) interp; envPtr->iPtr = iPtr; envPtr->source = string; envPtr->procPtr = iPtr->compiledProcPtr; envPtr->numCommands = 0; envPtr->excRangeDepth = 0; envPtr->maxExcRangeDepth = 0; envPtr->maxStackDepth = 0; Tcl_InitHashTable(&(envPtr->objTable), TCL_STRING_KEYS); envPtr->pushSimpleWords = 1; envPtr->wordIsSimple = 0; envPtr->numSimpleWordChars = 0; envPtr->exprIsJustVarRef = 0; envPtr->exprIsComparison = 0; envPtr->termOffset = 0; envPtr->codeStart = envPtr->staticCodeSpace; envPtr->codeNext = envPtr->codeStart; envPtr->codeEnd = (envPtr->codeStart + COMPILEENV_INIT_CODE_BYTES); envPtr->mallocedCodeArray = 0; envPtr->objArrayPtr = envPtr->staticObjArraySpace; envPtr->objArrayNext = 0; envPtr->objArrayEnd = COMPILEENV_INIT_NUM_OBJECTS; envPtr->mallocedObjArray = 0; envPtr->excRangeArrayPtr = envPtr->staticExcRangeArraySpace; envPtr->excRangeArrayNext = 0; envPtr->excRangeArrayEnd = COMPILEENV_INIT_EXCEPT_RANGES; envPtr->mallocedExcRangeArray = 0; envPtr->cmdMapPtr = envPtr->staticCmdMapSpace; envPtr->cmdMapEnd = COMPILEENV_INIT_CMD_MAP_SIZE; envPtr->mallocedCmdMap = 0; envPtr->auxDataArrayPtr = envPtr->staticAuxDataArraySpace; envPtr->auxDataArrayNext = 0; envPtr->auxDataArrayEnd = COMPILEENV_INIT_AUX_DATA_SIZE; envPtr->mallocedAuxDataArray = 0;}/* *---------------------------------------------------------------------- * * TclFreeCompileEnv -- * * Free the storage allocated in a CompileEnv compilation environment * structure. * * Results: * None. * * Side effects: * Allocated storage in the CompileEnv structure is freed. Note that * ref counts for Tcl objects in its object table are not decremented. * In addition, any storage referenced by any auxiliary data items * in the CompileEnv structure are not freed either. The expectation * is that when compilation is successful, "ownership" (i.e., the * pointers to) these objects and aux data items will just be handed * over to the corresponding ByteCode structure. * *---------------------------------------------------------------------- */voidTclFreeCompileEnv(envPtr) register CompileEnv *envPtr; /* Points to the CompileEnv structure. */{ Tcl_DeleteHashTable(&(envPtr->objTable)); if (envPtr->mallocedCodeArray) { ckfree((char *) envPtr->codeStart); } if (envPtr->mallocedObjArray) { ckfree((char *) envPtr->objArrayPtr); } if (envPtr->mallocedExcRangeArray) { ckfree((char *) envPtr->excRangeArrayPtr); } if (envPtr->mallocedCmdMap) { ckfree((char *) envPtr->cmdMapPtr); } if (envPtr->mallocedAuxDataArray) { ckfree((char *) envPtr->auxDataArrayPtr); }}/* *---------------------------------------------------------------------- * * TclInitByteCodeObj -- * * Create a ByteCode structure and initialize it from a CompileEnv * compilation environment structure. The ByteCode structure is * smaller and contains just that information needed to execute * the bytecode instructions resulting from compiling a Tcl script. * The resulting structure is placed in the specified object. * * Results: * A newly constructed ByteCode object is stored in the internal * representation of the objPtr. * * Side effects: * A single heap object is allocated to hold the new ByteCode structure * and its code, object, command location, and aux data arrays. Note * that "ownership" (i.e., the pointers to) the Tcl objects and aux * data items will be handed over to the new ByteCode structure from * the CompileEnv structure. * *---------------------------------------------------------------------- */voidTclInitByteCodeObj(objPtr, envPtr) Tcl_Obj *objPtr; /* Points object that should be * initialized, and whose string rep * contains the source code. */ register CompileEnv *envPtr; /* Points to the CompileEnv structure from * which to create a ByteCode structure. */{ register ByteCode *codePtr; size_t codeBytes, objArrayBytes, exceptArrayBytes, cmdLocBytes; size_t auxDataArrayBytes; register size_t size, objBytes, totalSize; register unsigned char *p; unsigned char *nextPtr; int srcLen = envPtr->termOffset; int numObjects, i; Namespace *namespacePtr;#ifdef TCL_COMPILE_STATS int srcLenLog2, sizeLog2;#endif /*TCL_COMPILE_STATS*/ codeBytes = (envPtr->codeNext - envPtr->codeStart); numObjects = envPtr->objArrayNext; objArrayBytes = (envPtr->objArrayNext * sizeof(Tcl_Obj *)); exceptArrayBytes = (envPtr->excRangeArrayNext * sizeof(ExceptionRange)); auxDataArrayBytes = (envPtr->auxDataArrayNext * sizeof(AuxData)); cmdLocBytes = GetCmdLocEncodingSize(envPtr); size = sizeof(ByteCode); size += TCL_ALIGN(codeBytes); /* align object array */ size += TCL_ALIGN(objArrayBytes); /* align exception range array */ size += TCL_ALIGN(exceptArrayBytes); /* align AuxData array */ size += auxDataArrayBytes; size += cmdLocBytes; /* * Compute the total number of bytes needed for this bytecode * including the storage for the Tcl objects in its object array. */ objBytes = (numObjects * sizeof(Tcl_Obj)); for (i = 0; i < numObjects; i++) { Tcl_Obj *litObjPtr = envPtr->objArrayPtr[i]; if (litObjPtr->bytes != NULL) { objBytes += litObjPtr->length; } } totalSize = (size + objBytes);#ifdef TCL_COMPILE_STATS tclNumCompilations++; tclTotalSourceBytes += (double) srcLen; tclTotalCodeBytes += (double) totalSize; tclTotalInstBytes += (double) codeBytes; tclTotalObjBytes += (double) objBytes; tclTotalExceptBytes += exceptArrayBytes; tclTotalAuxBytes += (double) auxDataArrayBytes; tclTotalCmdMapBytes += (double) cmdLocBytes; tclCurrentSourceBytes += (double) srcLen; tclCurrentCodeBytes += (double) totalSize; srcLenLog2 = TclLog2(srcLen); sizeLog2 = TclLog2((int) totalSize); if ((srcLenLog2 > 31) || (sizeLog2 > 31)) { panic("TclInitByteCodeObj: bad source or code sizes\n"); } tclSourceCount[srcLenLog2]++; tclByteCodeCount[sizeLog2]++;#endif /* TCL_COMPILE_STATS */ if (envPtr->iPtr->varFramePtr != NULL) { namespacePtr = envPtr->iPtr->varFramePtr->nsPtr; } else { namespacePtr = envPtr->iPtr->globalNsPtr; } p = (unsigned char *) ckalloc(size); codePtr = (ByteCode *) p; codePtr->iPtr = envPtr->iPtr; codePtr->compileEpoch = envPtr->iPtr->compileEpoch; codePtr->nsPtr = namespacePtr; codePtr->nsEpoch = namespacePtr->resolverEpoch; codePtr->refCount = 1; codePtr->flags = 0; codePtr->source = envPtr->source; codePtr->procPtr = envPtr->procPtr; codePtr->totalSize = totalSize; codePtr->numCommands = envPtr->numCommands; codePtr->numSrcChars = srcLen; codePtr->numCodeBytes = codeBytes; codePtr->numObjects = numObjects; codePtr->numExcRanges = envPtr->excRangeArrayNext; codePtr->numAuxDataItems = envPtr->auxDataArrayNext; codePtr->auxDataArrayPtr = NULL; codePtr->numCmdLocBytes = cmdLocBytes; codePtr->maxExcRangeDepth = envPtr->maxExcRangeDepth; codePtr->maxStackDepth = envPtr->maxStackDepth; p += sizeof(ByteCode); codePtr->codeStart = p; memcpy((VOID *) p, (VOID *) envPtr->codeStart, codeBytes); p += TCL_ALIGN(codeBytes); /* align object array */ codePtr->objArrayPtr = (Tcl_Obj **) p; memcpy((VOID *) p, (VOID *) envPtr->objArrayPtr, objArrayBytes); p += TCL_ALIGN(objArrayBytes); /* align exception range array */ if (exceptArrayBytes > 0) { codePtr->excRangeArrayPtr = (ExceptionRange *) p; memcpy((VOID *) p, (VOID *) envPtr->excRangeArrayPtr, exceptArrayBytes); } p += TCL_ALIGN(exceptArrayBytes); /* align AuxData array */ if (auxDataArrayBytes > 0) { codePtr->auxDataArrayPtr = (AuxData *) p; memcpy((VOID *) p, (VOID *) envPtr->auxDataArrayPtr, auxDataArrayBytes); } p += auxDataArrayBytes; nextPtr = EncodeCmdLocMap(envPtr, codePtr, (unsigned char *) p); if (((size_t)(nextPtr - p)) != cmdLocBytes) { panic("TclInitByteCodeObj: encoded cmd location bytes %d != expected size %d\n", (nextPtr - p), cmdLocBytes); } /* * Free the old internal rep then convert the object to a * bytecode object by making its internal rep point to the just * compiled ByteCode. */ if ((objPtr->typePtr != NULL) && (objPtr->typePtr->freeIntRepProc != NULL)) { objPtr->typePtr->freeIntRepProc(objPtr); } objPtr->internalRep.otherValuePtr = (VOID *) codePtr; objPtr->typePtr = &tclByteCodeType;}/* *---------------------------------------------------------------------- * * GetCmdLocEncodingSize -- * * Computes the total number of bytes needed to encode the command * location information for some compiled code. * * Results: * The byte count needed to encode the compiled location information. * * Side effects: * None. * *---------------------------------------------------------------------- */static intGetCmdLocEncodingSize(envPtr) CompileEnv *envPtr; /* Points to compilation environment * structure containing the CmdLocation * structure to encode. */{ register CmdLocation *mapPtr = envPtr->cmdMapPtr; int numCmds = envPtr->numCommands; int codeDelta, codeLen, srcDelta, srcLen; int codeDeltaNext, codeLengthNext, srcDeltaNext, srcLengthNext; /* The offsets in their respective byte * sequences where the next encoded offset * or length should go. */ int prevCodeOffset, prevSrcOffset, i; codeDeltaNext = codeLengthNext = srcDeltaNext = srcLengthNext = 0; prevCodeOffset = prevSrcOffset = 0; for (i = 0; i < numCmds; i++) { codeDelta = (mapPtr[i].codeOffset - prevCodeOffset); if (codeDelta < 0) { panic("GetCmdLocEncodingSize: bad code offset"); } else if (codeDelta <= 127) { codeDeltaNext++; } else { codeDeltaNext += 5; /* 1 byte for 0xFF, 4 for positive delta */ } prevCodeOffset = mapPtr[i].codeOffset; codeLen = mapPtr[i].numCodeBytes; if (codeLen < 0) { panic("GetCmdLocEncodingSize: bad code length"); } else if (codeLen <= 127) { codeLengthNext++; } else { codeLengthNext += 5; /* 1 byte for 0xFF, 4 for length */ } srcDelta = (mapPtr[i].srcOffset - prevSrcOffset); if ((-127 <= srcDelta) && (srcDelta <= 127)) { srcDeltaNext++; } else { srcDeltaNext += 5; /* 1 byte for 0xFF, 4 for delta */ } prevSrcOffset = mapPtr[i].srcOffset; srcLen = mapPtr[i].numSrcChars; if (srcLen < 0) { panic("GetCmdLocEncodingSize: bad source length"); } else if (srcLen <= 127) { srcLengthNext++; } else { srcLengthNext += 5; /* 1 byte for 0xFF, 4 for length */ } } return (codeDeltaNext + codeLengthNext + srcDeltaNext + srcLengthNext);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -