Support assigning structs.
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_;
107 static StructMap *New(Zone *zone, const StructureBufferBuilder &builder);
109 unsigned structureSize() {
110 return structureSize_;
112 unsigned traceOffsetCount() {
113 return traceOffsetCount_;
115 const unsigned *traceOffsets() {
116 return reinterpret_cast<unsigned *>(this + 1);
119 return Align(sizeof(StructMap) + sizeof(unsigned) * traceOffsetCount(), kObjectAlignment);
124 void setType(Type *type) {
129 // Begin GC descriptors.
130 static inline size_t offsetOfType() {
131 return OFFSETOF(StructMap, type_);
133 // End GC descriptors.
135 static inline StructMap *cast(Object *obj) {
136 assert(!obj || obj->is(MapKind_MetaStruct));
137 return reinterpret_cast<StructMap *>(obj);
141 class Struct : public Object
144 static Struct *New(Zone *zone, Handle<StructMap> map, Heap::Tenure tenure = Heap::Tenure_Default);
147 return Align(sizeof(Struct) + map()->structureSize(), kObjectAlignment);
150 return StructMap::cast(Object::map());
153 // This must NOT be used with any Object * type!
154 template <typename T> T get(Descriptor *desc) {
155 return *reinterpret_cast<T *>(
156 reinterpret_cast<Address>(this) +
157 offsetOfSlotOffset(desc->offset()));
160 template <typename T> void set(Descriptor *desc, const T &t) {
161 *reinterpret_cast<T *>(
162 reinterpret_cast<Address>(this) +
163 offsetOfSlotOffset(desc->offset())) = t;
166 void set(Zone *zone, Descriptor *desc, Object *obj) {
167 // :TODO: write barrier
168 *reinterpret_cast<Object **>(
169 reinterpret_cast<Address>(this) +
170 offsetOfSlotOffset(desc->offset())) = obj;
173 static inline size_t offsetOfSlotOffset(unsigned offset) {
174 return sizeof(Struct) + offset;
177 static inline Struct *cast(Object *obj) {
178 assert(!obj || obj->is(MapKind_Struct));
179 return reinterpret_cast<Struct *>(obj);
185 #endif // _include_jc_structure_h_