LCOV - code coverage report
Current view: directory - js/src/assembler/assembler - AssemblerBuffer.h (source / functions) Found Hit Coverage
Test: app.info Lines: 67 56 83.6 %
Date: 2012-06-02 Functions: 13 13 100.0 %

       1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  * vim: set ts=8 sw=4 et tw=79:
       3                 :  *
       4                 :  * ***** BEGIN LICENSE BLOCK *****
       5                 :  * Copyright (C) 2008 Apple Inc. All rights reserved.
       6                 :  *
       7                 :  * Redistribution and use in source and binary forms, with or without
       8                 :  * modification, are permitted provided that the following conditions
       9                 :  * are met:
      10                 :  * 1. Redistributions of source code must retain the above copyright
      11                 :  *    notice, this list of conditions and the following disclaimer.
      12                 :  * 2. Redistributions in binary form must reproduce the above copyright
      13                 :  *    notice, this list of conditions and the following disclaimer in the
      14                 :  *    documentation and/or other materials provided with the distribution.
      15                 :  *
      16                 :  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
      17                 :  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      18                 :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      19                 :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
      20                 :  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
      21                 :  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
      22                 :  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
      23                 :  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
      24                 :  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      25                 :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      26                 :  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
      27                 :  * 
      28                 :  * ***** END LICENSE BLOCK ***** */
      29                 : 
      30                 : #ifndef AssemblerBuffer_h
      31                 : #define AssemblerBuffer_h
      32                 : 
      33                 : #include "assembler/wtf/Platform.h"
      34                 : 
      35                 : #if ENABLE_ASSEMBLER
      36                 : 
      37                 : #include <string.h>
      38                 : #include "assembler/jit/ExecutableAllocator.h"
      39                 : #include "assembler/wtf/Assertions.h"
      40                 : 
      41                 : namespace JSC {
      42                 : 
      43                 :     class AssemblerBuffer {
      44                 :         static const int inlineCapacity = 256;
      45                 :     public:
      46          763316 :         AssemblerBuffer()
      47                 :             : m_buffer(m_inlineBuffer)
      48                 :             , m_capacity(inlineCapacity)
      49                 :             , m_size(0)
      50          763316 :             , m_oom(false)
      51                 :         {
      52          763316 :         }
      53                 : 
      54          763316 :         ~AssemblerBuffer()
      55                 :         {
      56          763316 :             if (m_buffer != m_inlineBuffer)
      57          211480 :                 free(m_buffer);
      58          763316 :         }
      59                 : 
      60       125088467 :         void ensureSpace(int space)
      61                 :         {
      62       125088467 :             if (m_size > m_capacity - space)
      63          559435 :                 grow();
      64       125088467 :         }
      65                 : 
      66                 :         bool isAligned(int alignment) const
      67                 :         {
      68                 :             return !(m_size & (alignment - 1));
      69                 :         }
      70                 : 
      71       335874537 :         void putByteUnchecked(int value)
      72                 :         {
      73       335874537 :             ASSERT(!(m_size > m_capacity - 4));
      74       335874537 :             m_buffer[m_size] = char(value);
      75       335874537 :             m_size++;
      76       335874537 :         }
      77                 : 
      78         5075928 :         void putByte(int value)
      79                 :         {
      80         5075928 :             if (m_size > m_capacity - 4)
      81               0 :                 grow();
      82         5075928 :             putByteUnchecked(value);
      83         5075928 :         }
      84                 : 
      85             281 :         void putShortUnchecked(int value)
      86                 :         {
      87             281 :             ASSERT(!(m_size > m_capacity - 4));
      88             281 :             *reinterpret_cast<short*>(&m_buffer[m_size]) = short(value);
      89             281 :             m_size += 2;
      90             281 :         }
      91                 : 
      92                 :         void putShort(int value)
      93                 :         {
      94                 :             if (m_size > m_capacity - 4)
      95                 :                 grow();
      96                 :             putShortUnchecked(value);
      97                 :         }
      98                 : 
      99        51691586 :         void putIntUnchecked(int value)
     100                 :         {
     101        51691586 :             ASSERT(!(m_size > m_capacity - 4));
     102        51691586 :             *reinterpret_cast<int*>(&m_buffer[m_size]) = value;
     103        51691586 :             m_size += 4;
     104        51691586 :         }
     105                 : 
     106                 :         void putInt64Unchecked(int64_t value)
     107                 :         {
     108                 :             ASSERT(!(m_size > m_capacity - 8));
     109                 :             *reinterpret_cast<int64_t*>(&m_buffer[m_size]) = value;
     110                 :             m_size += 8;
     111                 :         }
     112                 : 
     113                 :         void putInt(int value)
     114                 :         {
     115                 :             if (m_size > m_capacity - 4)
     116                 :                 grow();
     117                 :             putIntUnchecked(value);
     118                 :         }
     119                 : 
     120         7602636 :         void* data() const
     121                 :         {
     122         7602636 :             return m_buffer;
     123                 :         }
     124                 : 
     125        83271500 :         int size() const
     126                 :         {
     127        83271500 :             return m_size;
     128                 :         }
     129                 : 
     130         2260344 :         bool oom() const
     131                 :         {
     132         2260344 :             return m_oom;
     133                 :         }
     134                 : 
     135                 :         /*
     136                 :          * The user must check for a NULL return value, which means
     137                 :          * no code was generated, or there was an OOM.
     138                 :          */
     139          373153 :         void* executableAllocAndCopy(ExecutableAllocator* allocator, ExecutablePool** poolp, CodeKind kind)
     140                 :         {
     141          373153 :             if (m_oom || m_size == 0) {
     142               0 :                 *poolp = NULL;
     143               0 :                 return 0;
     144                 :             }
     145                 : 
     146          373153 :             void* result = allocator->alloc(m_size, poolp, kind);
     147          373153 :             if (!result) {
     148               0 :                 *poolp = NULL;
     149               0 :                 return 0;
     150                 :             }
     151          373153 :             JS_ASSERT(*poolp);
     152                 : 
     153          373153 :             ExecutableAllocator::makeWritable(result, m_size);
     154                 : 
     155          373153 :             return memcpy(result, m_buffer, m_size);
     156                 :         }
     157                 : 
     158          257654 :         unsigned char *buffer() const {
     159          257654 :             ASSERT(!m_oom);
     160          257654 :             return reinterpret_cast<unsigned char *>(m_buffer);
     161                 :         }
     162                 : 
     163                 :     protected:
     164                 :         void append(const char* data, int size)
     165                 :         {
     166                 :             if (m_size > m_capacity - size)
     167                 :                 grow(size);
     168                 : 
     169                 :             // If we OOM and size > inlineCapacity, this would crash.
     170                 :             if (m_oom)
     171                 :                 return;
     172                 :             memcpy(m_buffer + m_size, data, size);
     173                 :             m_size += size;
     174                 :         }
     175                 : 
     176                 :         /*
     177                 :          * OOM handling: This class can OOM in the grow() method trying to
     178                 :          * allocate a new buffer. In response to an OOM, we need to avoid
     179                 :          * crashing and report the error. We also want to make it so that
     180                 :          * users of this class need to check for OOM only at certain points
     181                 :          * and not after every operation.
     182                 :          *
     183                 :          * Our strategy for handling an OOM is to set m_oom, and then set
     184                 :          * m_size to 0, preserving the current buffer. This way, the user
     185                 :          * can continue assembling into the buffer, deferring OOM checking
     186                 :          * until the user wants to read code out of the buffer.
     187                 :          *
     188                 :          * See also the |executableAllocAndCopy| and |buffer| methods.
     189                 :          */
     190                 : 
     191          559435 :         void grow(int extraCapacity = 0)
     192                 :         {
     193                 :             /*
     194                 :              * If |extraCapacity| is zero (as it almost always is) this is an
     195                 :              * allocator-friendly doubling growth strategy.
     196                 :              */
     197          559435 :             int newCapacity = m_capacity + m_capacity + extraCapacity;
     198                 :             char* newBuffer;
     199                 : 
     200          559435 :             if (m_buffer == m_inlineBuffer) {
     201          211480 :                 newBuffer = static_cast<char*>(malloc(newCapacity));
     202          211480 :                 if (!newBuffer) {
     203               0 :                     m_size = 0;
     204               0 :                     m_oom = true;
     205               0 :                     return;
     206                 :                 }
     207          211480 :                 memcpy(newBuffer, m_buffer, m_size);
     208                 :             } else {
     209          347955 :                 newBuffer = static_cast<char*>(realloc(m_buffer, newCapacity));
     210          347955 :                 if (!newBuffer) {
     211               0 :                     m_size = 0;
     212               0 :                     m_oom = true;
     213               0 :                     return;
     214                 :                 }
     215                 :             }
     216                 : 
     217          559435 :             m_buffer = newBuffer;
     218          559435 :             m_capacity = newCapacity;
     219                 :         }
     220                 : 
     221                 :         char m_inlineBuffer[inlineCapacity];
     222                 :         char* m_buffer;
     223                 :         int m_capacity;
     224                 :         int m_size;
     225                 :         bool m_oom;
     226                 :     };
     227                 : 
     228                 : } // namespace JSC
     229                 : 
     230                 : #endif // ENABLE(ASSEMBLER)
     231                 : 
     232                 : #endif // AssemblerBuffer_h

Generated by: LCOV version 1.7