diff options
author | Gael Guennebaud <g.gael@free.fr> | 2011-03-19 01:06:50 +0100 |
---|---|---|
committer | Gael Guennebaud <g.gael@free.fr> | 2011-03-19 01:06:50 +0100 |
commit | 290205dfc049abc5a92c1191740b30fa91130ade (patch) | |
tree | 0d07fea8597fb5d7f023a23cce7cb0b240be84c2 /Eigen/src/Core | |
parent | 5991d247f9b167ed738ef95ead0b5ee9a0248edd (diff) |
fix memory leak when a custom scalar throw an exception
Diffstat (limited to 'Eigen/src/Core')
-rw-r--r-- | Eigen/src/Core/Product.h | 35 | ||||
-rw-r--r-- | Eigen/src/Core/SolveTriangular.h | 17 | ||||
-rw-r--r-- | Eigen/src/Core/products/GeneralMatrixMatrix.h | 16 | ||||
-rw-r--r-- | Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h | 6 | ||||
-rw-r--r-- | Eigen/src/Core/products/SelfadjointMatrixMatrix.h | 15 | ||||
-rw-r--r-- | Eigen/src/Core/products/SelfadjointMatrixVector.h | 41 | ||||
-rw-r--r-- | Eigen/src/Core/products/SelfadjointProduct.h | 20 | ||||
-rw-r--r-- | Eigen/src/Core/products/TriangularMatrixMatrix.h | 16 | ||||
-rw-r--r-- | Eigen/src/Core/products/TriangularMatrixVector.h | 43 | ||||
-rw-r--r-- | Eigen/src/Core/products/TriangularSolverMatrix.h | 14 | ||||
-rw-r--r-- | Eigen/src/Core/util/Memory.h | 82 |
11 files changed, 116 insertions, 189 deletions
diff --git a/Eigen/src/Core/Product.h b/Eigen/src/Core/Product.h index 1363e83b6..bde25375d 100644 --- a/Eigen/src/Core/Product.h +++ b/Eigen/src/Core/Product.h @@ -416,23 +416,15 @@ template<> struct gemv_selector<OnTheRight,ColMajor,true> RhsScalar compatibleAlpha = get_factor<ResScalar,RhsScalar>::run(actualAlpha); - ResScalar* actualDestPtr; - bool freeDestPtr = false; - if (evalToDest) - { - actualDestPtr = &dest.coeffRef(0); - } - else + ei_declare_aligned_stack_constructed_variable(ResScalar,actualDestPtr,dest.size(), + evalToDest ? dest.data() : static_dest.data()); + + if(!evalToDest) { #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN int size = dest.size(); EIGEN_DENSE_STORAGE_CTOR_PLUGIN #endif - if((actualDestPtr = static_dest.data())==0) - { - freeDestPtr = true; - actualDestPtr = ei_aligned_stack_new(ResScalar,dest.size()); - } if(!alphaIsCompatible) { MappedDest(actualDestPtr, dest.size()).setZero(); @@ -456,7 +448,6 @@ template<> struct gemv_selector<OnTheRight,ColMajor,true> dest += actualAlpha * MappedDest(actualDestPtr, dest.size()); else dest = MappedDest(actualDestPtr, dest.size()); - if(freeDestPtr) ei_aligned_stack_delete(ResScalar, actualDestPtr, dest.size()); } } }; @@ -490,23 +481,15 @@ template<> struct gemv_selector<OnTheRight,RowMajor,true> gemv_static_vector_if<RhsScalar,_ActualRhsType::SizeAtCompileTime,_ActualRhsType::MaxSizeAtCompileTime,!DirectlyUseRhs> static_rhs; - RhsScalar* actualRhsPtr; - bool freeRhsPtr = false; - if (DirectlyUseRhs) - { - actualRhsPtr = const_cast<RhsScalar*>(&actualRhs.coeffRef(0)); - } - else + ei_declare_aligned_stack_constructed_variable(RhsScalar,actualRhsPtr,actualRhs.size(), + DirectlyUseRhs ? const_cast<RhsScalar*>(actualRhs.data()) : static_rhs.data()); + + if(!DirectlyUseRhs) { #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN int size = actualRhs.size(); EIGEN_DENSE_STORAGE_CTOR_PLUGIN #endif - if((actualRhsPtr = static_rhs.data())==0) - { - freeRhsPtr = true; - actualRhsPtr = ei_aligned_stack_new(RhsScalar, actualRhs.size()); - } Map<typename _ActualRhsType::PlainObject>(actualRhsPtr, actualRhs.size()) = actualRhs; } @@ -517,8 +500,6 @@ template<> struct gemv_selector<OnTheRight,RowMajor,true> actualRhsPtr, 1, &dest.coeffRef(0,0), dest.innerStride(), actualAlpha); - - if((!DirectlyUseRhs) && freeRhsPtr) ei_aligned_stack_delete(RhsScalar, actualRhsPtr, prod.rhs().size()); } }; diff --git a/Eigen/src/Core/SolveTriangular.h b/Eigen/src/Core/SolveTriangular.h index 7cbcf3d80..71e129c7f 100644 --- a/Eigen/src/Core/SolveTriangular.h +++ b/Eigen/src/Core/SolveTriangular.h @@ -74,26 +74,19 @@ struct triangular_solver_selector<Lhs,Rhs,Side,Mode,NoUnrolling,1> // FIXME find a way to allow an inner stride if packet_traits<Scalar>::size==1 bool useRhsDirectly = Rhs::InnerStrideAtCompileTime==1 || rhs.innerStride()==1; - RhsScalar* actualRhs; - if(useRhsDirectly) - { - actualRhs = &rhs.coeffRef(0); - } - else - { - actualRhs = ei_aligned_stack_new(RhsScalar,rhs.size()); + + ei_declare_aligned_stack_constructed_variable(RhsScalar,actualRhs,rhs.size(), + (useRhsDirectly ? rhs.data() : 0)); + + if(!useRhsDirectly) MappedRhs(actualRhs,rhs.size()) = rhs; - } triangular_solve_vector<LhsScalar, RhsScalar, typename Lhs::Index, Side, Mode, LhsProductTraits::NeedToConjugate, (int(Lhs::Flags) & RowMajorBit) ? RowMajor : ColMajor> ::run(actualLhs.cols(), actualLhs.data(), actualLhs.outerStride(), actualRhs); if(!useRhsDirectly) - { rhs = MappedRhs(actualRhs, rhs.size()); - ei_aligned_stack_delete(RhsScalar, actualRhs, rhs.size()); - } } }; diff --git a/Eigen/src/Core/products/GeneralMatrixMatrix.h b/Eigen/src/Core/products/GeneralMatrixMatrix.h index 7736a4b29..d558b4759 100644 --- a/Eigen/src/Core/products/GeneralMatrixMatrix.h +++ b/Eigen/src/Core/products/GeneralMatrixMatrix.h @@ -94,8 +94,9 @@ static void run(Index rows, Index cols, Index depth, std::size_t sizeA = kc*mc; std::size_t sizeW = kc*Traits::WorkSpaceFactor; - LhsScalar* blockA = ei_aligned_stack_new(LhsScalar, sizeA); - RhsScalar* w = ei_aligned_stack_new(RhsScalar, sizeW); + ei_declare_aligned_stack_constructed_variable(LhsScalar, blockA, sizeA, 0); + ei_declare_aligned_stack_constructed_variable(RhsScalar, w, sizeW, 0); + RhsScalar* blockB = blocking.blockB(); eigen_internal_assert(blockB!=0); @@ -167,9 +168,10 @@ static void run(Index rows, Index cols, Index depth, std::size_t sizeA = kc*mc; std::size_t sizeB = kc*cols; std::size_t sizeW = kc*Traits::WorkSpaceFactor; - LhsScalar *blockA = blocking.blockA()==0 ? ei_aligned_stack_new(LhsScalar, sizeA) : blocking.blockA(); - RhsScalar *blockB = blocking.blockB()==0 ? ei_aligned_stack_new(RhsScalar, sizeB) : blocking.blockB(); - RhsScalar *blockW = blocking.blockW()==0 ? ei_aligned_stack_new(RhsScalar, sizeW) : blocking.blockW(); + + ei_declare_aligned_stack_constructed_variable(LhsScalar, blockA, sizeA, blocking.blockA()); + ei_declare_aligned_stack_constructed_variable(RhsScalar, blockB, sizeB, blocking.blockB()); + ei_declare_aligned_stack_constructed_variable(RhsScalar, blockW, sizeW, blocking.blockW()); // For each horizontal panel of the rhs, and corresponding panel of the lhs... // (==GEMM_VAR1) @@ -200,10 +202,6 @@ static void run(Index rows, Index cols, Index depth, } } - - if(blocking.blockA()==0) ei_aligned_stack_delete(LhsScalar, blockA, sizeA); - if(blocking.blockB()==0) ei_aligned_stack_delete(RhsScalar, blockB, sizeB); - if(blocking.blockW()==0) ei_aligned_stack_delete(RhsScalar, blockW, sizeW); } } diff --git a/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h b/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h index 39495c1a2..562c9c5ad 100644 --- a/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h +++ b/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h @@ -83,10 +83,10 @@ struct general_matrix_matrix_triangular_product<Index,LhsScalar,LhsStorageOrder, if(mc > Traits::nr) mc = (mc/Traits::nr)*Traits::nr; - LhsScalar* blockA = ei_aligned_stack_new(LhsScalar, kc*mc); std::size_t sizeW = kc*Traits::WorkSpaceFactor; std::size_t sizeB = sizeW + kc*size; - RhsScalar* allocatedBlockB = ei_aligned_stack_new(RhsScalar, sizeB); + ei_declare_aligned_stack_constructed_variable(LhsScalar, blockA, kc*mc, 0); + ei_declare_aligned_stack_constructed_variable(RhsScalar, allocatedBlockB, sizeB, 0); RhsScalar* blockB = allocatedBlockB + sizeW; gemm_pack_lhs<LhsScalar, Index, Traits::mr, Traits::LhsProgress, LhsStorageOrder> pack_lhs; @@ -125,8 +125,6 @@ struct general_matrix_matrix_triangular_product<Index,LhsScalar,LhsStorageOrder, } } } - ei_aligned_stack_delete(LhsScalar, blockA, kc*mc); - ei_aligned_stack_delete(RhsScalar, allocatedBlockB, sizeB); } }; diff --git a/Eigen/src/Core/products/SelfadjointMatrixMatrix.h b/Eigen/src/Core/products/SelfadjointMatrixMatrix.h index cfebcf426..6eb54d6ef 100644 --- a/Eigen/src/Core/products/SelfadjointMatrixMatrix.h +++ b/Eigen/src/Core/products/SelfadjointMatrixMatrix.h @@ -263,10 +263,10 @@ struct product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,true,ConjugateLhs // kc must smaller than mc kc = std::min(kc,mc); - Scalar* blockA = ei_aligned_stack_new(Scalar, kc*mc); std::size_t sizeW = kc*Traits::WorkSpaceFactor; std::size_t sizeB = sizeW + kc*cols; - Scalar* allocatedBlockB = ei_aligned_stack_new(Scalar, sizeB); + ei_declare_aligned_stack_constructed_variable(Scalar, blockA, kc*mc, 0); + ei_declare_aligned_stack_constructed_variable(Scalar, allocatedBlockB, sizeB, 0); Scalar* blockB = allocatedBlockB + sizeW; gebp_kernel<Scalar, Scalar, Index, Traits::mr, Traits::nr, ConjugateLhs, ConjugateRhs> gebp_kernel; @@ -313,9 +313,6 @@ struct product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,true,ConjugateLhs gebp_kernel(res+i2, resStride, blockA, blockB, actual_mc, actual_kc, cols, alpha); } } - - ei_aligned_stack_delete(Scalar, blockA, kc*mc); - ei_aligned_stack_delete(Scalar, allocatedBlockB, sizeB); } }; @@ -343,11 +340,10 @@ struct product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,false,ConjugateLh Index mc = rows; // cache block size along the M direction Index nc = cols; // cache block size along the N direction computeProductBlockingSizes<Scalar,Scalar>(kc, mc, nc); - - Scalar* blockA = ei_aligned_stack_new(Scalar, kc*mc); std::size_t sizeW = kc*Traits::WorkSpaceFactor; std::size_t sizeB = sizeW + kc*cols; - Scalar* allocatedBlockB = ei_aligned_stack_new(Scalar, sizeB); + ei_declare_aligned_stack_constructed_variable(Scalar, blockA, kc*mc, 0); + ei_declare_aligned_stack_constructed_variable(Scalar, allocatedBlockB, sizeB, 0); Scalar* blockB = allocatedBlockB + sizeW; gebp_kernel<Scalar, Scalar, Index, Traits::mr, Traits::nr, ConjugateLhs, ConjugateRhs> gebp_kernel; @@ -369,9 +365,6 @@ struct product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,false,ConjugateLh gebp_kernel(res+i2, resStride, blockA, blockB, actual_mc, actual_kc, cols, alpha); } } - - ei_aligned_stack_delete(Scalar, blockA, kc*mc); - ei_aligned_stack_delete(Scalar, allocatedBlockB, sizeB); } }; diff --git a/Eigen/src/Core/products/SelfadjointMatrixVector.h b/Eigen/src/Core/products/SelfadjointMatrixVector.h index 1d433e16d..62744f98d 100644 --- a/Eigen/src/Core/products/SelfadjointMatrixVector.h +++ b/Eigen/src/Core/products/SelfadjointMatrixVector.h @@ -62,14 +62,12 @@ static EIGEN_DONT_INLINE void product_selfadjoint_vector( // FIXME this copy is now handled outside product_selfadjoint_vector, so it could probably be removed. // if the rhs is not sequentially stored in memory we copy it to a temporary buffer, // this is because we need to extract packets - const Scalar* EIGEN_RESTRICT rhs = _rhs; + ei_declare_aligned_stack_constructed_variable(Scalar,rhs,size,rhsIncr==1 ? const_cast<Scalar*>(_rhs) : 0); if (rhsIncr!=1) { - Scalar* r = ei_aligned_stack_new(Scalar, size); const Scalar* it = _rhs; for (Index i=0; i<size; ++i, it+=rhsIncr) - r[i] = *it; - rhs = r; + rhs[i] = *it; } Index bound = std::max(Index(0),size-8) & 0xfffffffe; @@ -160,9 +158,6 @@ static EIGEN_DONT_INLINE void product_selfadjoint_vector( } res[j] += alpha * t2; } - - if(rhsIncr!=1) - ei_aligned_stack_delete(Scalar, const_cast<Scalar*>(rhs), size); } } // end namespace internal @@ -211,40 +206,28 @@ struct SelfadjointProductMatrix<Lhs,LhsMode,false,Rhs,0,true> internal::gemv_static_vector_if<ResScalar,Dest::SizeAtCompileTime,Dest::MaxSizeAtCompileTime,!EvalToDest> static_dest; internal::gemv_static_vector_if<RhsScalar,_ActualRhsType::SizeAtCompileTime,_ActualRhsType::MaxSizeAtCompileTime,!UseRhs> static_rhs; + + ei_declare_aligned_stack_constructed_variable(ResScalar,actualDestPtr,dest.size(), + EvalToDest ? dest.data() : static_dest.data()); + + ei_declare_aligned_stack_constructed_variable(RhsScalar,actualRhsPtr,rhs.size(), + UseRhs ? const_cast<RhsScalar*>(rhs.data()) : static_rhs.data()); - bool freeDestPtr = false; - ResScalar* actualDestPtr; - if(EvalToDest) - actualDestPtr = dest.data(); - else + if(!EvalToDest) { #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN int size = dest.size(); EIGEN_DENSE_STORAGE_CTOR_PLUGIN #endif - if((actualDestPtr=static_dest.data())==0) - { - freeDestPtr = true; - actualDestPtr = ei_aligned_stack_new(ResScalar,dest.size()); - } MappedDest(actualDestPtr, dest.size()) = dest; } - bool freeRhsPtr = false; - RhsScalar* actualRhsPtr; - if(UseRhs) - actualRhsPtr = const_cast<RhsScalar*>(rhs.data()); - else + if(!UseRhs) { #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN int size = rhs.size(); EIGEN_DENSE_STORAGE_CTOR_PLUGIN #endif - if((actualRhsPtr=static_rhs.data())==0) - { - freeRhsPtr = true; - actualRhsPtr = ei_aligned_stack_new(RhsScalar,rhs.size()); - } Map<typename _ActualRhsType::PlainObject>(actualRhsPtr, rhs.size()) = rhs; } @@ -259,11 +242,7 @@ struct SelfadjointProductMatrix<Lhs,LhsMode,false,Rhs,0,true> ); if(!EvalToDest) - { dest = MappedDest(actualDestPtr, dest.size()); - if(freeDestPtr) ei_aligned_stack_delete(ResScalar, actualDestPtr, dest.size()); - } - if(freeRhsPtr) ei_aligned_stack_delete(RhsScalar, actualRhsPtr, rhs.size()); } }; diff --git a/Eigen/src/Core/products/SelfadjointProduct.h b/Eigen/src/Core/products/SelfadjointProduct.h index da2e6ee20..3a4523fa4 100644 --- a/Eigen/src/Core/products/SelfadjointProduct.h +++ b/Eigen/src/Core/products/SelfadjointProduct.h @@ -81,27 +81,17 @@ struct selfadjoint_product_selector<MatrixType,OtherType,UpLo,true> UseOtherDirectly = _ActualOtherType::InnerStrideAtCompileTime==1 }; internal::gemv_static_vector_if<Scalar,OtherType::SizeAtCompileTime,OtherType::MaxSizeAtCompileTime,!UseOtherDirectly> static_other; - - bool freeOtherPtr = false; - Scalar* actualOtherPtr; - if(UseOtherDirectly) - actualOtherPtr = const_cast<Scalar*>(actualOther.data()); - else - { - if((actualOtherPtr=static_other.data())==0) - { - freeOtherPtr = true; - actualOtherPtr = ei_aligned_stack_new(Scalar,other.size()); - } + + ei_declare_aligned_stack_constructed_variable(Scalar, actualOtherPtr, other.size(), + (UseOtherDirectly ? const_cast<Scalar*>(actualOther.data()) : static_other.data())); + + if(!UseOtherDirectly) Map<typename _ActualOtherType::PlainObject>(actualOtherPtr, actualOther.size()) = actualOther; - } selfadjoint_rank1_update<Scalar,Index,StorageOrder,UpLo, OtherBlasTraits::NeedToConjugate && NumTraits<Scalar>::IsComplex, (!OtherBlasTraits::NeedToConjugate) && NumTraits<Scalar>::IsComplex> ::run(other.size(), mat.data(), mat.outerStride(), actualOtherPtr, actualAlpha); - - if((!UseOtherDirectly) && freeOtherPtr) ei_aligned_stack_delete(Scalar, actualOtherPtr, other.size()); } }; diff --git a/Eigen/src/Core/products/TriangularMatrixMatrix.h b/Eigen/src/Core/products/TriangularMatrixMatrix.h index 66a2515d0..8f7e58f62 100644 --- a/Eigen/src/Core/products/TriangularMatrixMatrix.h +++ b/Eigen/src/Core/products/TriangularMatrixMatrix.h @@ -118,11 +118,10 @@ struct product_triangular_matrix_matrix<Scalar,Index,Mode,true, Index mc = rows; // cache block size along the M direction Index nc = cols; // cache block size along the N direction computeProductBlockingSizes<Scalar,Scalar,4>(kc, mc, nc); - - Scalar* blockA = ei_aligned_stack_new(Scalar, kc*mc); std::size_t sizeW = kc*Traits::WorkSpaceFactor; std::size_t sizeB = sizeW + kc*cols; - Scalar* allocatedBlockB = ei_aligned_stack_new(Scalar, sizeB); + ei_declare_aligned_stack_constructed_variable(Scalar, blockA, kc*mc, 0); + ei_declare_aligned_stack_constructed_variable(Scalar, allocatedBlockB, sizeB, 0); Scalar* blockB = allocatedBlockB + sizeW; Matrix<Scalar,SmallPanelWidth,SmallPanelWidth,LhsStorageOrder> triangularBuffer; @@ -208,10 +207,6 @@ struct product_triangular_matrix_matrix<Scalar,Index,Mode,true, } } } - - ei_aligned_stack_delete(Scalar, blockA, kc*mc); - ei_aligned_stack_delete(Scalar, allocatedBlockB, sizeB); -// delete[] allocatedBlockB; } }; @@ -246,10 +241,10 @@ struct product_triangular_matrix_matrix<Scalar,Index,Mode,false, Index nc = cols; // cache block size along the N direction computeProductBlockingSizes<Scalar,Scalar,4>(kc, mc, nc); - Scalar* blockA = ei_aligned_stack_new(Scalar, kc*mc); std::size_t sizeW = kc*Traits::WorkSpaceFactor; std::size_t sizeB = sizeW + kc*cols; - Scalar* allocatedBlockB = ei_aligned_stack_new(Scalar,sizeB); + ei_declare_aligned_stack_constructed_variable(Scalar, blockA, kc*mc, 0); + ei_declare_aligned_stack_constructed_variable(Scalar, allocatedBlockB, sizeB, 0); Scalar* blockB = allocatedBlockB + sizeW; Matrix<Scalar,SmallPanelWidth,SmallPanelWidth,RhsStorageOrder> triangularBuffer; @@ -347,9 +342,6 @@ struct product_triangular_matrix_matrix<Scalar,Index,Mode,false, -1, -1, 0, 0, allocatedBlockB); } } - - ei_aligned_stack_delete(Scalar, blockA, kc*mc); - ei_aligned_stack_delete(Scalar, allocatedBlockB, sizeB); } }; diff --git a/Eigen/src/Core/products/TriangularMatrixVector.h b/Eigen/src/Core/products/TriangularMatrixVector.h index 23aa52ade..1dd2fafa4 100644 --- a/Eigen/src/Core/products/TriangularMatrixVector.h +++ b/Eigen/src/Core/products/TriangularMatrixVector.h @@ -41,9 +41,6 @@ struct product_triangular_matrix_vector<Index,Mode,LhsScalar,ConjLhs,RhsScalar,C static EIGEN_DONT_INLINE void run(Index rows, Index cols, const LhsScalar* _lhs, Index lhsStride, const RhsScalar* _rhs, Index rhsIncr, ResScalar* _res, Index resIncr, ResScalar alpha) { - EIGEN_UNUSED_VARIABLE(resIncr); - eigen_assert(resIncr==1); - static const Index PanelWidth = EIGEN_TUNE_TRIANGULAR_PANEL_WIDTH; typedef Map<const Matrix<LhsScalar,Dynamic,Dynamic,ColMajor>, 0, OuterStride<> > LhsMap; @@ -95,9 +92,6 @@ struct product_triangular_matrix_vector<Index,Mode,LhsScalar,ConjLhs,RhsScalar,C static void run(Index rows, Index cols, const LhsScalar* _lhs, Index lhsStride, const RhsScalar* _rhs, Index rhsIncr, ResScalar* _res, Index resIncr, ResScalar alpha) { - eigen_assert(rhsIncr==1); - EIGEN_UNUSED_VARIABLE(rhsIncr); - static const Index PanelWidth = EIGEN_TUNE_TRIANGULAR_PANEL_WIDTH; typedef Map<const Matrix<LhsScalar,Dynamic,Dynamic,RowMajor>, 0, OuterStride<> > LhsMap; @@ -185,7 +179,7 @@ struct TriangularProduct<Mode,false,Lhs,true,Rhs,false> template<typename Dest> void scaleAndAddTo(Dest& dst, Scalar alpha) const { eigen_assert(dst.rows()==m_lhs.rows() && dst.cols()==m_rhs.cols()); - + typedef TriangularProduct<(Mode & UnitDiag) | ((Mode & Lower) ? Upper : Lower),true,Transpose<const Rhs>,false,Transpose<const Lhs>,true> TriangularProductTranspose; Transpose<Dest> dstT(dst); internal::trmv_selector<(int(internal::traits<Rhs>::Flags)&RowMajorBit) ? ColMajor : RowMajor>::run( @@ -235,23 +229,15 @@ template<> struct trmv_selector<ColMajor> RhsScalar compatibleAlpha = get_factor<ResScalar,RhsScalar>::run(actualAlpha); - ResScalar* actualDestPtr; - bool freeDestPtr = false; - if (evalToDest) - { - actualDestPtr = dest.data(); - } - else + ei_declare_aligned_stack_constructed_variable(ResScalar,actualDestPtr,dest.size(), + evalToDest ? dest.data() : static_dest.data()); + + if(!evalToDest) { #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN int size = dest.size(); EIGEN_DENSE_STORAGE_CTOR_PLUGIN #endif - if((actualDestPtr = static_dest.data())==0) - { - freeDestPtr = true; - actualDestPtr = ei_aligned_stack_new(ResScalar,dest.size()); - } if(!alphaIsCompatible) { MappedDest(actualDestPtr, dest.size()).setZero(); @@ -277,7 +263,6 @@ template<> struct trmv_selector<ColMajor> dest += actualAlpha * MappedDest(actualDestPtr, dest.size()); else dest = MappedDest(actualDestPtr, dest.size()); - if(freeDestPtr) ei_aligned_stack_delete(ResScalar, actualDestPtr, dest.size()); } } }; @@ -310,23 +295,15 @@ template<> struct trmv_selector<RowMajor> gemv_static_vector_if<RhsScalar,_ActualRhsType::SizeAtCompileTime,_ActualRhsType::MaxSizeAtCompileTime,!DirectlyUseRhs> static_rhs; - RhsScalar* actualRhsPtr; - bool freeRhsPtr = false; - if (DirectlyUseRhs) - { - actualRhsPtr = const_cast<RhsScalar*>(actualRhs.data()); - } - else + ei_declare_aligned_stack_constructed_variable(RhsScalar,actualRhsPtr,actualRhs.size(), + DirectlyUseRhs ? const_cast<RhsScalar*>(actualRhs.data()) : static_rhs.data()); + + if(!DirectlyUseRhs) { #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN int size = actualRhs.size(); EIGEN_DENSE_STORAGE_CTOR_PLUGIN #endif - if((actualRhsPtr = static_rhs.data())==0) - { - freeRhsPtr = true; - actualRhsPtr = ei_aligned_stack_new(RhsScalar, actualRhs.size()); - } Map<typename _ActualRhsType::PlainObject>(actualRhsPtr, actualRhs.size()) = actualRhs; } @@ -340,8 +317,6 @@ template<> struct trmv_selector<RowMajor> actualRhsPtr,1, dest.data(),dest.innerStride(), actualAlpha); - - if((!DirectlyUseRhs) && freeRhsPtr) ei_aligned_stack_delete(RhsScalar, actualRhsPtr, prod.rhs().size()); } }; diff --git a/Eigen/src/Core/products/TriangularSolverMatrix.h b/Eigen/src/Core/products/TriangularSolverMatrix.h index 8b9143c2b..a6ad9c322 100644 --- a/Eigen/src/Core/products/TriangularSolverMatrix.h +++ b/Eigen/src/Core/products/TriangularSolverMatrix.h @@ -70,10 +70,10 @@ struct triangular_solve_matrix<Scalar,Index,OnTheLeft,Mode,Conjugate,TriStorageO Index nc = cols; // cache block size along the N direction computeProductBlockingSizes<Scalar,Scalar,4>(kc, mc, nc); - Scalar* blockA = ei_aligned_stack_new(Scalar, kc*mc); std::size_t sizeW = kc*Traits::WorkSpaceFactor; std::size_t sizeB = sizeW + kc*cols; - Scalar* allocatedBlockB = ei_aligned_stack_new(Scalar, sizeB); + ei_declare_aligned_stack_constructed_variable(Scalar, blockA, kc*mc, 0); + ei_declare_aligned_stack_constructed_variable(Scalar, allocatedBlockB, sizeB, 0); Scalar* blockB = allocatedBlockB + sizeW; conj_if<Conjugate> conj; @@ -174,9 +174,6 @@ struct triangular_solve_matrix<Scalar,Index,OnTheLeft,Mode,Conjugate,TriStorageO } } } - - ei_aligned_stack_delete(Scalar, blockA, kc*mc); - ei_aligned_stack_delete(Scalar, allocatedBlockB, sizeB); } }; @@ -209,10 +206,10 @@ struct triangular_solve_matrix<Scalar,Index,OnTheRight,Mode,Conjugate,TriStorage Index nc = rows; // cache block size along the N direction computeProductBlockingSizes<Scalar,Scalar,4>(kc, mc, nc); - Scalar* blockA = ei_aligned_stack_new(Scalar, kc*mc); std::size_t sizeW = kc*Traits::WorkSpaceFactor; std::size_t sizeB = sizeW + kc*size; - Scalar* allocatedBlockB = ei_aligned_stack_new(Scalar, sizeB); + ei_declare_aligned_stack_constructed_variable(Scalar, blockA, kc*mc, 0); + ei_declare_aligned_stack_constructed_variable(Scalar, allocatedBlockB, sizeB, 0); Scalar* blockB = allocatedBlockB + sizeW; conj_if<Conjugate> conj; @@ -314,9 +311,6 @@ struct triangular_solve_matrix<Scalar,Index,OnTheRight,Mode,Conjugate,TriStorage -1, -1, 0, 0, allocatedBlockB); } } - - ei_aligned_stack_delete(Scalar, blockA, kc*mc); - ei_aligned_stack_delete(Scalar, allocatedBlockB, sizeB); } }; diff --git a/Eigen/src/Core/util/Memory.h b/Eigen/src/Core/util/Memory.h index 8ccf0e603..fe61555ff 100644 --- a/Eigen/src/Core/util/Memory.h +++ b/Eigen/src/Core/util/Memory.h @@ -468,36 +468,70 @@ inline static Index first_aligned(const Scalar* array, Index size) *** Implementation of runtime stack allocation (falling back to malloc) *** *****************************************************************************/ +// you can overwrite Eigen's default behavior regarding alloca by defining EIGEN_ALLOCA +// to the appropriate stack allocation function +#ifndef EIGEN_ALLOCA + #if (defined __linux__) + #define EIGEN_ALLOCA alloca + #elif defined(_MSC_VER) + #define EIGEN_ALLOCA _alloca + #endif +#endif + +namespace internal { + +template<typename T> class stack_memory_destructor +{ + public: + stack_memory_destructor(T* ptr,size_t size) : m_ptr(ptr), m_size(size) {} + ~stack_memory_destructor() + { + Eigen::internal::destruct_elements_of_array<T>(m_ptr, m_size); + #ifdef EIGEN_ALLOCA + if(sizeof(T)*m_size>EIGEN_STACK_ALLOCATION_LIMIT) + #endif + Eigen::internal::aligned_free(m_ptr); + } + protected: + T* m_ptr; + size_t m_size; +}; + +} + /** \internal - * Allocates an aligned buffer of SIZE bytes on the stack if SIZE is smaller than - * EIGEN_STACK_ALLOCATION_LIMIT, and if stack allocation is supported by the platform - * (currently, this is Linux only). Otherwise the memory is allocated on the heap. - * Data allocated with ei_aligned_stack_alloc \b must be freed by calling - * ei_aligned_stack_free(PTR,SIZE). + * Declares, allocates and construct an aligned buffer named NAME of SIZE elements of type TYPE on the stack + * if SIZE is smaller than EIGEN_STACK_ALLOCATION_LIMIT, and if stack allocation is supported by the platform + * (currently, this is Linux and Visual Studio only). Otherwise the memory is allocated on the heap. + * The allocated buffer is automatically deleted when exiting the scope of this declaration. + * If BUFFER is non nul, then the declared variable is simply an alias for BUFFER, and no allocation/deletion occurs. + * Here is an example: * \code - * float * data = ei_aligned_stack_alloc(float,array.size()); - * // ... - * ei_aligned_stack_free(data,float,array.size()); + * { + * ei_declare_aligned_stack_constructed_variable(float,data,size,0); + * // use data[0] to data[size-1] + * } * \endcode + * The underlying stack allocation function can controlled with the EIGEN_ALLOCA preprocessor token. */ -#if (defined __linux__) - #define ei_aligned_stack_alloc(SIZE) (SIZE<=EIGEN_STACK_ALLOCATION_LIMIT) \ - ? alloca(SIZE) \ - : Eigen::internal::aligned_malloc(SIZE) - #define ei_aligned_stack_free(PTR,SIZE) if(SIZE>EIGEN_STACK_ALLOCATION_LIMIT) Eigen::internal::aligned_free(PTR) -#elif defined(_MSC_VER) - #define ei_aligned_stack_alloc(SIZE) (SIZE<=EIGEN_STACK_ALLOCATION_LIMIT) \ - ? _alloca(SIZE) \ - : Eigen::internal::aligned_malloc(SIZE) - #define ei_aligned_stack_free(PTR,SIZE) if(SIZE>EIGEN_STACK_ALLOCATION_LIMIT) Eigen::internal::aligned_free(PTR) +#ifdef EIGEN_ALLOCA + + #define ei_declare_aligned_stack_constructed_variable(TYPE,NAME,SIZE,BUFFER) \ + TYPE* NAME = (BUFFER)!=0 ? (BUFFER) \ + : reinterpret_cast<TYPE*>( \ + (sizeof(TYPE)*SIZE<=EIGEN_STACK_ALLOCATION_LIMIT) ? alloca(sizeof(TYPE)*SIZE) \ + : Eigen::internal::aligned_malloc(sizeof(TYPE)*SIZE) ); \ + if((BUFFER)==0) Eigen::internal::construct_elements_of_array(NAME, SIZE); \ + Eigen::internal::stack_memory_destructor<TYPE> EIGEN_CAT(stack_memory_destructor,__LINE__)((BUFFER)==0 ? NAME : 0,SIZE) + #else - #define ei_aligned_stack_alloc(SIZE) Eigen::internal::aligned_malloc(SIZE) - #define ei_aligned_stack_free(PTR,SIZE) Eigen::internal::aligned_free(PTR) -#endif -#define ei_aligned_stack_new(TYPE,SIZE) Eigen::internal::construct_elements_of_array(reinterpret_cast<TYPE*>(ei_aligned_stack_alloc(sizeof(TYPE)*SIZE)), SIZE) -#define ei_aligned_stack_delete(TYPE,PTR,SIZE) do {Eigen::internal::destruct_elements_of_array<TYPE>(PTR, SIZE); \ - ei_aligned_stack_free(PTR,sizeof(TYPE)*SIZE);} while(0) + #define ei_declare_aligned_stack_constructed_variable(TYPE,NAME,SIZE,BUFFER) \ + TYPE* NAME = (BUFFER)!=0 ? BUFFER : reinterpret_cast<TYPE*>(Eigen::internal::aligned_malloc(sizeof(TYPE)*SIZE)); \ + if((BUFFER)==0) Eigen::internal::construct_elements_of_array(NAME, SIZE); \ + Eigen::internal::stack_memory_destructor<TYPE> EIGEN_CAT(stack_memory_destructor,__LINE__)((BUFFER)==0 ? NAME : 0,SIZE) + +#endif /***************************************************************************** |