enum instructionIdx { IDX_objProc, IDX_asmEval, IDX_asmDuplicateObj, IDX_asmIncrInt, IDX_asmIncrObj, IDX_asmJump, IDX_asmJumpTrue, IDX_asmLeInt, IDX_asmLeIntObj, IDX_asmMethodDelegateDispatch, IDX_asmMethodDelegateDispatch11, IDX_asmMethodSelfCmdDispatch, IDX_asmMethodSelfDispatch, IDX_asmNoop, IDX_asmSelf, IDX_asmSetInt, IDX_asmSetObj, IDX_asmSetObjToResult, IDX_asmSetResult, IDX_asmSetResultInt, IDX_asmStoreResult, IDX_NULL }; /* *---------------------------------------------------------------------- * AsmExecute -- * * Define the execution engine for the code * *---------------------------------------------------------------------- */ int AsmExecute(ClientData cd, Tcl_Interp *interp, AsmCompiledProc *proc, int argc, Tcl_Obj *CONST argv[]) { int i, result = TCL_OK; AsmInstruction *ip; static void *instructionLabel[] = { &&INST_objProc, &&INST_asmEval, &&INST_asmDuplicateObj, &&INST_asmIncrInt, &&INST_asmIncrObj, &&INST_asmJump, &&INST_asmJumpTrue, &&INST_asmLeInt, &&INST_asmLeIntObj, &&INST_asmMethodDelegateDispatch, &&INST_asmMethodDelegateDispatch11, &&INST_asmMethodSelfCmdDispatch, &&INST_asmMethodSelfDispatch, &&INST_asmNoop, &&INST_asmSelf, &&INST_asmSetInt, &&INST_asmSetObj, &&INST_asmSetObjToResult, &&INST_asmSetResult, &&INST_asmSetResultInt, &&INST_asmStoreResult, &&INST_NULL }; /* * Place a copy of the actual argument into locals. */ for (i=1; i < argc; i++) { proc->locals[i-1] = argv[i]; } /* * Update all references to compiled arguments. */ for (i=0; i < proc->nrAsmArgReferences; i++) { AsmArgReference *arPtr = &proc->argReferences[i]; *(arPtr->objPtr) = proc->locals[arPtr->argNr]; } /* * Set the instruction pointer to the begin of the code. */ ip = proc->code; proc->status = 0; //fprintf(stderr, "AsmExecute jumps to %p\n", ip); goto *instructionLabel[ip->labelIdx]; INST_NULL: return result; EXEC_RESULT_CODE_HANDLER: if (likely(result == TCL_OK)) { ip++; goto *instructionLabel[ip->labelIdx]; } else { return result; } INST_objProc: result = (*ip->cmd)(ip->clientData, interp, ip->argc, ip->argv); goto EXEC_RESULT_CODE_HANDLER; INST_asmEval: result = Tcl_EvalObjv(interp, ip->argc, ip->argv, 0); goto EXEC_RESULT_CODE_HANDLER; ip++; goto *instructionLabel[ip->labelIdx]; INST_asmDuplicateObj: { int indexValue = PTR2INT(ip->argv[0]); //fprintf(stderr, "duplicateObj var[%d] = %s\n", indexValue, ObjStr(ip->argv[1])); if (proc->slots[indexValue]) { Tcl_DecrRefCount(proc->slots[indexValue]); } proc->slots[indexValue] = Tcl_DuplicateObj(ip->argv[1]); Tcl_IncrRefCount(proc->slots[indexValue]); proc->slotFlags[indexValue] |= ASM_SLOT_MUST_DECR; } ip++; goto *instructionLabel[ip->labelIdx]; INST_asmIncrInt: { int intValue, incrValue; //fprintf(stderr, "incrInt var[%d] incr var[%d]\n", PTR2INT(ip->argv[0]), PTR2INT(ip->argv[1])); intValue = PTR2INT(proc->slots[PTR2INT(ip->argv[0])]); incrValue = PTR2INT(proc->slots[PTR2INT(ip->argv[1])]); //fprintf(stderr, ".... intValue %d incr Value %d\n", intValue, incrValue); proc->slots[PTR2INT(ip->argv[0])] = INT2PTR(intValue + incrValue); //fprintf(stderr, ".... [%d] => %d\n", PTR2INT(ip->argv[0]), intValue + incrValue); } ip++; goto *instructionLabel[ip->labelIdx]; INST_asmIncrObj: { int intValue, incrValue; Tcl_Obj *intObj, *incrObj; //fprintf(stderr, "asmIncrScalar var[%d] incr var[%d], ", PTR2INT(ip->argv[0]), PTR2INT(ip->argv[1])); intObj = proc->slots[PTR2INT(ip->argv[0])]; incrObj = proc->slots[PTR2INT(ip->argv[1])]; if (likely(intObj->typePtr == Nsf_OT_intType)) { intValue = intObj->internalRep.longValue; } else { Tcl_GetIntFromObj(interp, intObj, &intValue); } if (likely(incrObj->typePtr == Nsf_OT_intType)) { incrValue = incrObj->internalRep.longValue; } else { Tcl_GetIntFromObj(interp, incrObj, &incrValue); } //fprintf(stderr, "%d + %d = %d,", intValue, incrValue, intValue + incrValue); Tcl_InvalidateStringRep(intObj); intObj->internalRep.longValue = (long)(intValue + incrValue); //fprintf(stderr, "updated %p var[%d] %p\n", intObj, PTR2INT(ip->argv[0]), proc->slots[PTR2INT(ip->argv[0])]); //Tcl_SetObjResult(interp, intObj); } ip++; goto *instructionLabel[ip->labelIdx]; INST_asmJump: //fprintf(stderr, "asmJump oc %d instructionIndex %d\n", ip->argc, PTR2INT(ip->argv[0])); NsfAsmJump(PTR2INT(ip->argv[0])); goto *instructionLabel[ip->labelIdx]; INST_asmJumpTrue: if (proc->status != 0) { //fprintf(stderr, "asmJumpTrue jump oc %d instructionIndex %d\n", ip->argc, PTR2INT(ip->argv[0])); NsfAsmJump(PTR2INT(ip->argv[0])); } else { //fprintf(stderr, "asmJumpTrue fall through\n"); NsfAsmJumpNext(); } goto *instructionLabel[ip->labelIdx]; INST_asmLeInt: { int value1, value2; value1 = PTR2INT(proc->slots[PTR2INT(ip->argv[0])]); value2 = PTR2INT(proc->slots[PTR2INT(ip->argv[1])]); proc->status = value1 <= value2; } ip++; goto *instructionLabel[ip->labelIdx]; INST_asmLeIntObj: { int value1, value2; Tcl_Obj *obj; //fprintf(stderr, "leIntObj oc %d op1 %p op2 %p\n", ip->argc, ip->argv[0], ip->argv[1]); // for the time being, we compare two int values obj = proc->slots[PTR2INT(ip->argv[0])]; if (likely(obj->typePtr == Nsf_OT_intType)) { value1 = obj->internalRep.longValue; } else { Tcl_GetIntFromObj(interp, obj, &value1); } obj = proc->slots[PTR2INT(ip->argv[1])]; if (likely(obj->typePtr == Nsf_OT_intType)) { value2 = obj->internalRep.longValue; } else { Tcl_GetIntFromObj(interp, obj, &value2); } //fprintf(stderr, "asmLeScalar oc %d op1 %d op2 %d => %d\n", ip->argc, value1, value2, value1 <= value2); proc->status = value1 <= value2; } ip++; goto *instructionLabel[ip->labelIdx]; INST_asmMethodDelegateDispatch: { Tcl_Command cmd = NULL; NsfObject *object; // obj and method are unresolved result = GetObjectFromObj(interp, ip->argv[0], &object); if (likely(ip->clientData != NULL)) { cmd = ip->clientData; } else { cmd = Tcl_GetCommandFromObj(interp, ip->argv[1]); } //fprintf(stderr, "cmd %p object %p\n", cmd, object); result = MethodDispatch(object, interp, ip->argc-1, ip->argv+1, cmd, object, NULL, ObjStr(ip->argv[1]), 0, 0); } goto EXEC_RESULT_CODE_HANDLER; ip++; goto *instructionLabel[ip->labelIdx]; INST_asmMethodDelegateDispatch11: // obj and method are resolved { AsmResolverInfo *resInfo = ip->clientData; result = MethodDispatch(resInfo->object, interp, ip->argc-1, ip->argv+1, resInfo->cmd, resInfo->object, NULL, ObjStr(ip->argv[1]), 0, 0); } goto EXEC_RESULT_CODE_HANDLER; ip++; goto *instructionLabel[ip->labelIdx]; INST_asmMethodSelfCmdDispatch: { AsmResolverInfo *resInfo = ip->clientData; assert(resInfo->cmd != NULL); result = Tcl_NRCallObjProc(interp, Tcl_Command_objProc(resInfo->cmd), resInfo->proc->currentObject, ip->argc, ip->argv); } goto EXEC_RESULT_CODE_HANDLER; ip++; goto *instructionLabel[ip->labelIdx]; INST_asmMethodSelfDispatch: { AsmResolverInfo *resInfo = ip->clientData; Tcl_Command cmd = (resInfo->cmd != NULL) ? resInfo->cmd : Tcl_GetCommandFromObj(interp, ip->argv[0]); result = MethodDispatch(resInfo->proc->currentObject, interp, ip->argc, ip->argv, cmd, resInfo->proc->currentObject, NULL, ObjStr(ip->argv[0]), 0, 0); } goto EXEC_RESULT_CODE_HANDLER; ip++; goto *instructionLabel[ip->labelIdx]; INST_asmNoop: ip++; goto *instructionLabel[ip->labelIdx]; INST_asmSelf: Tcl_SetObjResult(interp, proc->currentObject->cmdName); ip++; goto *instructionLabel[ip->labelIdx]; INST_asmSetInt: proc->slots[PTR2INT(ip->argv[0])] = ip->argv[1]; ip++; goto *instructionLabel[ip->labelIdx]; INST_asmSetObj: //fprintf(stderr, "setObj var[%d] = %s\n", PTR2INT(ip->argv[0]), ObjStr(ip->argv[1])); proc->slots[PTR2INT(ip->argv[0])] = ip->argv[1]; ip++; goto *instructionLabel[ip->labelIdx]; INST_asmSetObjToResult: //fprintf(stderr, "setObjToResult var[%d] = %s\n", PTR2INT(ip->argv[0]), ObjStr(ip->argv[1])); proc->slots[PTR2INT(ip->argv[0])] = Tcl_GetObjResult(interp); ip++; goto *instructionLabel[ip->labelIdx]; INST_asmSetResult: Tcl_SetObjResult(interp, proc->slots[PTR2INT(ip->argv[0])]); ip++; goto *instructionLabel[ip->labelIdx]; INST_asmSetResultInt: Tcl_SetObjResult(interp, Tcl_NewIntObj(PTR2INT(proc->slots[PTR2INT(ip->argv[0])]))); ip++; goto *instructionLabel[ip->labelIdx]; INST_asmStoreResult: ip->argv[0] = Tcl_GetObjResult(interp); Tcl_IncrRefCount(ip->argv[0]); ip++; goto *instructionLabel[ip->labelIdx]; }