src/Structures.cpp
author David Anderson <dvander@alliedmods.net>
Sun Nov 18 16:10:43 2012 -0800 (2012-11-18)
changeset 218 ccb089827f87
parent 195 c1ba166f3fc4
child 234 26e3035cdffc
permissions -rw-r--r--
Re-add postinc support.
dvander@146
     1
/* vim: set ts=4 sw=4 tw=99 et:
dvander@85
     2
 *
dvander@85
     3
 * Copyright (C) 2012 David Anderson
dvander@85
     4
 *
dvander@146
     5
 * This file is part of SourcePawn.
dvander@85
     6
 *
dvander@146
     7
 * SourcePawn is free software: you can redistribute it and/or modify it under
dvander@85
     8
 * the terms of the GNU General Public License as published by the Free
dvander@85
     9
 * Software Foundation, either version 3 of the License, or (at your option)
dvander@85
    10
 * any later version.
dvander@85
    11
 * 
dvander@146
    12
 * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
dvander@85
    13
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@85
    14
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
dvander@85
    15
 *
dvander@85
    16
 * You should have received a copy of the GNU General Public License along with
dvander@146
    17
 * SourcePawn. If not, see http://www.gnu.org/licenses/.
dvander@85
    18
 */
dvander@147
    19
#include <string.h>
dvander@85
    20
#include "Structures.h"
dvander@146
    21
#include "Zone.h"
dvander@85
    22
#include "Types.h"
dvander@192
    23
#include "Array.h"
danderson@92
    24
#include "Spaces-inl.h"
danderson@92
    25
#include "Heap-inl.h"
dvander@85
    26
dvander@85
    27
using namespace ke;
dvander@85
    28
dvander@85
    29
StructureBufferBuilder::StructureBufferBuilder()
dvander@85
    30
  : size_(0)
dvander@85
    31
{
dvander@85
    32
}
dvander@85
    33
dvander@85
    34
bool
dvander@85
    35
StructureBufferBuilder::add(Handle<Type> type, unsigned *offset)
dvander@85
    36
{
dvander@85
    37
    *offset = size_;
dvander@85
    38
dvander@85
    39
    if (!type->isTraceable()) {
dvander@85
    40
        // For now, assume the size of primitives is 4-byte.
dvander@85
    41
        assert(type->isInt32() || type->isFloat());
dvander@85
    42
        size_ += 4;
dvander@85
    43
        return true;
dvander@85
    44
    }
dvander@85
    45
dvander@85
    46
    if (!offsets_.append(size_))
dvander@85
    47
        return false;
dvander@85
    48
dvander@85
    49
    size_ += sizeof(Object *);
dvander@85
    50
    return true;
dvander@85
    51
}
dvander@146
    52
dvander@146
    53
Descriptor *
dvander@195
    54
Descriptor::New(Zone *zone, Handle<String> name, Handle<Type> type)
dvander@146
    55
{
dvander@146
    56
    Local<Descriptor> desc(zone,
dvander@146
    57
        Descriptor::cast(zone->allocate(MapKind_Descriptor, sizeof(Descriptor), Heap::Tenure_Old)));
dvander@146
    58
    if (!desc)
dvander@146
    59
        return NULL;
dvander@146
    60
dvander@146
    61
    desc->name_ = name;
dvander@146
    62
    desc->type_ = type;
dvander@195
    63
    desc->offset_ = unsigned(-1);
dvander@146
    64
    return desc;
dvander@146
    65
}
dvander@146
    66
dvander@147
    67
StructMap *
dvander@195
    68
