Exemple #1
0
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;
}
Exemple #3
0
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);
    }
}