Error JitRuntime::add(void** dst, BaseAssembler* assembler) { // Disallow empty code generation. size_t codeSize = assembler->getCodeSize(); if (codeSize == 0) { *dst = NULL; return kErrorInvalidFunction; } void* p = _memMgr.alloc(codeSize, getAllocType()); if (p == NULL) { *dst = NULL; return kErrorNoVirtualMemory; } // Relocate the code. size_t relocSize = assembler->relocCode(p); // Return unused memory to `VMemMgr`. if (relocSize < codeSize) _memMgr.shrink(p, relocSize); // Return the code. *dst = p; flush(p, relocSize); return kErrorOk; }
Error JitRuntime::_add(void** dst, CodeHolder* code) noexcept { size_t codeSize = code->getCodeSize(); if (ASMJIT_UNLIKELY(codeSize == 0)) { *dst = nullptr; return DebugUtils::errored(kErrorNoCodeGenerated); } void* p = _memMgr.alloc(codeSize, getAllocType()); if (ASMJIT_UNLIKELY(!p)) { *dst = nullptr; return DebugUtils::errored(kErrorNoVirtualMemory); } // Relocate the code and release the unused memory back to `VMemMgr`. size_t relocSize = code->relocate(p); if (ASMJIT_UNLIKELY(relocSize == 0)) { *dst = nullptr; _memMgr.release(p); return DebugUtils::errored(kErrorInvalidState); } if (relocSize < codeSize) _memMgr.shrink(p, relocSize); flush(p, relocSize); *dst = p; return kErrorOk; }
Error JitRuntime::add(void** dst, Assembler* assembler) noexcept { size_t codeSize = assembler->getCodeSize(); if (codeSize == 0) { *dst = nullptr; return kErrorNoCodeGenerated; } void* p = _memMgr.alloc(codeSize, getAllocType()); if (p == nullptr) { *dst = nullptr; return kErrorNoVirtualMemory; } // Relocate the code and release the unused memory back to `VMemMgr`. size_t relocSize = assembler->relocCode(p); if (relocSize == 0) { *dst = nullptr; _memMgr.release(p); return kErrorInvalidState; } if (relocSize < codeSize) _memMgr.shrink(p, relocSize); flush(p, relocSize); *dst = p; return kErrorOk; }
void CheckAllocationsInFunctionVisitor::VisitAllocate( const A0& getArg0, const A1& getArg1, const T& getAllocType) { const Expr* firstArgNode = getArg0(); // Check if the first argument (to new or AllocateArray) is a static cast // AllocatorNew/AllocateArray in Chakra always does a static_cast to the AllocatorType const CXXStaticCastExpr* castNode = nullptr; if (firstArgNode != nullptr && (castNode = dyn_cast<CXXStaticCastExpr>(firstArgNode))) { QualType allocatedType = getAllocType(); string allocatedTypeStr = allocatedType.getAsString(); auto allocationType = CheckAllocationType(castNode); if (allocationType == AllocationTypes::Recycler) // Recycler allocation { const Expr* secondArgNode = getArg1(); // Chakra has two types of allocating functions- throwing and non-throwing // However, recycler allocations are always throwing, so the second parameter // should be the address of the allocator function auto unaryNode = cast<UnaryOperator>(secondArgNode); if (unaryNode != nullptr && unaryNode->getOpcode() == UnaryOperatorKind::UO_AddrOf) { Expr* subExpr = unaryNode->getSubExpr(); if (DeclRefExpr* declRef = cast<DeclRefExpr>(subExpr)) { auto declNameInfo = declRef->getNameInfo(); auto allocationFunctionStr = declNameInfo.getName().getAsString(); _mainVisitor->RecordRecyclerAllocation(allocationFunctionStr, allocatedTypeStr); if (!Contains(allocationFunctionStr, "Leaf")) { // Recycler write barrier allocation -- unless "Leaf" in allocFunc allocationType = AllocationTypes::RecyclerWriteBarrier; } } else { Log::errs() << "ERROR: (internal) Expected DeclRefExpr:\n"; subExpr->dump(); } } else if (auto mExpr = cast<MaterializeTemporaryExpr>(secondArgNode)) { auto name = mExpr->GetTemporaryExpr()->IgnoreImpCasts()->getType().getAsString(); if (StartsWith(name, "InfoBitsWrapper<")) // && Contains(name, "WithBarrierBit")) { // RecyclerNewEnumClass, RecyclerNewWithInfoBits -- always have WithBarrier varients allocationType = AllocationTypes::RecyclerWriteBarrier; } } else { Log::errs() << "ERROR: (internal) Expected unary node or MaterializeTemporaryExpr:\n"; secondArgNode->dump(); } } if (allocationType & AllocationTypes::WriteBarrier) { Log::outs() << "In \"" << _functionDecl->getQualifiedNameAsString() << "\"\n"; Log::outs() << " Allocating \"" << allocatedTypeStr << "\" in write barriered memory\n"; } _mainVisitor->RecordAllocation(allocatedType, allocationType); } }