From 86a864f906d7dcda1b1ab04d1e25e7020a53be64 Mon Sep 17 00:00:00 2001
From: Kent Hansen <kent.hansen@nokia.com>
Date: Tue, 25 Jan 2011 17:06:16 +0100
Subject: QtScript/JSC on Symbian: Enhanced memory allocator for Collector heap

Cherry-picked from http://trac.webkit.org/changeset/56370

The old allocator caused QML to crash in MCL (TB10.1, week 1).

Task-number: QTBUG-14293
Reviewed-by: Simon Hausmann
---
 .../javascriptcore/JavaScriptCore/ChangeLog        |  28 +++++
 .../JavaScriptCore/JavaScriptCore.pri              |   3 +
 .../JavaScriptCore/runtime/Collector.cpp           |  46 ++-----
 .../JavaScriptCore/runtime/Collector.h             |   9 ++
 .../wtf/symbian/BlockAllocatorSymbian.cpp          | 132 +++++++++++++++++++++
 .../wtf/symbian/BlockAllocatorSymbian.h            | 120 +++++++++++++++++++
 src/3rdparty/javascriptcore/VERSION                |   4 +-
 src/script/script.pro                              |   1 -
 8 files changed, 303 insertions(+), 40 deletions(-)
 create mode 100644 src/3rdparty/javascriptcore/JavaScriptCore/wtf/symbian/BlockAllocatorSymbian.cpp
 create mode 100644 src/3rdparty/javascriptcore/JavaScriptCore/wtf/symbian/BlockAllocatorSymbian.h

diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/ChangeLog b/src/3rdparty/javascriptcore/JavaScriptCore/ChangeLog
index fd6c3f7..c2b1155 100644
--- a/src/3rdparty/javascriptcore/JavaScriptCore/ChangeLog
+++ b/src/3rdparty/javascriptcore/JavaScriptCore/ChangeLog
@@ -232,6 +232,34 @@
         without using doubles, but the code would be much more complicated, and there is no important
         reason to stick to integers here.
 
+2010-03-22  Siddharth Mathur  <siddharth.mathur@nokia.com>
+
+        Reviewed by Laszlo Gombos.
+
+        [Symbian] More efficient aligned memory allocation for JSC Collector
+        https://bugs.webkit.org/show_bug.cgi?id=34350
+
+        * JavaScriptCore.pri: Added 2 new Symbian source files and HAL linkage
+
+        * runtime/Collector.cpp: Reduced port-specific code and added private data member
+        (JSC::Heap::Heap):
+        (JSC::Heap::~Heap):
+        (JSC::Heap::destroy):
+        (JSC::Heap::allocateBlock):
+        (JSC::Heap::freeBlockPtr):
+
+        * runtime/Collector.h: Added private data member
+
+        * wtf/symbian: Added.
+        * wtf/symbian/BlockAllocatorSymbian.cpp: Added.
+        (WTF::AlignedBlockAllocator::AlignedBlockAllocator): Helper class to allocate 
+        aligned blocks more efficiently as required by Collector
+        (WTF::AlignedBlockAllocator::alloc):
+        (WTF::AlignedBlockAllocator::free):
+        (WTF::AlignedBlockAllocator::destroy):
+        (WTF::AlignedBlockAllocator::~AlignedBlockAllocator):
+        * wtf/symbian/BlockAllocatorSymbian.h: Added.
+
 2010-03-22  Geoffrey Garen  <ggaren@apple.com>
 
         Reviewed by Sam Weinig.
diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/JavaScriptCore.pri b/src/3rdparty/javascriptcore/JavaScriptCore/JavaScriptCore.pri
index d75bd31..b061321 100644
--- a/src/3rdparty/javascriptcore/JavaScriptCore/JavaScriptCore.pri
+++ b/src/3rdparty/javascriptcore/JavaScriptCore/JavaScriptCore.pri
@@ -16,6 +16,7 @@ CONFIG(debug, debug|release) {
 symbian: {
     # Need to guarantee this comes before system includes of /epoc32/include
     MMP_RULES += "USERINCLUDE ../JavaScriptCore/profiler"
+    LIBS += -lhal
 }
 
 INCLUDEPATH = \
@@ -33,6 +34,7 @@ INCLUDEPATH = \
     $$PWD/runtime \
     $$PWD/wrec \
     $$PWD/wtf \
+    $$PWD/wtf/symbian \
     $$PWD/wtf/unicode \
     $$PWD/yarr \
     $$PWD/API \
@@ -211,6 +213,7 @@ SOURCES += \
     wtf/qt/ThreadingQt.cpp \
     wtf/RandomNumber.cpp \
     wtf/RefCountedLeakCounter.cpp \
+    wtf/symbian/BlockAllocatorSymbian.cpp \
     wtf/symbian/RegisterFileAllocatorSymbian.cpp \
     wtf/ThreadingNone.cpp \
     wtf/Threading.cpp \
diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.cpp
index 24873c8..42e2a35 100644
--- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.cpp
+++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.cpp
@@ -53,11 +53,6 @@
 #include <mach/thread_act.h>
 #include <mach/vm_map.h>
 
-#elif OS(SYMBIAN)
-#include <e32std.h>
-#include <e32cmn.h>
-#include <unistd.h>
-
 #elif OS(WINDOWS)
 
 #include <windows.h>
@@ -109,11 +104,6 @@ const size_t ALLOCATIONS_PER_COLLECTION = 3600;
 // a PIC branch in Mach-O binaries, see <rdar://problem/5971391>.
 #define MIN_ARRAY_SIZE (static_cast<size_t>(14))
 
-#if OS(SYMBIAN)
-const size_t MAX_NUM_BLOCKS = 256; // Max size of collector heap set to 16 MB
-static RHeap* userChunk = 0;
-#endif
-
 #if ENABLE(JSC_MULTIPLE_THREADS)
 
 #if OS(DARWIN)
@@ -146,29 +136,11 @@ Heap::Heap(JSGlobalData* globalData)
     , m_currentThreadRegistrar(0)
 #endif
     , m_globalData(globalData)
+#if OS(SYMBIAN)
+    , m_blockallocator(JSCCOLLECTOR_VIRTUALMEM_RESERVATION, BLOCK_SIZE)
+#endif
 {
     ASSERT(globalData);
-    
-#if OS(SYMBIAN)
-    // Symbian OpenC supports mmap but currently not the MAP_ANON flag.
-    // Using fastMalloc() does not properly align blocks on 64k boundaries
-    // and previous implementation was flawed/incomplete.
-    // UserHeap::ChunkHeap allows allocation of continuous memory and specification
-    // of alignment value for (symbian) cells within that heap.
-    //
-    // Clarification and mapping of terminology:
-    // RHeap (created by UserHeap::ChunkHeap below) is continuos memory chunk,
-    // which can dynamically grow up to 8 MB,
-    // that holds all CollectorBlocks of this session (static).
-    // Each symbian cell within RHeap maps to a 64kb aligned CollectorBlock.
-    // JSCell objects are maintained as usual within CollectorBlocks.
-    if (!userChunk) {
-        userChunk = UserHeap::ChunkHeap(0, 0, MAX_NUM_BLOCKS * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
-        if (!userChunk)
-            CRASH();
-    }
-#endif // OS(SYMBIAN)
-    
     memset(&m_heap, 0, sizeof(CollectorHeap));
     allocateBlock();
 }
@@ -211,7 +183,9 @@ void Heap::destroy()
         t = next;
     }
 #endif
-
+#if OS(SYMBIAN)
+    m_blockallocator.destroy();
+#endif
     m_globalData = 0;
 }
 
