dvander@11: /* dvander@11: * Copyright (C) 2012 David Anderson dvander@11: * dvander@11: * This file is part of JITCraft. dvander@11: * dvander@11: * JITCraft is free software: you can redistribute it and/or modify it under dvander@11: * the terms of the GNU General Public License as published by the Free dvander@11: * Software Foundation, either version 3 of the License, or (at your option) dvander@11: * any later version. dvander@11: * dvander@11: * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY dvander@11: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS dvander@11: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. dvander@11: * dvander@11: * You should have received a copy of the GNU General Public License along with dvander@11: * JITCraft. If not, see http://www.gnu.org/licenses/. dvander@11: */ dvander@11: #ifndef _include_jitcraft_objects_h_ dvander@11: #define _include_jitcraft_objects_h_ dvander@11: dvander@11: #include "Utility.h" dvander@11: #include "Spaces.h" dvander@13: #include "Barriers.h" dvander@11: dvander@11: namespace jc { dvander@11: dvander@11: class Zone; dvander@11: dvander@11: // Macros for laying out objects. dvander@11: #define OBJECT_FIELD(Type, name) \ dvander@11: Type fld_##name##_; dvander@11: dvander@12: // :TODO: refactor these now that objects are no longer tagged. dvander@11: #define RAW_FIELD_ADDRESS(ptr) \ dvander@12: (reinterpret_cast(ptr)) dvander@11: #define TYPED_FIELD_ADDRESS(Type, ptr) \ dvander@11: (reinterpret_cast(RAW_FIELD_ADDRESS(ptr))) dvander@11: #define OBJ_FIELD_OFFSET(obj, ptr) \ dvander@11: (reinterpret_cast(ptr) - reinterpret_cast(obj)) dvander@11: #define READ_FIELD(name) \ dvander@11: read(&fld_##name##_) dvander@11: #define WRITE_FIELD(name, val) \ dvander@11: write(&fld_##name##_, val) dvander@11: #define READ_FIELD_OBJ(name) \ dvander@11: read(reinterpret_cast(&fld_##name##_)) dvander@11: #define WRITE_FIELD_OBJ(env, name, val) \ dvander@11: write(env, reinterpret_cast(&fld_##name##_), val) dvander@11: #define WRITE_FIELD_OBJ_NO_BARRIER(name, val) \ dvander@11: writeNoBarrier(reinterpret_cast(&fld_##name##_), val) dvander@11: dvander@11: // Garbage-collection objects require a header to describe their layout. This dvander@11: // header is called a "map". The different kinds of maps are enumerated below. dvander@11: class Map; dvander@11: dvander@11: enum MapKind dvander@11: { dvander@12: // Represents Type objects. dvander@12: MapKind_Type, dvander@12: dvander@14: // Represents basic data structures. When adding to this, don't forget dvander@14: // to update Zone::initialize(), or you'll get a NULL crash trying to dvander@14: // allocate, since these maps are cached. dvander@12: MapKind_FixedArray, dvander@12: MapKind_ByteArray, dvander@12: MapKind_Code, dvander@14: MapKind_Reference, dvander@14: MapKind_Module, dvander@26: MapKind_Function, dvander@11: dvander@14: // Used to represent Arrays. This does not have a canonical map. dvander@12: MapKind_Array, dvander@12: dvander@12: // These represent special Map subclasses that require special tracing. dvander@12: MapKinds_Special, dvander@12: MapKind_Meta, // (default map class) dvander@12: MapKind_MetaArray, // ArrayMap instances dvander@12: MapKinds_EndSpecial, dvander@11: dvander@11: MapKinds_Total dvander@11: }; dvander@11: dvander@12: typedef void * VoidPtr; dvander@11: dvander@11: // All garbage collected objects must inherit from GCObject. Note that using dvander@11: // virtual functions is illegal, as the |map| field would be displaced. dvander@12: class Object dvander@11: { dvander@13: Barriered map_; dvander@11: dvander@11: public: dvander@11: void init(Map *map) { dvander@13: map_ = map; dvander@11: } dvander@11: dvander@11: Map *map() { dvander@13: return map_; dvander@11: } dvander@12: inline bool is(MapKind map); dvander@13: dvander@13: inline void write(Zone *zone, Object **ptr, Object *value); dvander@11: }; dvander@11: dvander@12: // Maps describe the layout of GCObjects. Every GCObject requires a map. dvander@12: class Map : public Object dvander@11: { dvander@13: MapKind kind_; dvander@11: dvander@11: public: dvander@11: void setKind(MapKind kind) { dvander@13: kind_ = kind; dvander@11: } dvander@11: MapKind kind() { dvander@13: return kind_; dvander@11: } dvander@12: dvander@12: static inline Map *cast(Object *obj) { dvander@12: // Note that ArrayMap is a map, but a special one: since it is non- dvander@12: assert(obj->map()->kind() > MapKinds_Special && dvander@12: obj->map()->kind() < MapKinds_EndSpecial); dvander@12: return reinterpret_cast(obj); dvander@12: } dvander@11: }; dvander@11: dvander@11: // Heap-allocated objects go here. Heaps are thread-local. dvander@11: class Heap dvander@11: { dvander@11: Zone *zone_; dvander@12: HeapStack lifoSpace_; dvander@11: OldSpace mapSpace_; dvander@11: OldSpace oldSpace_; dvander@11: dvander@11: Map *metaMap_; dvander@11: dvander@11: public: dvander@11: enum Tenure { dvander@12: // Default, objects go into the nursery. dvander@11: Tenure_Default, dvander@12: dvander@12: // If objects are proven to not escape the stack, they can go into dvander@12: // a LIFO arena. Allocation on the LIFO arena is not guaranteed to dvander@12: // succeed; thus, objects may still be allocated in other arenas. dvander@12: Tenure_Stack, dvander@12: dvander@12: // Objects that should not go into the nursery (i.e. are expected dvander@12: // to be long-living) go here. dvander@11: Tenure_Old dvander@11: }; dvander@11: dvander@11: private: dvander@12: Address newOldObject(size_t bytes); dvander@12: inline Address newStackObject(size_t bytes); dvander@11: inline Address newObject(size_t bytes, Tenure pretenure); dvander@11: dvander@11: public: dvander@11: Heap(Zone *zone); dvander@11: bool initialize(); dvander@11: dvander@11: inline Object *allocate(Map *map, size_t byes, Tenure pretenure); dvander@27: inline Object *allocate(Handle map, size_t byes, Tenure pretenure); dvander@11: Map *allocateMap(MapKind kind, size_t bytes); dvander@11: dvander@11: Map *metaMap() { dvander@11: return metaMap_; dvander@11: } dvander@12: inline Address lifoPosition() const { dvander@12: return lifoSpace_.position(); dvander@12: } dvander@12: inline void unwindLifo(Address to) { dvander@12: lifoSpace_.unwind(to); dvander@12: } dvander@11: }; dvander@11: dvander@11: inline bool dvander@11: Object::is(MapKind kind) dvander@11: { dvander@12: return map()->kind() == kind; dvander@11: } dvander@11: dvander@11: } dvander@11: dvander@11: #endif //_include_jitcraft_objects_h_