From d9779adc025ab665fde1c9983e7793e96ab56d4e Mon Sep 17 00:00:00 2001 From: John Reck Date: Mon, 30 Jul 2012 16:45:46 -0700 Subject: Switch GraphicsOperation to LinearAllocator Change-Id: I9afb489c55a7acfdc35cfe8655d46ce47923b3df --- .../graphics/android/context/GraphicsOperation.cpp | 55 ++++++++++ .../graphics/android/context/GraphicsOperation.h | 18 ++-- .../context/PlatformGraphicsContextRecording.cpp | 112 +++++++++++++-------- .../context/PlatformGraphicsContextRecording.h | 4 + .../platform/graphics/android/context/RTree.cpp | 6 +- .../platform/graphics/android/context/RTree.h | 2 +- .../graphics/android/utils/LinearAllocator.cpp | 84 ++++++++++------ .../graphics/android/utils/LinearAllocator.h | 11 +- 8 files changed, 198 insertions(+), 94 deletions(-) create mode 100644 Source/WebCore/platform/graphics/android/context/GraphicsOperation.cpp (limited to 'Source/WebCore/platform/graphics') diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsOperation.cpp b/Source/WebCore/platform/graphics/android/context/GraphicsOperation.cpp new file mode 100644 index 0000000..ab6e676 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/context/GraphicsOperation.cpp @@ -0,0 +1,55 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#define LOG_TAG "GraphicsOperation" + +#include "config.h" +#include "GraphicsOperation.h" + +#include "AndroidLog.h" +#include "LinearAllocator.h" + +namespace WebCore { +namespace GraphicsOperation { + +void* Operation::operator new(size_t size, LinearAllocator* allocator) +{ + return allocator->alloc(size); +} + +void* Operation::operator new(size_t size) +{ + ALOGE("Cannot allocate a new Operation directly!"); + CRASH(); + return (void*) 0xBADBEEF; +} + +void Operation::operator delete(void*) +{ + ALOGE("Cannot call delete on an Operation!"); + CRASH(); +} + +} // namespace GraphicsOperation +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h b/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h index 604206b..4d2c634 100644 --- a/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h +++ b/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h @@ -45,6 +45,7 @@ namespace WebCore { class CanvasState; +class LinearAllocator; namespace GraphicsOperation { @@ -87,6 +88,12 @@ public: , m_canvasState(0) {} + void* operator new(size_t size, LinearAllocator* allocator); + + // Purposely not implemented - use a LinearAllocator please + void* operator new(size_t size); + void operator delete(void* ptr); + // This m_state is applied by ourselves PlatformGraphicsContext::State* m_state; // This is the canvas state that this operation needs @@ -102,7 +109,6 @@ public: virtual bool applyImpl(PlatformGraphicsContext* context) = 0; virtual ~Operation() {} virtual OperationType type() { return UndefinedOperation; } - virtual String parameters() { return ""; } virtual void subtractOpaqueClip(FloatRect& clip) {} const char* name() { @@ -220,11 +226,6 @@ public: return context->clip(m_rect); } virtual OperationType type() { return ClipOperation; } - virtual String parameters() { - return String::format("[x=%.2f,y=%.2f,w=%.2f,h=%.2f]", - m_rect.x(), m_rect.y(), - m_rect.width(), m_rect.height()); - } private: const FloatRect m_rect; }; @@ -305,11 +306,6 @@ public: return true; } virtual OperationType type() { return DrawBitmapRectOperation; } - virtual String parameters() { - return String::format("%.2f, %.2f - %.2f x %.2f", - m_dstR.fLeft, m_dstR.fTop, - m_dstR.width(), m_dstR.height()); - } private: SkBitmap m_bitmap; SkIRect m_srcR; diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp index a2163ce..42f8400 100644 --- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp +++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp @@ -35,6 +35,7 @@ #include "Font.h" #include "GraphicsContext.h" #include "GraphicsOperation.h" +#include "LinearAllocator.h" #include "PlatformGraphicsContextSkia.h" #include "RTree.h" @@ -42,6 +43,8 @@ #include "wtf/HashSet.h" #include "wtf/StringHasher.h" +#define NEW_OP(X) new (operationHeap()) GraphicsOperation::X + namespace WebCore { static FloatRect approximateTextBounds(size_t numGlyphs, @@ -164,6 +167,10 @@ public: return m_isTransparencyLayer; } + void* operator new(size_t size, LinearAllocator* la) { + return la->alloc(size); + } + private: CanvasState *m_parent; bool m_isTransparencyLayer; @@ -172,9 +179,18 @@ private: }; class RecordingImpl { +private: + // Careful, ordering matters here. Ordering is first constructed == last destroyed, + // so we have to make sure our Heap is the first thing listed so that it is + // the last thing destroyed. + LinearAllocator m_operationHeap; + LinearAllocator m_canvasStateHeap; + LinearAllocator m_stateHeap; public: RecordingImpl() - : m_nodeCount(0) + : m_canvasStateHeap(sizeof(CanvasState)) + , m_stateHeap(sizeof(PlatformGraphicsContext::State)) + , m_nodeCount(0) { } @@ -187,8 +203,8 @@ public: StateHashSet::iterator it = m_states.find(inState); if (it != m_states.end()) return (*it); - // TODO: Use a custom allocator - PlatformGraphicsContext::State* state = new PlatformGraphicsContext::State(*inState); + void* buf = m_stateHeap.alloc(sizeof(PlatformGraphicsContext::State)); + PlatformGraphicsContext::State* state = new (buf) PlatformGraphicsContext::State(*inState); m_states.add(state); return state; } @@ -236,6 +252,9 @@ public: toState->playback(context, fromId, toId); } + LinearAllocator* operationHeap() { return &m_operationHeap; } + LinearAllocator* canvasStateHeap() { return &m_canvasStateHeap; } + RTree::RTree m_tree; int m_nodeCount; @@ -244,13 +263,13 @@ private: void clearStates() { StateHashSet::iterator end = m_states.end(); for (StateHashSet::iterator it = m_states.begin(); it != end; ++it) - delete (*it); + (*it)->~State(); m_states.clear(); } void clearCanvasStates() { for (size_t i = 0; i < m_canvasStates.size(); i++) - delete m_canvasStates[i]; + m_canvasStates[i]->~CanvasState(); m_canvasStates.clear(); } @@ -299,7 +318,7 @@ void Recording::draw(SkCanvas* canvas) op->m_canvasState, nodes[i]->m_orderBy); currState = op->m_canvasState; lastOperationId = nodes[i]->m_orderBy; - ALOGV("apply: %p->%s(%s)", op, op->name(), op->parameters().ascii().data()); + ALOGV("apply: %p->%s()", op, op->name()); op->apply(&context); } while (currState) { @@ -338,7 +357,7 @@ PlatformGraphicsContextRecording::PlatformGraphicsContextRecording(Recording* re mRecording->setRecording(new RecordingImpl()); mMatrixStack.append(SkMatrix::I()); mCurrentMatrix = &(mMatrixStack.last()); - pushStateOperation(new CanvasState(0)); + pushStateOperation(new (canvasStateHeap()) CanvasState(0)); } bool PlatformGraphicsContextRecording::isPaintingDisabled() @@ -359,7 +378,7 @@ SkCanvas* PlatformGraphicsContextRecording::recordingCanvas() void PlatformGraphicsContextRecording::beginTransparencyLayer(float opacity) { CanvasState* parent = mRecordingStateStack.last().mCanvasState; - pushStateOperation(new CanvasState(parent, opacity)); + pushStateOperation(new (canvasStateHeap()) CanvasState(parent, opacity)); } void PlatformGraphicsContextRecording::endTransparencyLayer() @@ -371,7 +390,7 @@ void PlatformGraphicsContextRecording::save() { PlatformGraphicsContext::save(); CanvasState* parent = mRecordingStateStack.last().mCanvasState; - pushStateOperation(new CanvasState(parent)); + pushStateOperation(new (canvasStateHeap()) CanvasState(parent)); pushMatrix(); } @@ -490,26 +509,26 @@ void PlatformGraphicsContextRecording::setStrokeThickness(float f) void PlatformGraphicsContextRecording::concatCTM(const AffineTransform& affine) { mCurrentMatrix->preConcat(affine); - appendStateOperation(new GraphicsOperation::ConcatCTM(affine)); + appendStateOperation(NEW_OP(ConcatCTM)(affine)); } void PlatformGraphicsContextRecording::rotate(float angleInRadians) { float value = angleInRadians * (180.0f / 3.14159265f); mCurrentMatrix->preRotate(SkFloatToScalar(value)); - appendStateOperation(new GraphicsOperation::Rotate(angleInRadians)); + appendStateOperation(NEW_OP(Rotate)(angleInRadians)); } void PlatformGraphicsContextRecording::scale(const FloatSize& size) { mCurrentMatrix->preScale(SkFloatToScalar(size.width()), SkFloatToScalar(size.height())); - appendStateOperation(new GraphicsOperation::Scale(size)); + appendStateOperation(NEW_OP(Scale)(size)); } void PlatformGraphicsContextRecording::translate(float x, float y) { mCurrentMatrix->preTranslate(SkFloatToScalar(x), SkFloatToScalar(y)); - appendStateOperation(new GraphicsOperation::Translate(x, y)); + appendStateOperation(NEW_OP(Translate)(x, y)); } const SkMatrix& PlatformGraphicsContextRecording::getTotalMatrix() @@ -524,7 +543,7 @@ const SkMatrix& PlatformGraphicsContextRecording::getTotalMatrix() void PlatformGraphicsContextRecording::addInnerRoundedRectClip(const IntRect& rect, int thickness) { - appendStateOperation(new GraphicsOperation::InnerRoundedRectClip(rect, thickness)); + appendStateOperation(NEW_OP(InnerRoundedRectClip)(rect, thickness)); } void PlatformGraphicsContextRecording::canvasClip(const Path& path) @@ -535,14 +554,14 @@ void PlatformGraphicsContextRecording::canvasClip(const Path& path) bool PlatformGraphicsContextRecording::clip(const FloatRect& rect) { clipState(rect); - appendStateOperation(new GraphicsOperation::Clip(rect)); + appendStateOperation(NEW_OP(Clip)(rect)); return true; } bool PlatformGraphicsContextRecording::clip(const Path& path) { clipState(path.boundingRect()); - appendStateOperation(new GraphicsOperation::ClipPath(path)); + appendStateOperation(NEW_OP(ClipPath)(path)); return true; } @@ -555,20 +574,20 @@ bool PlatformGraphicsContextRecording::clipConvexPolygon(size_t numPoints, bool PlatformGraphicsContextRecording::clipOut(const IntRect& r) { - appendStateOperation(new GraphicsOperation::ClipOut(r)); + appendStateOperation(NEW_OP(ClipOut)(r)); return true; } bool PlatformGraphicsContextRecording::clipOut(const Path& path) { - appendStateOperation(new GraphicsOperation::ClipPath(path, true)); + appendStateOperation(NEW_OP(ClipPath)(path, true)); return true; } bool PlatformGraphicsContextRecording::clipPath(const Path& pathToClip, WindRule clipRule) { clipState(pathToClip.boundingRect()); - GraphicsOperation::ClipPath* operation = new GraphicsOperation::ClipPath(pathToClip); + GraphicsOperation::ClipPath* operation = NEW_OP(ClipPath)(pathToClip); operation->setWindRule(clipRule); appendStateOperation(operation); return true; @@ -576,7 +595,7 @@ bool PlatformGraphicsContextRecording::clipPath(const Path& pathToClip, WindRule void PlatformGraphicsContextRecording::clearRect(const FloatRect& rect) { - appendDrawingOperation(new GraphicsOperation::ClearRect(rect), rect); + appendDrawingOperation(NEW_OP(ClearRect)(rect), rect); } //************************************** @@ -588,7 +607,7 @@ void PlatformGraphicsContextRecording::drawBitmapPattern( CompositeOperator compositeOp, const FloatRect& destRect) { appendDrawingOperation( - new GraphicsOperation::DrawBitmapPattern(bitmap, matrix, compositeOp, destRect), + NEW_OP(DrawBitmapPattern)(bitmap, matrix, compositeOp, destRect), destRect); } @@ -596,7 +615,7 @@ void PlatformGraphicsContextRecording::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, const SkRect& dst, CompositeOperator op) { - appendDrawingOperation(new GraphicsOperation::DrawBitmapRect(bitmap, *src, dst, op), dst); + appendDrawingOperation(NEW_OP(DrawBitmapRect)(bitmap, *src, dst, op), dst); } void PlatformGraphicsContextRecording::drawConvexPolygon(size_t numPoints, @@ -611,12 +630,12 @@ void PlatformGraphicsContextRecording::drawConvexPolygon(size_t numPoints, } FloatRect bounds; bounds.fitToPoints(points[0], points[1], points[2], points[3]); - appendDrawingOperation(new GraphicsOperation::DrawConvexPolygonQuad(points, shouldAntialias), bounds); + appendDrawingOperation(NEW_OP(DrawConvexPolygonQuad)(points, shouldAntialias), bounds); } void PlatformGraphicsContextRecording::drawEllipse(const IntRect& rect) { - appendDrawingOperation(new GraphicsOperation::DrawEllipse(rect), rect); + appendDrawingOperation(NEW_OP(DrawEllipse)(rect), rect); } void PlatformGraphicsContextRecording::drawFocusRing(const Vector& rects, @@ -628,7 +647,7 @@ void PlatformGraphicsContextRecording::drawFocusRing(const Vector& rect IntRect bounds = rects[0]; for (size_t i = 1; i < rects.size(); i++) bounds.unite(rects[i]); - appendDrawingOperation(new GraphicsOperation::DrawFocusRing(rects, width, offset, color), bounds); + appendDrawingOperation(NEW_OP(DrawFocusRing)(rects, width, offset, color), bounds); } void PlatformGraphicsContextRecording::drawHighlightForText( @@ -657,41 +676,41 @@ void PlatformGraphicsContextRecording::drawLine(const IntPoint& point1, float width = m_state->strokeThickness; if (!width) width = 1; bounds.inflate(width); - appendDrawingOperation(new GraphicsOperation::DrawLine(point1, point2), bounds); + appendDrawingOperation(NEW_OP(DrawLine)(point1, point2), bounds); } void PlatformGraphicsContextRecording::drawLineForText(const FloatPoint& pt, float width) { FloatRect bounds(pt.x(), pt.y(), width, m_state->strokeThickness); - appendDrawingOperation(new GraphicsOperation::DrawLineForText(pt, width), bounds); + appendDrawingOperation(NEW_OP(DrawLineForText)(pt, width), bounds); } void PlatformGraphicsContextRecording::drawLineForTextChecking(const FloatPoint& pt, float width, GraphicsContext::TextCheckingLineStyle lineStyle) { FloatRect bounds(pt.x(), pt.y(), width, m_state->strokeThickness); - appendDrawingOperation(new GraphicsOperation::DrawLineForTextChecking(pt, width, lineStyle), bounds); + appendDrawingOperation(NEW_OP(DrawLineForTextChecking)(pt, width, lineStyle), bounds); } void PlatformGraphicsContextRecording::drawRect(const IntRect& rect) { - appendDrawingOperation(new GraphicsOperation::DrawRect(rect), rect); + appendDrawingOperation(NEW_OP(DrawRect)(rect), rect); } void PlatformGraphicsContextRecording::fillPath(const Path& pathToFill, WindRule fillRule) { - appendDrawingOperation(new GraphicsOperation::FillPath(pathToFill, fillRule), pathToFill.boundingRect()); + appendDrawingOperation(NEW_OP(FillPath)(pathToFill, fillRule), pathToFill.boundingRect()); } void PlatformGraphicsContextRecording::fillRect(const FloatRect& rect) { - appendDrawingOperation(new GraphicsOperation::FillRect(rect), rect); + appendDrawingOperation(NEW_OP(FillRect)(rect), rect); } void PlatformGraphicsContextRecording::fillRect(const FloatRect& rect, const Color& color) { - GraphicsOperation::FillRect* operation = new GraphicsOperation::FillRect(rect); + GraphicsOperation::FillRect* operation = NEW_OP(FillRect)(rect); operation->setColor(color); appendDrawingOperation(operation, rect); } @@ -701,26 +720,26 @@ void PlatformGraphicsContextRecording::fillRoundedRect( const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color) { - appendDrawingOperation(new GraphicsOperation::FillRoundedRect(rect, topLeft, + appendDrawingOperation(NEW_OP(FillRoundedRect)(rect, topLeft, topRight, bottomLeft, bottomRight, color), rect); } void PlatformGraphicsContextRecording::strokeArc(const IntRect& r, int startAngle, int angleSpan) { - appendDrawingOperation(new GraphicsOperation::StrokeArc(r, startAngle, angleSpan), r); + appendDrawingOperation(NEW_OP(StrokeArc)(r, startAngle, angleSpan), r); } void PlatformGraphicsContextRecording::strokePath(const Path& pathToStroke) { - appendDrawingOperation(new GraphicsOperation::StrokePath(pathToStroke), pathToStroke.boundingRect()); + appendDrawingOperation(NEW_OP(StrokePath)(pathToStroke), pathToStroke.boundingRect()); } void PlatformGraphicsContextRecording::strokeRect(const FloatRect& rect, float lineWidth) { FloatRect bounds = rect; bounds.inflate(lineWidth); - appendDrawingOperation(new GraphicsOperation::StrokeRect(rect, lineWidth), bounds); + appendDrawingOperation(NEW_OP(StrokeRect)(rect, lineWidth), bounds); } void PlatformGraphicsContextRecording::drawPosText(const void* text, size_t byteLength, @@ -730,7 +749,7 @@ void PlatformGraphicsContextRecording::drawPosText(const void* text, size_t byte ALOGE("Unsupported text encoding! %d", paint.getTextEncoding()); } FloatRect bounds = approximateTextBounds(byteLength / sizeof(uint16_t), pos, paint); - appendDrawingOperation(new GraphicsOperation::DrawPosText(text, byteLength, pos, paint), bounds); + appendDrawingOperation(NEW_OP(DrawPosText)(text, byteLength, pos, paint), bounds); } void PlatformGraphicsContextRecording::clipState(const FloatRect& clip) @@ -757,7 +776,8 @@ void PlatformGraphicsContextRecording::popStateOperation() ALOGV("popStateOperation is deleting %p(isLayer=%d)", state.mCanvasState, state.mCanvasState->isTransparencyLayer()); mRecording->recording()->removeCanvasState(state.mCanvasState); - delete state.mCanvasState; + state.mCanvasState->~CanvasState(); + canvasStateHeap()->rewindTo(state.mCanvasState); } else { ALOGV("popStateOperation: %p(isLayer=%d)", state.mCanvasState, state.mCanvasState->isTransparencyLayer()); @@ -824,9 +844,9 @@ void PlatformGraphicsContextRecording::appendDrawingOperation( WebCore::IntRect ibounds = calculateFinalBounds(untranslatedBounds); if (ibounds.isEmpty()) { - ALOGV("Operation %s(%s) was clipped out", operation->name(), - operation->parameters().ascii().data()); - delete operation; + ALOGV("Operation %s() was clipped out", operation->name()); + operation->~Operation(); + operationHeap()->rewindTo(operation); return; } ALOGV("appendOperation %p->%s()", operation, operation->name()); @@ -842,4 +862,14 @@ void PlatformGraphicsContextRecording::appendStateOperation(GraphicsOperation::O mRecordingStateStack.last().mCanvasState->adoptAndAppend(data); } +LinearAllocator* PlatformGraphicsContextRecording::operationHeap() +{ + return mRecording->recording()->operationHeap(); +} + +LinearAllocator* PlatformGraphicsContextRecording::canvasStateHeap() +{ + return mRecording->recording()->canvasStateHeap(); +} + } // WebCore diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h index 3af1e2f..991e13f 100644 --- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h +++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h @@ -37,7 +37,9 @@ class Operation; } class CanvasState; +class LinearAllocator; class RecordingImpl; + class Recording : public SkRefCnt { public: Recording() @@ -152,6 +154,8 @@ private: void pushMatrix(); void popMatrix(); IntRect calculateFinalBounds(FloatRect bounds); + LinearAllocator* operationHeap(); + LinearAllocator* canvasStateHeap(); SkPicture* mPicture; SkMatrix* mCurrentMatrix; diff --git a/Source/WebCore/platform/graphics/android/context/RTree.cpp b/Source/WebCore/platform/graphics/android/context/RTree.cpp index c6b9854..9512ffe 100644 --- a/Source/WebCore/platform/graphics/android/context/RTree.cpp +++ b/Source/WebCore/platform/graphics/android/context/RTree.cpp @@ -166,15 +166,13 @@ void RTree::display() void* RTree::allocateNode() { - return m_allocator->alloc(); + return m_allocator->alloc(sizeof(Node)); } void RTree::deleteNode(Node* n) { - if (n) { + if (n) n->~Node(); - m_allocator->dealloc(n); - } } ////////////////////////////////////////////////////////////////////// diff --git a/Source/WebCore/platform/graphics/android/context/RTree.h b/Source/WebCore/platform/graphics/android/context/RTree.h index 4ad8986..2a460d6 100644 --- a/Source/WebCore/platform/graphics/android/context/RTree.h +++ b/Source/WebCore/platform/graphics/android/context/RTree.h @@ -41,7 +41,7 @@ public: , m_operation(ops) {} ~RecordingData() { - delete m_operation; + m_operation->~Operation(); } size_t m_orderBy; diff --git a/Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp b/Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp index e7617b1..1899557 100644 --- a/Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp +++ b/Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp @@ -27,7 +27,6 @@ #define LOG_NDEBUG 1 #include "config.h" - #include "LinearAllocator.h" #include "AndroidLog.h" @@ -40,6 +39,33 @@ namespace WebCore { // our pool needs to big enough to hold at least this many items #define MIN_OBJECT_COUNT 4 +#if LOG_NDEBUG +#define ADD_ALLOCATION(size) +#define RM_ALLOCATION(size) +#else +#include +static size_t s_totalAllocations = 0; +static double s_lastLogged = 0; +static android::Mutex s_mutex; + +static void _logUsageLocked() { + double now = currentTimeMS(); + if (now - s_lastLogged > 5) { + s_lastLogged = now; + ALOGV("Total memory usage: %d kb", s_totalAllocations / 1024); + } +} + +static void _addAllocation(size_t size) { + android::AutoMutex lock(s_mutex); + s_totalAllocations += size; + _logUsageLocked(); +} + +#define ADD_ALLOCATION(size) _addAllocation(size); +#define RM_ALLOCATION(size) _addAllocation(-size); +#endif + class LinearAllocator::Page { public: Page* next() { return m_nextPage; } @@ -64,30 +90,29 @@ private: Page* m_nextPage; }; -LinearAllocator::LinearAllocator(size_t allocSize) - : m_allocSize(allocSize) - , m_allocCount(0) - , m_next(0) +LinearAllocator::LinearAllocator(size_t averageAllocSize) + : m_next(0) , m_currentPage(0) , m_pages(0) { - int usable_page_size = TARGET_PAGE_SIZE - sizeof(LinearAllocator::Page); - int pcount = usable_page_size / allocSize; - if (pcount < MIN_OBJECT_COUNT) - pcount = MIN_OBJECT_COUNT; - m_pageSize = pcount * allocSize + sizeof(LinearAllocator::Page); + if (averageAllocSize) { + int usable_page_size = TARGET_PAGE_SIZE - sizeof(LinearAllocator::Page); + int pcount = usable_page_size / averageAllocSize; + if (pcount < MIN_OBJECT_COUNT) + pcount = MIN_OBJECT_COUNT; + m_pageSize = pcount * averageAllocSize + sizeof(LinearAllocator::Page); + } else + m_pageSize = TARGET_PAGE_SIZE; + m_maxAllocSize = (m_pageSize - sizeof(LinearAllocator::Page)); } LinearAllocator::~LinearAllocator(void) { - if (m_allocCount) - ALOGW("Leaked allocations!"); - IF_ALOGV() - ALOGV("Freeing to %dkb", memusage() >> 10); Page* p = m_pages; while (p) { Page* next = p->next(); delete p; + RM_ALLOCATION(m_pageSize); p = next; } } @@ -102,9 +127,9 @@ void* LinearAllocator::end(Page* p) return ((char*)p) + m_pageSize; } -void LinearAllocator::ensureNext() +void LinearAllocator::ensureNext(size_t size) { - if (m_next && m_next < end(m_currentPage)) + if (m_next && ((char*)m_next + size) <= end(m_currentPage)) return; Page* p = newPage(); if (m_currentPage) @@ -113,9 +138,6 @@ void LinearAllocator::ensureNext() if (!m_pages) m_pages = m_currentPage; m_next = start(m_currentPage); - - IF_ALOGV() - ALOGV("Allocator grew to %dkb", memusage() >> 10); } unsigned LinearAllocator::memusage() @@ -129,28 +151,28 @@ unsigned LinearAllocator::memusage() return memusage; } -void* LinearAllocator::alloc() +void* LinearAllocator::alloc(size_t size) { - m_allocCount++; - ensureNext(); + if (size > m_maxAllocSize) { + ALOGE("Allocation too large! (%d exceeds max size %d)", size, m_maxAllocSize); + return 0; + } + ensureNext(size); void* ptr = m_next; - m_next = ((char*)m_next) + m_allocSize; + m_next = ((char*)m_next) + size; return ptr; } -void LinearAllocator::dealloc(void* ptr) +void LinearAllocator::rewindTo(void* ptr) { - m_allocCount--; - if (m_next > start(m_currentPage)) { - // If this happened to be the previous allocation, just rewind m_next - void* prev = ((char*)m_next) - m_allocSize; - if (ptr == prev) - m_next = prev; - } + // Don't bother rewinding across pages + if (ptr >= start(m_currentPage) && ptr < end(m_currentPage)) + m_next = ptr; } LinearAllocator::Page* LinearAllocator::newPage() { + ADD_ALLOCATION(m_pageSize); void* buf = malloc(m_pageSize); return new (buf) Page(); } diff --git a/Source/WebCore/platform/graphics/android/utils/LinearAllocator.h b/Source/WebCore/platform/graphics/android/utils/LinearAllocator.h index b0c584b..1f3265c 100644 --- a/Source/WebCore/platform/graphics/android/utils/LinearAllocator.h +++ b/Source/WebCore/platform/graphics/android/utils/LinearAllocator.h @@ -31,11 +31,11 @@ namespace WebCore { class LinearAllocator { public: - LinearAllocator(size_t allocSize); + LinearAllocator(size_t averageAllocSize = 0); ~LinearAllocator(); - void* alloc(); - void dealloc(void*); + void* alloc(size_t size); + void rewindTo(void*); private: LinearAllocator(const LinearAllocator& other); @@ -43,15 +43,14 @@ private: class Page; Page* newPage(); - void ensureNext(); + void ensureNext(size_t size); void* start(Page *p); void* end(Page* p); unsigned memusage(); - size_t m_allocSize; - size_t m_allocCount; size_t m_pageSize; + size_t m_maxAllocSize; void* m_next; Page* m_currentPage; Page* m_pages; -- cgit v1.1