bool SkipRange() { int savedObjPtr = g_pCompilerData->obj_ptr; bool savedStringPatchEnable = g_pCompilerData->str_patch_enable; g_pCompilerData->str_patch_enable = false; bool bRange; if (!CompileRange(bRange)) { return false; } g_pCompilerData->str_patch_enable = savedStringPatchEnable; g_pCompilerData->obj_ptr = savedObjPtr; return true; }
void CBasicBlock::Compile() { #ifndef AOT_USE_CACHE Framework::CMemStream stream; { static #ifdef AOT_BUILD_CACHE __declspec(thread) #endif CMipsJitter* jitter = nullptr; if(jitter == nullptr) { Jitter::CCodeGen* codeGen = Jitter::CreateCodeGen(); jitter = new CMipsJitter(codeGen); for(unsigned int i = 0; i < 4; i++) { jitter->SetVariableAsConstant( offsetof(CMIPS, m_State.nGPR[CMIPS::R0].nV[i]), 0); } } jitter->SetStream(&stream); jitter->Begin(); CompileRange(jitter); // codeGen.DumpVariables(0); // codeGen.EndQuota(); jitter->End(); } m_function = CMemoryFunction(stream.GetBuffer(), stream.GetSize()); #ifdef VTUNE_ENABLED if(iJIT_IsProfilingActive() == iJIT_SAMPLING_ON) { iJIT_Method_Load jmethod = {}; jmethod.method_id = iJIT_GetNewMethodID(); jmethod.class_file_name = ""; jmethod.source_file_name = __FILE__; jmethod.method_load_address = m_function.GetCode(); jmethod.method_size = m_function.GetSize(); jmethod.line_number_size = 0; auto functionName = string_format("BasicBlock_0x%08X_0x%08X", m_begin, m_end); jmethod.method_name = const_cast<char*>(functionName.c_str()); iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, reinterpret_cast<void*>(&jmethod)); } #endif #endif #ifdef AOT_ENABLED size_t blockSize = ((m_end - m_begin) / 4) + 1; auto blockData = new uint32[blockSize]; for(uint32 i = 0; i < blockSize; i++) { blockData[i] = m_context.m_pMemoryMap->GetWord(m_begin + (i * 4)); } uint32 blockChecksum = crc32(0, reinterpret_cast<Bytef*>(blockData), blockSize * 4); #endif #ifdef AOT_USE_CACHE AOT_BLOCK* blocksBegin = &_aot_firstBlock; AOT_BLOCK* blocksEnd = blocksBegin + _aot_blockCount; AOT_BLOCK blockRef = {blockChecksum, m_begin, m_end, nullptr}; static const auto blockComparer = [](const AOT_BLOCK& item1, const AOT_BLOCK& item2) { return item1.key < item2.key; }; // assert(std::is_sorted(blocksBegin, blocksEnd, blockComparer)); bool blockExists = std::binary_search(blocksBegin, blocksEnd, blockRef, blockComparer); auto blockIterator = std::lower_bound(blocksBegin, blocksEnd, blockRef, blockComparer); assert(blockExists); assert(blockIterator != blocksEnd); assert(blockIterator->key.crc == blockChecksum); assert(blockIterator->key.begin == m_begin); assert(blockIterator->key.end == m_end); m_function = reinterpret_cast<void (*)(void*)>(blockIterator->fct); #endif #ifdef AOT_BUILD_CACHE { std::lock_guard<std::mutex> lock(m_aotBlockOutputStreamMutex); m_aotBlockOutputStream->Write32(blockChecksum); m_aotBlockOutputStream->Write32(m_begin); m_aotBlockOutputStream->Write32(m_end); m_aotBlockOutputStream->Write(blockData, blockSize * 4); } #endif }
bool CompileCase(int column, int param) { param = param; // stop warning if (!BlockStack_CompileConstant()) { return false; } if (!CompileExpression()) { return false; } if (!g_pElementizer->GetElement(type_end)) { return false; } int savedSourcePtr = g_pElementizer->GetSourcePtr(); int otherSourcePtr = 0; bool bOther = false; int caseCount = 0; bool bEof = false; while (!bEof) { if (!g_pElementizer->GetNext(bEof)) { return false; } if (bEof) { break; } if (g_pElementizer->GetType() == type_end) { continue; } s_column = g_pElementizer->GetColumn(); g_pElementizer->Backup(); if (s_column <= column) { break; } if (bOther) // if we have OTHER: it should have been the last case, so we shouldn't get here again { g_pCompilerData->error = true; g_pCompilerData->error_msg = g_pErrorStrings[error_omblc]; return false; } if (g_pElementizer->GetType() == type_other) { bOther = true; if (!g_pElementizer->GetNext(bEof)) // get/skip 'other' { return false; } otherSourcePtr = g_pCompilerData->source_start; // save the pointer to the beginning of 'other' } else { caseCount++; if (caseCount > case_limit) { g_pCompilerData->error = true; g_pCompilerData->error_msg = g_pErrorStrings[error_loxce]; return false; } while (1) { bool bRange = false; if (!CompileRange(bRange)) { return false; } if (!EnterObj(bRange ? 0x0E : 0x0D)) // enter bytecode for case range or case value into obj { return false; } if (!BlockStack_CompileAddress(caseCount)) { return false; } if (!g_pElementizer->CheckElement(type_comma)) { break; } } } if (!g_pElementizer->GetElement(type_colon)) { return false; } if (!SkipBlock(s_column)) { return false; } } if (caseCount == 0) { g_pCompilerData->error = true; g_pCompilerData->error_msg = g_pErrorStrings[error_nce]; return false; } if (bOther) { // set the source pointer to where the OTHER is at, then get it to set the column g_pElementizer->SetSourcePtr(otherSourcePtr); if (!g_pElementizer->GetNext(bEof)) { return false; } int new_column = g_pElementizer->GetColumn(); // skip the colon if (!g_pElementizer->GetNext(bEof)) { return false; } if (!CompileBlock(new_column)) { return false; } } if (!EnterObj(0x0C)) // casedone, end of range checks { return false; } g_pElementizer->SetSourcePtr(savedSourcePtr); caseCount = 0; bOther = false; bEof = false; while(!bEof) { if (!g_pElementizer->GetNext(bEof)) { return false; } if (bEof) { break; } if (g_pElementizer->GetType() == type_end) { continue; } s_column = g_pElementizer->GetColumn(); g_pElementizer->Backup(); if (s_column <= column) { break; } if (g_pElementizer->GetType() == type_other) { // skip over other, already compiled if (!g_pElementizer->GetNext(bEof)) { return false; } if (!g_pElementizer->GetNext(bEof)) { return false; } if (!SkipBlock(s_column)) { return false; } } else { // skip over range/values(s), allready compiled while (1) { if (!SkipRange()) { return false; } if (!g_pElementizer->CheckElement(type_comma)) { break; } } caseCount++; BlockStack_Write(caseCount, g_pCompilerData->obj_ptr); if (!g_pElementizer->GetElement(type_colon)) { return false; } if (!CompileBlock(s_column)) { return false; } if (!EnterObj(0x0C)) // casedone { return false; } } } BlockStack_Write(0, g_pCompilerData->obj_ptr); return true; }