Allow structs to contain arrays.
1 /* vim: set ts=4 sw=4 tw=99 et:
3 * Copyright (C) 2012 David Anderson
5 * This file is part of SourcePawn.
7 * SourcePawn is free software: you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License as published by the Free
9 * Software Foundation, either version 3 of the License, or (at your option)
12 * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with
17 * SourcePawn. If not, see http://www.gnu.org/licenses/.
19 #ifndef _include_jc_structure_h_
20 #define _include_jc_structure_h_
33 // When describing composite structures, the GC must be able to trace interior
34 // references to Objects. To make this possible, maps that describe composite
35 // structures must provide a list of offsets into their objects that are
36 // traceable. StructureBufferBuilder assists with this.
37 class StructureBufferBuilder
40 StructureBufferBuilder();
42 bool add(Handle<Type> type, unsigned *offset);
44 unsigned structureSize() const {
47 unsigned traceableOffsetCount() const {
48 return offsets_.length();
50 const unsigned *offsets() const {
51 return offsets_.buffer();
55 Vector<unsigned> offsets_;
59 // Represents a property descriptor for a structure field.
60 class Descriptor : public Object
62 // The name of the field.
63 Barriered<String> name_;
65 // The type of the field.
66 Barriered<Type> type_;
68 // The offset into an object at which this field can be accessed.
72 static Descriptor *New(Zone *zone, Handle<String> name, Handle<Type> type,
85 // Begin GC descriptor.
86 static inline size_t offsetOfName() {
87 return OFFSETOF(Descriptor, name_);
89 static inline size_t offsetOfType() {
90 return OFFSETOF(Descriptor, type_);
94 static inline Descriptor *cast(Object *obj) {
95 assert(!obj || obj->is(MapKind_Descriptor));
96 return reinterpret_cast<Descriptor *>(obj);
100 class StructMap : public Map
102 unsigned structureSize_;
103 unsigned traceOffsetCount_;
104 Barriered<Type> type_;
106 // List of descriptors which must be allocated upon initialization.
107 Barriered<FixedArray> composed_;
110 static StructMap *New(Zone *zone, const StructureBufferBuilder &builder, Handle<FixedArray> composed);
112 unsigned structureSize() {
113 return structureSize_;
115 unsigned traceOffsetCount() {
116 return traceOffsetCount_;
118 const unsigned *traceOffsets() {
119 return reinterpret_cast<unsigned *>(this + 1);
122 return sizeof(StructMap) + sizeof(unsigned) * traceOffsetCount();
127 FixedArray *composed() {
131 void setType(Type *type) {
136 // Begin GC descriptors.
137 static inline size_t offsetOfType() {
138 return OFFSETOF(StructMap, type_);
140 static inline size_t offsetOfComposed() {
141 return OFFSETOF(StructMap, composed_);
143 // End GC descriptors.
145 static inline StructMap *cast(Object *obj) {
146 assert(!obj || obj->is(MapKind_MetaStruct));
147 return reinterpret_cast<StructMap *>(obj);
151 class Struct : public Object
154 static Struct *New(Zone *zone, Handle<StructMap> map, Heap::Tenure tenure = Heap::Tenure_Default);
157 return sizeof(Struct) + map()->structureSize();
160 return StructMap::cast(Object::map());
163 void *ref(Descriptor *desc) {
164 return reinterpret_cast<Address>(this) + offsetOfSlotOffset(desc->offset());
167 // This must NOT be used with any Object * type!
168 template <typename T> T get(Descriptor *desc) {
169 return *reinterpret_cast<T *>(ref(desc));
172 template <typename T> void set(Descriptor *desc, const T &t) {
173 *reinterpret_cast<T *>(ref(desc)) = t;
176 void set(Zone *zone, Descriptor *desc, Object *obj) {
177 // :TODO: write barrier
178 *reinterpret_cast<Object **>(
179 reinterpret_cast<Address>(this) +
180 offsetOfSlotOffset(desc->offset())) = obj;
183 static inline size_t offsetOfSlotOffset(unsigned offset) {
184 return sizeof(Struct) + offset;
187 static inline Struct *cast(Object *obj) {
188 assert(!obj || obj->is(MapKind_Struct));
189 return reinterpret_cast<Struct *>(obj);
195 #endif // _include_jc_structure_h_