void CColorEyeIDoc::debugByTxt(CString pathName) { std::vector<CString> vStr; CString str; str.IsEmpty(); vStr.clear(); str.Format("點位描述\tLv\tx\ty\tdu\tdv\tT\tDuv\tX\tY\tZ\t量測時間\n"); vStr.push_back(str); for (std::vector<Cartridge2>::iterator iter = m_docRNA.Begin(); iter != m_docRNA.End(); ++iter) { str.Format("%s\t%s\t%s\t\n", iter->GetDescrip(), iter->GetBullet().ShowData(), iter->GetBullet().GetLastTime()); vStr.push_back(str); } CStdioFile file; CFileException fx; pathName.Format("%s_debug.omd", pathName.Left(pathName.GetLength()-4)); if (!file.Open(pathName, CFile::modeCreate | CFile::modeWrite | CFile::typeText, &fx)) { TCHAR buf[255]; fx.GetErrorMessage(buf, 255); CString strPrompt(buf); AfxMessageBox(strPrompt); } else { if (!vStr.empty()) for (std::vector<CString>::iterator it = vStr.begin(); it != vStr.end(); ++it) file.WriteString(it->GetBuffer(0)); file.Close(); } }
TObject* SmalltalkVM::performPrimitive(uint8_t opcode, hptr<TProcess>& process, TVMExecutionContext& ec, bool& failed) { switch (opcode) { // FIXME opcodes 253-255 are not standard case 255: // Debug trap std::printf("Debug trap\n"); break; case 254: m_memoryManager->collectGarbage(); break; #if defined(LLVM) case primitive::LLVMsendMessage: { //252 TObjectArray* args = ec.stackPop<TObjectArray>(); TSymbol* selector = ec.stackPop<TSymbol>(); try { return sendMessage(ec.currentContext, selector, args, 0); } catch(TBlockReturn& blockReturn) { //When we catch blockReturn we change the current context to block.creatingContext. //The post processing code will change 'block.creatingContext' to the previous one // and the result of blockReturn will be injected on the stack ec.currentContext = blockReturn.targetContext; return blockReturn.value; } catch(TContext* errorContext) { //context is thrown by LLVM:throwError primitive //that means that it was not caught by LLVM:executeProcess function //so we have to stop execution of the current process and return returnError process->context = errorContext; failed = true; return globals.nilObject; } } break; case 247: { // Jit once: aBlock try { TBlock* const block = ec.stackPop<TBlock>(); return JITRuntime::Instance()->invokeBlock(block, ec.currentContext, true); } catch(TBlockReturn& blockReturn) { ec.currentContext = blockReturn.targetContext; return blockReturn.value; } catch(TContext* errorContext) { process->context = errorContext; failed = true; return globals.nilObject; } } #endif case 251: { // TODO Unicode support TString* prompt = ec.stackPop<TString>(); std::string strPrompt(reinterpret_cast<const char*>(prompt->getBytes()), prompt->getSize()); std::string input; bool userInsertedAnything = CompletionEngine::Instance()->readline(strPrompt, input); if ( userInsertedAnything ) { if ( !input.empty() ) CompletionEngine::Instance()->addHistory(input); TString* result = static_cast<TString*>( newBinaryObject(globals.stringClass, input.size()) ); std::memcpy(result->getBytes(), input.c_str(), input.size()); return result; } else return globals.nilObject; } break; #if defined(LLVM) case 250: // patchHotMethods JITRuntime::Instance()->patchHotMethods(); break; case 249: { // printMethod TMethod* method = ec.stackPop<TMethod>(); JITRuntime::Instance()->printMethod(method); } break; case 248: JITRuntime::Instance()->printStat(); break; #endif case primitive::startNewProcess: { // 6 TInteger ticks = ec.stackPop(); TProcess* newProcess = ec.stackPop<TProcess>(); // FIXME possible stack overflow due to recursive call TExecuteResult result = this->execute(newProcess, ticks); return TInteger(result); } break; case primitive::allocateObject: { // 7 // Taking object's size and class from the stack TObject* size = ec.stackPop(); TClass* klass = ec.stackPop<TClass>(); uint32_t fieldsCount = TInteger(size); // Instantinating the object. Each object has size and class fields return newOrdinaryObject(klass, sizeof(TObject) + fieldsCount * sizeof(TObject*)); } break; case primitive::blockInvoke: { // 8 TBlock* block = ec.stackPop<TBlock>(); uint32_t argumentLocation = block->argumentLocation; // Amount of arguments stored on the stack except the block itself uint32_t argCount = ec.instruction.getArgument() - 1; // Checking the passed temps size TObjectArray* blockTemps = block->temporaries; if (argCount > (blockTemps ? blockTemps->getSize() - argumentLocation : 0) ) { ec.stackTop -= (argCount + 1); // unrolling stack failed = true; break; } // Loading temporaries array for (uint32_t index = argCount - 1, count = argCount; count > 0; index--, count--) (*blockTemps)[argumentLocation + index] = ec.stackPop(); // Switching execution context to the invoking block block->previousContext = ec.currentContext->previousContext; ec.currentContext = static_cast<TContext*>(block); ec.stackTop = 0; // resetting stack // Block is bound to the method's bytecodes, so it's // first bytecode will not be zero but the value specified ec.bytePointer = block->blockBytePointer; return block; } break; case primitive::throwError: // 19 process->context = ec.currentContext; process->result = ec.returnedValue; break; case primitive::allocateByteArray: { // 20 TInteger dataSize = ec.stackPop(); TClass* klass = ec.stackPop<TClass>(); return newBinaryObject(klass, dataSize); } break; case primitive::arrayAt: // 24 case primitive::arrayAtPut: { // 5 TObject* indexObject = ec.stackPop(); TObjectArray* array = ec.stackPop<TObjectArray>(); TObject* valueObject = 0; // If the method is Array:at:put then pop a value from the stack if (opcode == primitive::arrayAtPut) valueObject = ec.stackPop(); if (! isSmallInteger(indexObject) ) { failed = true; break; } // Smalltalk indexes arrays starting from 1, not from 0 // So we need to recalculate the actual array index before uint32_t actualIndex = TInteger(indexObject) - 1; // Checking boundaries if (actualIndex >= array->getSize()) { failed = true; break; } if (opcode == primitive::arrayAt) { return array->getField(actualIndex); } else { // Array:at:put TObject** objectSlot = &( array->getFields()[actualIndex] ); // Checking whether we need to register current object slot in the GC checkRoot(valueObject, objectSlot); // Storing the value into the array array->putField(actualIndex, valueObject); // Return self return static_cast<TObject*>(array); } } break; case primitive::cloneByteObject: { // 23 TClass* klass = ec.stackPop<TClass>(); hptr<TByteObject> original = newPointer( ec.stackPop<TByteObject>() ); // Creating clone uint32_t dataSize = original->getSize(); TByteObject* clone = newBinaryObject(klass, dataSize); // Cloning data std::memcpy(clone->getBytes(), original->getBytes(), dataSize); return static_cast<TObject*>(clone); } break; // case primitive::integerDiv: // Integer / // case primitive::integerMod: // Integer % // case primitive::integerAdd: // Integer + // case primitive::integerMul: // Integer * // case primitive::integerSub: // Integer - // case primitive::integerLess: // Integer < // case primitive::integerEqual: // Integer == // //TODO integer operations // break; case primitive::integerNew: { // 32 TObject* object = ec.stackPop(); if (! isSmallInteger(object)) { failed = true; break; } return object; // FIXME long integer } break; case primitive::flushCache: // 34 flushMethodCache(); break; case primitive::bulkReplace: { // 38 //Implementation of replaceFrom:to:with:startingAt: as a primitive // Array replaceFrom: start to: stop with: replacement startingAt: repStart // <38 start stop replacement repStart self>. // Current stack contents (top is the top) // self // repStart // replacement // stop // start TObject* destination = ec.stackPop(); TObject* sourceStartOffset = ec.stackPop(); TObject* source = ec.stackPop(); TObject* destinationStopOffset = ec.stackPop(); TObject* destinationStartOffset = ec.stackPop(); bool isSucceeded = doBulkReplace( destination, destinationStartOffset, destinationStopOffset, source, sourceStartOffset ); if (! isSucceeded) { failed = true; break; } return destination; } break; // TODO cases 33, 35, 40 // TODO case 18 // turn on debugging case primitive::objectsAreEqual: // 1 case primitive::getClass: // 2 case primitive::getSize: // 4 case primitive::ioGetChar: // 9 case primitive::ioPutChar: // 3 case primitive::ioFileOpen: // 100 case primitive::ioFileClose: // 103 case primitive::ioFileSetStatIntoArray: // 105 case primitive::ioFileReadIntoByteArray: // 106 case primitive::ioFileWriteFromByteArray: // 107 case primitive::ioFileSeek: // 108 case primitive::stringAt: // 21 case primitive::stringAtPut: // 22 case primitive::smallIntAdd: // 10 case primitive::smallIntDiv: // 11 case primitive::smallIntMod: // 12 case primitive::smallIntLess: // 13 case primitive::smallIntEqual: // 14 case primitive::smallIntMul: // 15 case primitive::smallIntSub: // 16 case primitive::smallIntBitOr: // 36 case primitive::smallIntBitAnd: // 37 case primitive::smallIntBitShift: // 39 case primitive::getSystemTicks: //253 default: { uint32_t argCount = ec.instruction.getArgument(); hptr<TObjectArray> args = newObject<TObjectArray>(argCount); uint32_t i = argCount; while (i > 0) args[--i] = ec.stackPop(); TObject* result = callPrimitive(opcode, args, failed); return result; } } return globals.nilObject; }