StructMap::New(Zone *zone, const StructureBufferBuilder &builder, Handle<StructType> type)
dvander@147
    69
{
dvander@195
    70
    Vector<unsigned> composedIndexes;
dvander@195
    71
    for (size_t i = 0; i < type->fields()->length(); i++) {
dvander@195
    72
        Descriptor *desc = Descriptor::cast(type->fields()->at(i));
dvander@195
    73
        if (desc->type()->isArray() || desc->type()->isStruct()) {
dvander@195
    74
            if (!composedIndexes.append(i))
dvander@195
    75
                return NULL;
dvander@195
    76
        }
dvander@195
    77
    }
dvander@195
    78
dvander@195
    79
    Local<FixedArray> composed(zone, FixedArray::New(zone, composedIndexes.length(), Heap::Tenure_Old));
dvander@195
    80
    if (!composed)
dvander@195
    81
        return NULL;
dvander@195
    82
dvander@195
    83
    for (size_t i = 0; i < composedIndexes.length(); i++) {
dvander@195
    84
        Descriptor *desc = Descriptor::cast(type->fields()->at(composedIndexes[i]));
dvander@195
    85
        composed->set(zone, i, desc);
dvander@195
    86
    }
dvander@195
    87
dvander@147
    88
    size_t bytesNeeded = sizeof(StructMap) +
dvander@147
    89
                         (builder.traceableOffsetCount() * sizeof(unsigned));
dvander@147
    90
dvander@147
    91
    Local<StructMap> map(zone);
dvander@147
    92
    map = StructMap::cast(zone->allocateMap(MapKind_Struct, bytesNeeded, MapKind_MetaStruct));
dvander@147
    93
    if (!map)
dvander@147
    94
        return NULL;
dvander@147
    95
dvander@147
    96
    map->structureSize_ = builder.structureSize();
dvander@147
    97
    map->traceOffsetCount_ = builder.traceableOffsetCount();
dvander@195
    98
    map->type_ = type;
dvander@153
    99
    map->composed_ = composed;
dvander@147
   100
    memcpy(const_cast<unsigned *>(map->traceOffsets()), builder.offsets(),
dvander@147
   101
           sizeof(unsigned) * builder.traceableOffsetCount());
dvander@147
   102
dvander@147
   103
    return map;
dvander@147
   104
}
dvander@147
   105
dvander@147
   106
Struct *
dvander@147
   107
Struct::New(Zone *zone, Handle<StructMap> map, Heap::Tenure tenure)
dvander@147
   108
{
dvander@147
   109
    size_t bytesNeeded = sizeof(Struct) + map->structureSize();
dvander@147
   110
    Local<Struct> obj(zone, Struct::cast(zone->allocate(map, bytesNeeded, tenure)));
dvander@147
   111
    if (!obj)
dvander@147
   112
        return NULL;
dvander@147
   113
dvander@147
   114
    memset((Struct *)obj + 1, 0, map->structureSize());
dvander@153
   115
dvander@153
   116
    // Initialize any sub-structures. Right now, this is performed as part of
dvander@153
   117
    // struct allocation, rather than inlined in bytecode, for simplicity.
dvander@153
   118
    if (map->composed()) {
dvander@153
   119
        Local<Descriptor> desc(zone);
dvander@192
   120
        Local<Object> child(zone);
dvander@192
   121
        Local<StructMap> childStructMap(zone);
dvander@192
   122
        Local<ArrayMap> childArrayMap(zone);
dvander@192
   123
dvander@153
   124
        for (unsigned i = 0; i < map->composed()->length(); i++) {
dvander@153
   125
            desc = Descriptor::cast(map->composed()->at(i));
dvander@153
   126
dvander@192
   127
            if (desc->type()->isStruct()) {
dvander@195
   128
                childStructMap = StructMap::cast(StructType::cast(desc->type())->newMap());
dvander@192
   129
                child = Struct::New(zone, childStructMap, tenure);
dvander@192
   130
            } else if (desc->type()->isArray()) {
dvander@195
   131
                assert(false);
dvander@195
   132
#if 0
dvander@192
   133
                childArrayMap = ArrayMap::cast(desc->type()->newMap());
dvander@192
   134
                if (desc->type()->isFixedLength())
dvander@192
   135
                    child = Array::NewFixed(zone, childArrayMap, tenure);
dvander@192
   136
                else
dvander@192
   137
                    child = Array::NewEmpty(zone, childArrayMap, tenure);
dvander@195
   138
#endif
dvander@192
   139
            }
dvander@153
   140
            if (!child)
dvander@153
   141
                return NULL;
dvander@153
   142
dvander@153
   143
            obj->set(zone, desc, child);
dvander@153
   144
        }
dvander@153
   145
    }
dvander@153
   146
dvander@147
   147
    return obj;
dvander@147
   148
}
dvander@147
   149