@@ -221,11 +195,9 @@ NEVER_INLINE CollectorBlock* Heap::allocateBlock()
     vm_address_t address = 0;
     vm_map(current_task(), &address, BLOCK_SIZE, BLOCK_OFFSET_MASK, VM_FLAGS_ANYWHERE | VM_TAG_FOR_COLLECTOR_MEMORY, MEMORY_OBJECT_NULL, 0, FALSE, VM_PROT_DEFAULT, VM_PROT_DEFAULT, VM_INHERIT_DEFAULT);
 #elif OS(SYMBIAN)
-    // Allocate a 64 kb aligned CollectorBlock
-    unsigned char* mask = reinterpret_cast<unsigned char*>(userChunk->Alloc(BLOCK_SIZE));
-    if (!mask)
+    void* address = m_blockallocator.alloc();  
+    if (!address)
         CRASH();
-    uintptr_t address = reinterpret_cast<uintptr_t>(mask);
 #elif OS(WINCE)
     void* address = VirtualAlloc(NULL, BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
 #elif OS(WINDOWS)
@@ -316,7 +288,7 @@ NEVER_INLINE void Heap::freeBlockPtr(CollectorBlock* block)
 #if OS(DARWIN)    
     vm_deallocate(current_task(), reinterpret_cast<vm_address_t>(block), BLOCK_SIZE);
 #elif OS(SYMBIAN)
-    userChunk->Free(reinterpret_cast<TAny*>(block));
+    m_blockallocator.free(reinterpret_cast<void*>(block));
 #elif OS(WINCE)
     VirtualFree(block, 0, MEM_RELEASE);
 #elif OS(WINDOWS)
diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.h
index 7f7a679..d3616dc 100644
--- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.h
+++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.h
@@ -35,6 +35,10 @@
 #include <pthread.h>
 #endif
 
+#if OS(SYMBIAN)
+#include <wtf/symbian/BlockAllocatorSymbian.h>
+#endif
+
 #define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) <= CELL_SIZE, class_fits_in_cell)
 
 namespace JSC {
@@ -167,6 +171,11 @@ namespace JSC {
         pthread_key_t m_currentThreadRegistrar;
 #endif
 
+#if OS(SYMBIAN)
+        // Allocates collector blocks with correct alignment
+        WTF::AlignedBlockAllocator m_blockallocator; 
+#endif
+        
         JSGlobalData* m_globalData;
     };
 
diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/symbian/BlockAllocatorSymbian.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/symbian/BlockAllocatorSymbian.cpp
new file mode 100644
index 0000000..6a28e9e
--- /dev/null
+++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/symbian/BlockAllocatorSymbian.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  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. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 APPLE OR ITS 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.
+ */
+
+#include "config.h"
+
+#if OS(SYMBIAN)
+
+#include "BlockAllocatorSymbian.h"
+
+
+namespace WTF {
+
+/** Efficiently allocates blocks of size blockSize with blockSize alignment. 
+ * Primarly designed for JSC Collector's needs. 
+ * Not thread-safe.    
+ */
+AlignedBlockAllocator::AlignedBlockAllocator(TUint32 reservationSize, TUint32 blockSize )
+    : m_reservation(reservationSize), 
+      m_blockSize(blockSize)
+{
+
+     // Get system's page size value.
+     SYMBIAN_PAGESIZE(m_pageSize); 
+     
+     // We only accept multiples of system page size for both initial reservation and the alignment/block size
+     m_reservation = SYMBIAN_ROUNDUPTOMULTIPLE(m_reservation, m_pageSize);
+     __ASSERT_ALWAYS(SYMBIAN_ROUNDUPTOMULTIPLE(m_blockSize, m_pageSize), User::Panic(_L("AlignedBlockAllocator1"), KErrArgument));
+     
+     // Calculate max. bit flags we need to carve a reservationSize range into blockSize-sized blocks
+     m_map.numBits = m_reservation / m_blockSize;   
+     const TUint32 bitsPerWord = 8*sizeof(TUint32); 
+     const TUint32 numWords = (m_map.numBits + bitsPerWord -1) / bitsPerWord; 
+   
+     m_map.bits = new TUint32[numWords];
+     __ASSERT_ALWAYS(m_map.bits, User::Panic(_L("AlignedBlockAllocator2"), KErrNoMemory));
+     m_map.clearAll();
+     
+     // Open a Symbian RChunk, and reserve requested virtual address range   
+     // Any thread in this process can operate this rchunk due to EOwnerProcess access rights. 
+     TInt ret = m_chunk.CreateDisconnectedLocal(0 , 0, (TInt)m_reservation , EOwnerProcess);  
+     if (ret != KErrNone) 
+         User::Panic(_L("AlignedBlockAllocator3"), ret);
+       
+     // This is the offset to m_chunk.Base() required to make it m_blockSize-aligned
+     m_offset = SYMBIAN_ROUNDUPTOMULTIPLE(TUint32(m_chunk.Base()), m_blockSize) - TUint(m_chunk.Base()); 
+
+}
+
+void* AlignedBlockAllocator::alloc()
+{
+
+    TInt  freeRam = 0; 
+    void* address = 0;
+    
+    // Look up first free slot in bit map
+    const TInt freeIdx = m_map.findFree();
+        
+    // Pseudo OOM: We ate up the address space we reserved..
+    // ..even though the device may have free RAM left
+    if (freeIdx < 0)
+        return 0;
+        
+    TInt ret = m_chunk.Commit(m_offset + (m_blockSize * freeIdx), m_blockSize);
+    if (ret != KErrNone)  
+        return 0; // True OOM: Device didn't have physical RAM to spare
+        
+    // Updated bit to mark region as in use. 
+    m_map.set(freeIdx); 
+    
+    // Calculate address of committed region (block)
+    address = (void*)( (m_chunk.Base() + m_offset) + (TUint)(m_blockSize * freeIdx) );
+    
+    return address;
+}
+
+void AlignedBlockAllocator::free(void* block)
+{
+    // Calculate index of block to be freed
+    TInt idx = TUint(static_cast<TUint8*>(block) - m_chunk.Base() - m_offset) / m_blockSize;
+    
+    __ASSERT_DEBUG(idx >= 0 && idx < m_map.numBits, User::Panic(_L("AlignedBlockAllocator4"), KErrCorrupt)); // valid index check
+    __ASSERT_DEBUG(m_map.get(idx), User::Panic(_L("AlignedBlockAllocator5"), KErrCorrupt)); // in-use flag check    
+    
+    // Return committed region to system RAM pool (the physical RAM becomes usable by others)
+    TInt ret = m_chunk.Decommit(m_offset + m_blockSize * idx, m_blockSize);
+            
+    // mark this available again
+    m_map.clear(idx); 
+}
+
+void AlignedBlockAllocator::destroy() 
+{
+    // release everything!
+    m_chunk.Decommit(0, m_chunk.MaxSize());
+    m_map.clearAll();
+}
+
+AlignedBlockAllocator::~AlignedBlockAllocator()
+{
+    destroy();
+    m_chunk.Close();
+    delete [] m_map.bits;
+}
+
+} // end of namespace
+
+#endif // SYMBIAN
diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/symbian/BlockAllocatorSymbian.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/symbian/BlockAllocatorSymbian.h
new file mode 100644
index 0000000..21422f6
--- /dev/null
+++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/symbian/BlockAllocatorSymbian.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  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. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 APPLE OR ITS 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.
+ */
+
+#ifndef BlockAllocatorSymbian_h
+#define BlockAllocatorSymbian_h
+
+#include <e32cmn.h>
+#include <e32std.h>
+#include <hal.h>
+
+
+#define SYMBIAN_PAGESIZE(x) (HAL::Get(HALData::EMemoryPageSize, x));
+#define SYMBIAN_FREERAM(x)  (HAL::Get(HALData::EMemoryRAMFree, x));
+#define SYMBIAN_ROUNDUPTOMULTIPLE(x, multipleof)    ( (x + multipleof - 1) & ~(multipleof - 1) )
+
+// Set sane defaults if -D<flagname=value> wasn't provided via compiler args
+#ifndef JSCCOLLECTOR_VIRTUALMEM_RESERVATION
+#if defined(__WINS__) 
+    // Emulator has limited virtual address space
+    #define JSCCOLLECTOR_VIRTUALMEM_RESERVATION (4*1024*1024)
+#else
+    // HW has plenty of virtual addresses
+    #define JSCCOLLECTOR_VIRTUALMEM_RESERVATION (128*1024*1024)
+#endif
+#endif
+
+namespace WTF {
+
+/** 
+ *  Allocates contiguous region of size blockSize with blockSize-aligned address. 
+ *  blockSize must be a multiple of system page size (typically 4K on Symbian/ARM)
+ *
+ *  @param reservationSize Virtual address range to be reserved upon creation of chunk (bytes).
+ *  @param blockSize Size of a single allocation. Returned address will also be blockSize-aligned.
+ */
+class AlignedBlockAllocator {
+    public:
+        AlignedBlockAllocator(TUint32 reservationSize, TUint32 blockSize);
+        ~AlignedBlockAllocator();
+        void destroy();
+        void* alloc();
+        void free(void* data);
+    
+    private: 
+        RChunk   m_chunk; // Symbian chunk that lets us reserve/commit/decommit
+        TUint    m_offset; // offset of first committed region from base 
+        TInt     m_pageSize; // cached value of system page size, typically 4K on Symbian
+        TUint32  m_reservation;
+        TUint32  m_blockSize;  
+
+        // Tracks comitted/decommitted state of a blockSize region
+        struct {
+            
+            TUint32 *bits; // array of bit flags 
+            TUint32  numBits; // number of regions to keep track of
+            
+            bool get(TUint32 n) const
+            {
+                return !!(bits[n >> 5] & (1 << (n & 0x1F)));
+            }
+            
+            void set(TUint32 n)
+            {
+                bits[n >> 5] |= (1 << (n & 0x1F));
+            }
+            
+            void clear(TUint32 n)
+            {
+                bits[n >> 5] &= ~(1 << (n & 0x1F));
+            }
+            
+            void clearAll()
+            {
+               for (TUint32 i = 0; i < numBits; i++)
+                    clear(i);
+            }
+            
+            TInt findFree() const
+            {
+                for (TUint32 i = 0; i < numBits; i++) {
+                    if (!get(i)) 
+                        return i;
+                }
+                return -1;
+            }
+            
+        } m_map;  
+
+};
+ 
+}
+
+#endif // end of BlockAllocatorSymbian_h
+
+
diff --git a/src/3rdparty/javascriptcore/VERSION b/src/3rdparty/javascriptcore/VERSION
index 9991ac0..b4744b7 100644
--- a/src/3rdparty/javascriptcore/VERSION
+++ b/src/3rdparty/javascriptcore/VERSION
@@ -4,8 +4,8 @@ This is a snapshot of JavaScriptCore from
 
 The commit imported was from the
 
-        javascriptcore-snapshot-05102010 branch/tag
+        javascriptcore-snapshot-24012011 branch/tag
 
 and has the sha1 checksum
 
-        82ead85cfea5859044eeb25b33314dcc0fa5eea1
+        d143bde5ae8cff229aebd43487a2fce5e713e990
diff --git a/src/script/script.pro b/src/script/script.pro
index d1633d8..63917b1 100644
--- a/src/script/script.pro
+++ b/src/script/script.pro
@@ -81,7 +81,6 @@ include(script.pri)
 
 symbian {
     TARGET.UID3=0x2001B2E1
-    LIBS += -lhal
 }
 
 symbian {
-- 
cgit v0.12