src/Structures.cpp
author David Anderson <dvander@alliedmods.net>
Sat Aug 11 12:11:39 2012 -0700 (2012-08-11)
changeset 170 5e4570966ece
parent 153 fc91c4a3dfe2
child 192 23a804fa1d3e
permissions -rw-r--r--
Parser support for public variables.
     1 /* vim: set ts=4 sw=4 tw=99 et:
     2  *
     3  * Copyright (C) 2012 David Anderson
     4  *
     5  * This file is part of SourcePawn.
     6  *
     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)
    10  * any later version.
    11  * 
    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.
    15  *
    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/.
    18  */
    19 #include <string.h>
    20 #include "Structures.h"
    21 #include "Zone.h"
    22 #include "Types.h"
    23 #include "Spaces-inl.h"
    24 #include "Heap-inl.h"
    25 
    26 using namespace ke;
    27 
    28 StructureBufferBuilder::StructureBufferBuilder()
    29   : size_(0)
    30 {
    31 }
    32 
    33 bool
    34 StructureBufferBuilder::add(Handle<Type> type, unsigned *offset)
    35 {
    36     *offset = size_;
    37 
    38     if (!type->isTraceable()) {
    39         // For now, assume the size of primitives is 4-byte.
    40         assert(type->isInt32() || type->isFloat());
    41         size_ += 4;
    42         return true;
    43     }
    44 
    45     if (!offsets_.append(size_))
    46         return false;
    47 
    48     size_ += sizeof(Object *);
    49     return true;
    50 }
    51 
    52 Descriptor *
    53 Descriptor::New(Zone *zone, Handle<String> name, Handle<Type> type, unsigned offset)
    54 {
    55     Local<Descriptor> desc(zone,
    56         Descriptor::cast(zone->allocate(MapKind_Descriptor, sizeof(Descriptor), Heap::Tenure_Old)));
    57     if (!desc)
    58         return NULL;
    59 
    60     desc->name_ = name;
    61     desc->type_ = type;
    62     desc->offset_ = offset;
    63     return desc;
    64 }
    65 
    66 StructMap *
    67 StructMap::New(Zone *zone, const StructureBufferBuilder &builder, Handle<FixedArray> composed)
    68 {
    69     size_t bytesNeeded = sizeof(StructMap) +
    70                          (builder.traceableOffsetCount() * sizeof(unsigned));
    71 
    72     Local<StructMap> map(zone);
    73     map = StructMap::cast(zone->allocateMap(MapKind_Struct, bytesNeeded, MapKind_MetaStruct));
    74     if (!map)
    75         return NULL;
    76 
    77     map->structureSize_ = builder.structureSize();
    78     map->traceOffsetCount_ = builder.traceableOffsetCount();
    79     map->type_ = NULL;
    80     map->composed_ = composed;
    81     memcpy(const_cast<unsigned *>(map->traceOffsets()), builder.offsets(),
    82            sizeof(unsigned) * builder.traceableOffsetCount());
    83 
    84     return map;
    85 }
    86 
    87 Struct *
    88 Struct::New(Zone *zone, Handle<StructMap> map, Heap::Tenure tenure)
    89 {
    90     size_t bytesNeeded = sizeof(Struct) + map->structureSize();
    91     Local<Struct> obj(zone, Struct::cast(zone->allocate(map, bytesNeeded, tenure)));
    92     if (!obj)
    93         return NULL;
    94 
    95     memset((Struct *)obj + 1, 0, map->structureSize());
    96 
    97     // Initialize any sub-structures. Right now, this is performed as part of
    98     // struct allocation, rather than inlined in bytecode, for simplicity.
    99     if (map->composed()) {
   100         Local<Descriptor> desc(zone);
   101         Local<Struct> child(zone);
   102         Local<StructMap> childMap(zone);
   103         for (unsigned i = 0; i < map->composed()->length(); i++) {
   104             desc = Descriptor::cast(map->composed()->at(i));
   105 
   106             // We don't support composing arrays yet.
   107             assert(desc->type()->isStruct());
   108 
   109             childMap = StructMap::cast(desc->type()->newMap());
   110             child = Struct::New(zone, childMap, tenure);
   111             if (!child)
   112                 return NULL;
   113 
   114             obj->set(zone, desc, child);
   115         }
   116     }
   117 
   118     return obj;
   119 }
   120