working on large space
authorDavid Anderson <dvander@alliedmods.net>
Fri Jul 06 09:45:21 2012 -0400 (2012-07-06)
changeset 49a92afa7484fd
parent 48 2b6904506469
child 50 5e3c49013064
working on large space
jitcraft/Heap-inl.h
jitcraft/Heap.cpp
jitcraft/Heap.h
jitcraft/Spaces-inl.h
jitcraft/Spaces.cpp
jitcraft/Spaces.h
jitcraft/Utility.h
tests/prototype/lifo.sp
     1.1 --- a/jitcraft/Heap-inl.h	Wed Jul 04 19:54:53 2012 -0400
     1.2 +++ b/jitcraft/Heap-inl.h	Fri Jul 06 09:45:21 2012 -0400
     1.3 @@ -1,4 +1,5 @@
     1.4 -/*
     1.5 +/* vim: set ts=4 sw=4 tw=99 et:
     1.6 + *
     1.7   * Copyright (C) 2012 David Anderson
     1.8   *
     1.9   * This file is part of JITCraft.
    1.10 @@ -37,10 +38,8 @@
    1.11  inline Address
    1.12  Heap::newObject(size_t bytes, Tenure age)
    1.13  {
    1.14 -#if 0
    1.15 -    if (bytes >= kLargeObjectThreshold)
    1.16 +    if (bytes >= HeapChunk::kLargeObjectThreshold)
    1.17          return newLargeObject(bytes);
    1.18 -#endif
    1.19  
    1.20      if (age == Tenure_Stack) {
    1.21          if (Address addr = newStackObject(bytes))
    1.22 @@ -62,13 +61,10 @@
    1.23      if (Address addr = newOldObject(bytes))
    1.24          return addr;
    1.25  
    1.26 -    // Uh-oh - perform a collection.
    1.27 -    assert(false);
    1.28 +    // Uh-oh - perform a last-ditch collection.
    1.29 +    reclaim();
    1.30  
    1.31 -#if 0
    1.32      return newOldObject(bytes);
    1.33 -#endif
    1.34 -    return NULL;
    1.35  }
    1.36  
    1.37  inline Object *
    1.38 @@ -89,6 +85,17 @@
    1.39      return lifoSpace_.allocate(bytes);
    1.40  }
    1.41  
    1.42 +inline Address
    1.43 +Heap::newOldObject(size_t bytes)
    1.44 +{
    1.45 +    return oldSpace_.allocate(bytes);
    1.46 +}
    1.47 +
    1.48 +inline Address
    1.49 +Heap::newLargeObject(size_t bytes)
    1.50 +{
    1.51 +    return largeSpace_.allocate(bytes);
    1.52 +}
    1.53  
    1.54  inline void
    1.55  Object::write(Zone *zone, Object **ptr, Object *obj)
     2.1 --- a/jitcraft/Heap.cpp	Wed Jul 04 19:54:53 2012 -0400
     2.2 +++ b/jitcraft/Heap.cpp	Fri Jul 06 09:45:21 2012 -0400
     2.3 @@ -1,51 +1,54 @@
     2.4 -/*
     2.5 - * Copyright (C) 2012 David Anderson
     2.6 - *
     2.7 - * This file is part of JITCraft.
     2.8 - *
     2.9 - * JITCraft is free software: you can redistribute it and/or modify it under
    2.10 - * the terms of the GNU General Public License as published by the Free
    2.11 - * Software Foundation, either version 3 of the License, or (at your option)
    2.12 - * any later version.
    2.13 - * 
    2.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    2.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    2.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    2.17 - *
    2.18 - * You should have received a copy of the GNU General Public License along with
    2.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
    2.20 - */
    2.21 -#include "Heap.h"
    2.22 -#include "Heap-inl.h"
    2.23 -#include "Spaces-inl.h"
    2.24 -
    2.25 -using namespace jc;
    2.26 -
    2.27 -Heap::Heap(Zone *zone)
    2.28 -  : zone_(zone)
    2.29 -{
    2.30 -}
    2.31 -
    2.32 -bool
    2.33 -Heap::initialize()
    2.34 -{
    2.35 -    if (!lifoSpace_.initialize())
    2.36 -        return false;
    2.37 -    if (!oldSpace_.initialize())
    2.38 -        return false;
    2.39 -    if (!mapSpace_.initialize())
    2.40 -        return false;
    2.41 -
    2.42 -    if ((metaMap_ = allocateMap(MapKind_Meta, sizeof(Map))) == NULL)
    2.43 -        return false;
    2.44 -    metaMap_->init(metaMap_);
    2.45 -
    2.46 -    return true;
    2.47 -}
    2.48 -
    2.49 -Map *
    2.50 -Heap::allocateMap(MapKind kind, size_t bytes)
    2.51 -{
    2.52 +/* vim: set ts=4 sw=4 tw=99 et:
    2.53 + *
    2.54 + * Copyright (C) 2012 David Anderson
    2.55 + *
    2.56 + * This file is part of JITCraft.
    2.57 + *
    2.58 + * JITCraft is free software: you can redistribute it and/or modify it under
    2.59 + * the terms of the GNU General Public License as published by the Free
    2.60 + * Software Foundation, either version 3 of the License, or (at your option)
    2.61 + * any later version.
    2.62 + * 
    2.63 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    2.64 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    2.65 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    2.66 + *
    2.67 + * You should have received a copy of the GNU General Public License along with
    2.68 + * JITCraft. If not, see http://www.gnu.org/licenses/.
    2.69 + */
    2.70 +#include "Heap.h"
    2.71 +#include "Heap-inl.h"
    2.72 +#include "Spaces-inl.h"
    2.73 +
    2.74 +using namespace jc;
    2.75 +
    2.76 +Heap::Heap(Zone *zone)
    2.77 +  : zone_(zone)
    2.78 +{
    2.79 +}
    2.80 +
    2.81 +bool
    2.82 +Heap::initialize()
    2.83 +{
    2.84 +    if (!lifoSpace_.initialize())
    2.85 +        return false;
    2.86 +    if (!oldSpace_.initialize())
    2.87 +        return false;
    2.88 +    if (!mapSpace_.initialize())
    2.89 +        return false;
    2.90 +    if (!largeSpace_.initialize())
    2.91 +        return false;
    2.92 +
    2.93 +    if ((metaMap_ = allocateMap(MapKind_Meta, sizeof(Map))) == NULL)
    2.94 +        return false;
    2.95 +    metaMap_->init(metaMap_);
    2.96 +
    2.97 +    return true;
    2.98 +}
    2.99 +
   2.100 +Map *
   2.101 +Heap::allocateMap(MapKind kind, size_t bytes)
   2.102 +{
   2.103      size_t actualBytes = Align(bytes, kObjectAlignment);
   2.104  
   2.105      Address addr = mapSpace_.allocate(actualBytes);
   2.106 @@ -59,11 +62,11 @@
   2.107      Object *obj = InitAddressIntoObject(addr, NULL);
   2.108      Map *map = reinterpret_cast<Map *>(obj);
   2.109      map->setKind(kind);
   2.110 -    return map;
   2.111 -}
   2.112 -
   2.113 -Address
   2.114 -Heap::newOldObject(size_t bytes)
   2.115 -{
   2.116 -    return oldSpace_.allocate(bytes);
   2.117 -}
   2.118 +    return map;
   2.119 +}
   2.120 +
   2.121 +void
   2.122 +Heap::reclaim()
   2.123 +{
   2.124 +}
   2.125 +
     3.1 --- a/jitcraft/Heap.h	Wed Jul 04 19:54:53 2012 -0400
     3.2 +++ b/jitcraft/Heap.h	Fri Jul 06 09:45:21 2012 -0400
     3.3 @@ -1,4 +1,5 @@
     3.4 -/*
     3.5 +/* vim: set ts=4 sw=4 tw=99 et:
     3.6 + *
     3.7   * Copyright (C) 2012 David Anderson
     3.8   *
     3.9   * This file is part of JITCraft.
    3.10 @@ -28,13 +29,67 @@
    3.11  
    3.12  class Zone;
    3.13  
    3.14 -// Heap-allocated objects go here. Heaps are thread-local.
    3.15 +// Heap-allocated objects go here. Heaps are thread-local. The heap contains
    3.16 +// four spaces:
    3.17 +//
    3.18 +//    LIFO Space:  Used for objects that may be stack-allocated.
    3.19 +//    New Space:   Used for objects that are expected to be short-lived.
    3.20 +//    Old Space:   Used for objects that are expected to be long-lived, or that
    3.21 +//                 survive one collection.
    3.22 +//    Large Space: Used for objects that are so large they should never be
    3.23 +//                 moved between spaces.
    3.24 +//
    3.25 +// The garbage collector is both incremental and generational. Marking is
    3.26 +// performed incrementally, interleaved with program execution. Minor
    3.27 +// collections are also performed to mitigate the potential necessity of
    3.28 +// major collections.
    3.29 +//
    3.30 +// MINOR COLLECTIONS (also called "scavenges") are usually performed when the
    3.31 +//   new space reaches maximum capacity. During a minor collection, all live
    3.32 +//   objects in the new space are moved into the old space. Then, the new space
    3.33 +//   is reset such that it is empty.
    3.34 +//
    3.35 +//   The new is split into contiguous halves. When both halves reach maximum
    3.36 +//   capacity, a scavenge is performed on the older half. Thus, allocation is
    3.37 +//   only ever performed in one half at a time, to give newer objects a chance
    3.38 +//   to die.
    3.39 +//
    3.40 +//   Scavenges are beneficial for two major reasons:
    3.41 +//    (1) Allocation from the new space is just a pointer bump.
    3.42 +//    (2) Only the root set and remembered sets need to visited.
    3.43 +//
    3.44 +//   The "remembered set" is a list of all pointers that reach into the new
    3.45 +//   space, but come from the Old or Large spaces. The remembered set is
    3.46 +//   maintained via write barriers, and if it becomes full, entire chunks
    3.47 +//   are marked as requiring traversal.
    3.48 +//
    3.49 +//   The root and remembered sets must be visited twice: once to determine
    3.50 +//   which objects in the new space are live, and again to update any
    3.51 +//   references after the new space has been reclaimed.
    3.52 +//
    3.53 +//   Live objects in the LIFO space are always deeply traversed for pointers
    3.54 +//   into the new space, since it would be too difficult to maintain a working
    3.55 +//   remembered set.
    3.56 +//
    3.57 +// MAJOR COLLECTIONS are performed periodically, when either a given memory
    3.58 +//   threshold has been reached, or when requested by the host application.
    3.59 +//   They are also performed if no memory can be allocated.
    3.60 +//
    3.61 +//   Major collections are extremely slow; they require full heap traversal,
    3.62 +//   which can take more than a second on very large heaps. However, they
    3.63 +//   have the greatest chance at reclaiming all syntactically dead objects.
    3.64 +//
    3.65 +// SWEEPING is performed after major collections. The free space in between
    3.66 +//   live objects is added to a free list. Tenured allocations are then
    3.67 +//   performed in the free space, if possible.
    3.68 +//
    3.69  class Heap
    3.70  {
    3.71      Zone *zone_;
    3.72      HeapStack lifoSpace_;
    3.73      OldSpace mapSpace_;
    3.74      OldSpace oldSpace_;
    3.75 +    LargeObjectSpace largeSpace_;
    3.76  
    3.77      Map *metaMap_;
    3.78  
    3.79 @@ -54,7 +109,8 @@
    3.80      };
    3.81  
    3.82    private:
    3.83 -    Address newOldObject(size_t bytes);
    3.84 +    inline Address newLargeObject(size_t bytes);
    3.85 +    inline Address newOldObject(size_t bytes);
    3.86      inline Address newStackObject(size_t bytes);
    3.87      inline Address newObject(size_t bytes, Tenure pretenure);
    3.88  
    3.89 @@ -74,6 +130,9 @@
    3.90      inline void unwindLifo(Address to) {
    3.91          lifoSpace_.unwind(to);
    3.92      }
    3.93 +
    3.94 +    // Perform a full garbage collection.
    3.95 +    void reclaim();
    3.96  };
    3.97  
    3.98  }
     4.1 --- a/jitcraft/Spaces-inl.h	Wed Jul 04 19:54:53 2012 -0400
     4.2 +++ b/jitcraft/Spaces-inl.h	Fri Jul 06 09:45:21 2012 -0400
     4.3 @@ -1,45 +1,46 @@
     4.4 -/*
     4.5 - * Copyright (C) 2012 David Anderson
     4.6 - *
     4.7 - * This file is part of JITCraft.
     4.8 - *
     4.9 - * JITCraft is free software: you can redistribute it and/or modify it under
    4.10 - * the terms of the GNU General Public License as published by the Free
    4.11 - * Software Foundation, either version 3 of the License, or (at your option)
    4.12 - * any later version.
    4.13 - * 
    4.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    4.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    4.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    4.17 - *
    4.18 - * You should have received a copy of the GNU General Public License along with
    4.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
    4.20 - */
    4.21 -#ifndef _include_jitcraft_spaces_inl_h_
    4.22 -#define _include_jitcraft_spaces_inl_h_
    4.23 -
    4.24 -namespace jc {
    4.25 -
    4.26 -inline Address
    4.27 -HeapStack::allocate(size_t nbytes)
    4.28 -{
    4.29 -    nbytes = Align(nbytes, kObjectAlignment);
    4.30 -
    4.31 -    if (pos_ + nbytes > end_)
    4.32 -        return NULL;
    4.33 -
    4.34 -    Address ptr = pos_;
    4.35 -    pos_ += nbytes;
    4.36 -    return ptr;
    4.37 -}
    4.38 -
    4.39 -inline void
    4.40 -HeapStack::unwind(Address to)
    4.41 -{
    4.42 -    assert(to <= pos_ && to >= buffer_);
    4.43 -    pos_ = to;
    4.44 -}
    4.45 -
    4.46 +/* vim: set ts=4 sw=4 tw=99 et:
    4.47 + *
    4.48 + * Copyright (C) 2012 David Anderson
    4.49 + *
    4.50 + * This file is part of JITCraft.
    4.51 + *
    4.52 + * JITCraft is free software: you can redistribute it and/or modify it under
    4.53 + * the terms of the GNU General Public License as published by the Free
    4.54 + * Software Foundation, either version 3 of the License, or (at your option)
    4.55 + * any later version.
    4.56 + * 
    4.57 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    4.58 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    4.59 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    4.60 + *
    4.61 + * You should have received a copy of the GNU General Public License along with
    4.62 + * JITCraft. If not, see http://www.gnu.org/licenses/.
    4.63 + */
    4.64 +#ifndef _include_jitcraft_spaces_inl_h_
    4.65 +#define _include_jitcraft_spaces_inl_h_
    4.66 +
    4.67 +namespace jc {
    4.68 +
    4.69 +inline Address
    4.70 +HeapStack::allocate(size_t nbytes)
    4.71 +{
    4.72 +    nbytes = Align(nbytes, kObjectAlignment);
    4.73 +
    4.74 +    if (pos_ + nbytes > end_)
    4.75 +        return NULL;
    4.76 +
    4.77 +    Address ptr = pos_;
    4.78 +    pos_ += nbytes;
    4.79 +    return ptr;
    4.80 +}
    4.81 +
    4.82 +inline void
    4.83 +HeapStack::unwind(Address to)
    4.84 +{
    4.85 +    assert(to <= pos_ && to >= buffer_);
    4.86 +    pos_ = to;
    4.87 +}
    4.88 +
    4.89  inline Address
    4.90  HeapChunk::allocate(size_t nbytes)
    4.91  {
    4.92 @@ -60,8 +61,8 @@
    4.93          return addr;
    4.94  
    4.95      return allocateSlow(nbytes);
    4.96 -}
    4.97 -
    4.98 -}
    4.99 -
   4.100 -#endif // _include_jitcraft_spaces_inl_h_
   4.101 +}
   4.102 +
   4.103 +}
   4.104 +
   4.105 +#endif // _include_jitcraft_spaces_inl_h_
     5.1 --- a/jitcraft/Spaces.cpp	Wed Jul 04 19:54:53 2012 -0400
     5.2 +++ b/jitcraft/Spaces.cpp	Fri Jul 06 09:45:21 2012 -0400
     5.3 @@ -1,52 +1,54 @@
     5.4 -/*
     5.5 - * Copyright (C) 2012 David Anderson
     5.6 - *
     5.7 - * This file is part of JITCraft.
     5.8 - *
     5.9 - * JITCraft is free software: you can redistribute it and/or modify it under
    5.10 - * the terms of the GNU General Public License as published by the Free
    5.11 - * Software Foundation, either version 3 of the License, or (at your option)
    5.12 - * any later version.
    5.13 - * 
    5.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    5.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    5.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    5.17 - *
    5.18 - * You should have received a copy of the GNU General Public License along with
    5.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
    5.20 - */
    5.21 -#include "Spaces.h"
    5.22 -#include "Platform.h"
    5.23 -#include "Spaces-inl.h"
    5.24 -
    5.25 -using namespace jc;
    5.26 -
    5.27 -HeapStack::HeapStack()
    5.28 -  : buffer_(NULL),
    5.29 -    pos_(NULL),
    5.30 -    end_(NULL)
    5.31 -{
    5.32 -}
    5.33 -
    5.34 -HeapStack::~HeapStack()
    5.35 -{
    5.36 -    if (buffer_)
    5.37 -        OS::UnmapAlignedMemory(map_.base(), map_.size());
    5.38 -}
    5.39 -
    5.40 -bool
    5.41 -HeapStack::initialize()
    5.42 -{
    5.43 -    map_ = OS::MapAlignedMemory(kStackSize, kStackSize, OS::Map_Commit);
    5.44 -    if (!map_.base())
    5.45 -        return false;
    5.46 -
    5.47 -    buffer_ = map_.aligned();
    5.48 -    pos_ = buffer_;
    5.49 -    end_ = buffer_ + kStackSize;
    5.50 -    return true;
    5.51 -}
    5.52 -
    5.53 +/* vim: set ts=4 sw=4 tw=99 et:
    5.54 + *
    5.55 + * Copyright (C) 2012 David Anderson
    5.56 + *
    5.57 + * This file is part of JITCraft.
    5.58 + *
    5.59 + * JITCraft is free software: you can redistribute it and/or modify it under
    5.60 + * the terms of the GNU General Public License as published by the Free
    5.61 + * Software Foundation, either version 3 of the License, or (at your option)
    5.62 + * any later version.
    5.63 + * 
    5.64 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    5.65 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    5.66 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    5.67 + *
    5.68 + * You should have received a copy of the GNU General Public License along with
    5.69 + * JITCraft. If not, see http://www.gnu.org/licenses/.
    5.70 + */
    5.71 +#include "Spaces.h"
    5.72 +#include "Platform.h"
    5.73 +#include "Spaces-inl.h"
    5.74 +
    5.75 +using namespace jc;
    5.76 +
    5.77 +HeapStack::HeapStack()
    5.78 +  : buffer_(NULL),
    5.79 +    pos_(NULL),
    5.80 +    end_(NULL)
    5.81 +{
    5.82 +}
    5.83 +
    5.84 +HeapStack::~HeapStack()
    5.85 +{
    5.86 +    if (buffer_)
    5.87 +        OS::UnmapAlignedMemory(map_.base(), map_.size());
    5.88 +}
    5.89 +
    5.90 +bool
    5.91 +HeapStack::initialize()
    5.92 +{
    5.93 +    map_ = OS::MapAlignedMemory(kStackSize, kStackSize, OS::Map_Commit);
    5.94 +    if (!map_.base())
    5.95 +        return false;
    5.96 +
    5.97 +    buffer_ = map_.aligned();
    5.98 +    pos_ = buffer_;
    5.99 +    end_ = buffer_ + kStackSize;
   5.100 +    mask_ = kStackSize - 1;
   5.101 +    return true;
   5.102 +}
   5.103 +
   5.104  HeapChunk *
   5.105  HeapChunk::New(HeapChunk *prev, size_t size)
   5.106  {
   5.107 @@ -105,4 +107,18 @@
   5.108          first_ = temp;
   5.109      }
   5.110  }
   5.111 -
   5.112 +
   5.113 +
   5.114 +Address
   5.115 +LargeObjectSpace::allocate(size_t nbytes)
   5.116 +{
   5.117 +    assert(IsAligned(nbytes, kObjectAlignment));
   5.118 +
   5.119 +    if (last_) {
   5.120 +        if (Address addr = last_->allocate(nbytes))
   5.121 +            return addr;
   5.122 +    }
   5.123 +
   5.124 +
   5.125 +}
   5.126 +
     6.1 --- a/jitcraft/Spaces.h	Wed Jul 04 19:54:53 2012 -0400
     6.2 +++ b/jitcraft/Spaces.h	Fri Jul 06 09:45:21 2012 -0400
     6.3 @@ -1,56 +1,65 @@
     6.4 -/*
     6.5 - * Copyright (C) 2012 David Anderson
     6.6 - *
     6.7 - * This file is part of JITCraft.
     6.8 - *
     6.9 - * JITCraft is free software: you can redistribute it and/or modify it under
    6.10 - * the terms of the GNU General Public License as published by the Free
    6.11 - * Software Foundation, either version 3 of the License, or (at your option)
    6.12 - * any later version.
    6.13 - * 
    6.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    6.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    6.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    6.17 - *
    6.18 - * You should have received a copy of the GNU General Public License along with
    6.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
    6.20 - */
    6.21 -#ifndef _include_jitcraft_spaces_h_
    6.22 -#define _include_jitcraft_spaces_h_
    6.23 -
    6.24 -#include "Utility.h"
    6.25 -#include "Platform.h"
    6.26 -
    6.27 -namespace jc {
    6.28 -
    6.29 -static const size_t kObjectAlignment = 8;
    6.30 -
    6.31 -// The heap stack is designed for structures which are known to not escape the
    6.32 -// program stack, and can thus be quickly allocated in a LIFO manner.
    6.33 -// 
    6.34 -class HeapStack
    6.35 -{
    6.36 -    OS::AlignableMapping map_;
    6.37 -    Address buffer_;
    6.38 -    Address pos_;
    6.39 -    Address end_;
    6.40 -
    6.41 -  private:
    6.42 -    static const size_t kStackSize = 1024 * 1024;
    6.43 -
    6.44 -  public:
    6.45 -    HeapStack();
    6.46 -    ~HeapStack();
    6.47 -    bool initialize();
    6.48 -
    6.49 -  public:
    6.50 -    Address position() const {
    6.51 -        return pos_;
    6.52 -    }
    6.53 -    inline Address allocate(size_t nbytes);
    6.54 -    inline void unwind(Address to);
    6.55 -};
    6.56 -
    6.57 +/* vim: set ts=4 sw=4 tw=99 et:
    6.58 + *
    6.59 + * Copyright (C) 2012 David Anderson
    6.60 + *
    6.61 + * This file is part of JITCraft.
    6.62 + *
    6.63 + * JITCraft is free software: you can redistribute it and/or modify it under
    6.64 + * the terms of the GNU General Public License as published by the Free
    6.65 + * Software Foundation, either version 3 of the License, or (at your option)
    6.66 + * any later version.
    6.67 + * 
    6.68 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    6.69 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    6.70 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    6.71 + *
    6.72 + * You should have received a copy of the GNU General Public License along with
    6.73 + * JITCraft. If not, see http://www.gnu.org/licenses/.
    6.74 + */
    6.75 +#ifndef _include_jitcraft_spaces_h_
    6.76 +#define _include_jitcraft_spaces_h_
    6.77 +
    6.78 +#include <limits.h>
    6.79 +#include "Utility.h"
    6.80 +#include "Platform.h"
    6.81 +
    6.82 +namespace jc {
    6.83 +
    6.84 +class Object;
    6.85 +
    6.86 +static const size_t kObjectAlignment = 8;
    6.87 +
    6.88 +// The heap stack is designed for structures which are known to not escape the
    6.89 +// program stack, and can thus be quickly allocated in a LIFO manner.
    6.90 +// 
    6.91 +class HeapStack
    6.92 +{
    6.93 +    OS::AlignableMapping map_;
    6.94 +    Address buffer_;
    6.95 +    Address pos_;
    6.96 +    Address end_;
    6.97 +    uintptr_t mask_;
    6.98 +
    6.99 +  private:
   6.100 +    static const size_t kStackSize = 1024 * 1024;
   6.101 +
   6.102 +  public:
   6.103 +    HeapStack();
   6.104 +    ~HeapStack();
   6.105 +    bool initialize();
   6.106 +
   6.107 +  public:
   6.108 +    Address position() const {
   6.109 +        return pos_;
   6.110 +    }
   6.111 +    inline Address allocate(size_t nbytes);
   6.112 +    inline void unwind(Address to);
   6.113 +
   6.114 +    inline bool contains(Object *obj) {
   6.115 +        return (reinterpret_cast<uintptr_t>(obj) & mask_) == reinterpret_cast<uintptr_t>(buffer_);
   6.116 +    }
   6.117 +};
   6.118 +
   6.119  class HeapChunk
   6.120  {
   6.121      HeapChunk *next_;
   6.122 @@ -65,9 +74,25 @@
   6.123      Address cursor_;
   6.124  
   6.125    public:
   6.126 -    static const size_t kMaxObjectSize = 1 * kGB;
   6.127 -    static const size_t kDefaultSize = 256 * kKB;
   6.128 -    static const size_t kAlignment = 256 * kKB;
   6.129 +    static const size_t kDefaultSize = 1 * kMB;
   6.130 +    static const size_t kAlignment = 1 * kMB;
   6.131 +
   6.132 +    // Maximum size of an object that will fit in a page. We limit this
   6.133 +    // specifically to help JITs: the computation of a[i] has a special
   6.134 +    // instruction form on most CPUs, but the index might not be sign-
   6.135 +    // extended on 64-bit architectures. We limit the size such that:
   6.136 +    //
   6.137 +    //    index * sizeof(Object *)
   6.138 +    //
   6.139 +    // Is guaranteed to not overflow a signed 32-bit integer.
   6.140 +    static const size_t kMaxObjectSize = INT_MAX / sizeof(Object *);
   6.141 +
   6.142 +    // Size of a HeapChunk header.
   6.143 +    static const size_t kHeaderSize =
   6.144 +        sizeof(HeapChunk *) +
   6.145 +        sizeof(Address) +
   6.146 +        sizeof(Address) +
   6.147 +        sizeof(Address);
   6.148  
   6.149      // All objects must be allocated in the first kAlignment bytes of the
   6.150      // chunk. Every object is at least 8 bytes (kPointerAlignment), so we
   6.151 @@ -93,15 +118,16 @@
   6.152      static const size_t kMarkBytes = kMarkBits / 8;
   6.153      static const size_t kMarkWords = kMarkBytes / sizeof(uint32);
   6.154  
   6.155 -    static inline size_t offsetToMarkBits()
   6.156 -    {
   6.157 -        return Align(sizeof(HeapChunk), kObjectAlignment);
   6.158 -    }
   6.159 +    static const size_t kMarkBitsOffset = kHeaderSize;
   6.160 +    static const size_t kFirstObject = kMarkBitsOffset + kMarkBytes;
   6.161  
   6.162 -    static inline size_t offsetToFirst()
   6.163 -    {
   6.164 -        assert(IsAligned(kMarkBytes, kObjectAlignment));
   6.165 -        return offsetToMarkBits() + kMarkBytes;
   6.166 +    // Threshold for allocating an object in the large object space.
   6.167 +    static const size_t kLargeObjectThreshold = kAlignment - kFirstObject;
   6.168 +
   6.169 +    static inline void StaticAsserts() {
   6.170 +        STATIC_ASSERT(kHeaderSize == sizeof(HeapChunk));
   6.171 +        STATIC_ASSERT(IS_ALIGNED(kHeaderSize, kObjectAlignment));
   6.172 +        STATIC_ASSERT(IS_ALIGNED(kFirstObject, kObjectAlignment));
   6.173      }
   6.174  
   6.175    public:
   6.176 @@ -124,11 +150,10 @@
   6.177          return end() - base();
   6.178      }
   6.179      Address first() {
   6.180 -        return reinterpret_cast<Address>(this) + offsetToFirst();
   6.181 +        return reinterpret_cast<Address>(this) + kFirstObject;
   6.182      }
   6.183      uint32 *markBits() {
   6.184 -        return reinterpret_cast<uint32 *>(reinterpret_cast<Address>(this) +
   6.185 -                                          offsetToMarkBits());
   6.186 +        return reinterpret_cast<uint32 *>(reinterpret_cast<Address>(this) + kMarkBitsOffset);
   6.187      }
   6.188  };
   6.189  
   6.190 @@ -146,8 +171,23 @@
   6.191    public:
   6.192      inline Address allocate(size_t nbytes);
   6.193      Address allocateSlow(size_t nbytes);
   6.194 -};
   6.195 -
   6.196 -}
   6.197 -
   6.198 -#endif // _include_jitcraft_spaces_h_
   6.199 +};
   6.200 +
   6.201 +class LargeObjectSpace
   6.202 +{
   6.203 +    HeapChunk *first_;
   6.204 +    HeapChunk *last_;
   6.205 +
   6.206 +  public:
   6.207 +    LargeObjectSpace();
   6.208 +    ~LargeObjectSpace();
   6.209 +
   6.210 +    bool initialize();
   6.211 +
   6.212 +  public:
   6.213 +    Address allocate(size_t nbytes);
   6.214 +};
   6.215 +
   6.216 +}
   6.217 +
   6.218 +#endif // _include_jitcraft_spaces_h_
     7.1 --- a/jitcraft/Utility.h	Wed Jul 04 19:54:53 2012 -0400
     7.2 +++ b/jitcraft/Utility.h	Fri Jul 06 09:45:21 2012 -0400
     7.3 @@ -1,4 +1,5 @@
     7.4 -/*
     7.5 +/* vim: set ts=4 sw=4 tw=99 et:
     7.6 + *
     7.7   * Copyright (C) 2012 David Anderson
     7.8   *
     7.9   * This file is part of JITCraft.
    7.10 @@ -125,6 +126,8 @@
    7.11  #define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0]))
    7.12  #define STATIC_ASSERT(cond) extern int static_assert_f(int a[(cond) ? 1 : -1])
    7.13  
    7.14 +#define IS_ALIGNED(addr, alignment)	(!(uintptr_t(addr) & ((alignment) - 1)))
    7.15 +
    7.16  template <typename T>
    7.17  static inline bool
    7.18  IsAligned(T addr, size_t alignment)
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/tests/prototype/lifo.sp	Fri Jul 06 09:45:21 2012 -0400
     8.3 @@ -0,0 +1,13 @@
     8.4 +q(&a)
     8.5 +{
     8.6 +    return 5;
     8.7 +}
     8.8 +
     8.9 +main()
    8.10 +{
    8.11 +    for (new i = 0; i < 100; i++) {
    8.12 +        q(i);
    8.13 +    }
    8.14 +    return 5;
    8.15 +}
    8.16 +