src/Structures.cpp
author David Anderson <dvander@alliedmods.net>
Sun Nov 18 15:00:08 2012 -0800 (2012-11-18)
changeset 214 e1a6deaa6ebe
parent 195 c1ba166f3fc4
child 234 26e3035cdffc
permissions -rw-r--r--
Fix timeout handling in the test harness.
     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 "Array.h"
    24 #include "Spaces-inl.h"
    25 #include "Heap-inl.h"
    26 
    27 using namespace ke;
    28 
    29 StructureBufferBuilder::StructureBufferBuilder()
    30   : size_(0)
    31 {
    32 }
    33 
    34 bool
    35 StructureBufferBuilder::add(Handle<Type> type, unsigned *offset)
    36 {
    37     *offset = size_;
    38 
    39     if (!type->isTraceable()) {
    40         // For now, assume the size of primitives is 4-byte.
    41         assert(type->isInt32() || type->isFloat());
    42         size_ += 4;
    43         return true;
    44     }
    45 
    46     if (!offsets_.append(size_))
    47         return false;
    48 
    49     size_ += sizeof(Object *);
    50     return true;
    51 }
    52 
    53 Descriptor *
    54 Descriptor::New(Zone *zone, Handle<String> name, Handle<Type> type)
    55 {
    56     Local<Descriptor> desc(zone,
    57         Descriptor::cast(zone->allocate(MapKind_Descriptor, sizeof(Descriptor), Heap::Tenure_Old)));
    58     if (!desc)
    59         return NULL;
    60 
    61     desc->name_ = name;
    62     desc->type_ = type;
    63     desc->offset_ = unsigned(-1);
    64     return desc;
    65 }
    66 
    67 StructMap *
    68 StructMap::New(Zone *zone, const StructureBufferBuilder &builder, Handle<StructType> type)
    69 {
    70     Vector<unsigned> composedIndexes;
    71     for (size_t i = 0; i < type->fields()->length(); i++) {
    72         Descriptor *desc = Descriptor::cast(type->fields()->at(i));
    73         if (desc->type()->isArray() || desc->type()->isStruct()) {
    74             if (!composedIndexes.append(i))
    75                 return NULL;
    76         }
    77     }
    78 
    79     Local<FixedArray> composed(zone, FixedArray::New(zone, composedIndexes.length(), Heap::Tenure_Old));
    80     if (!composed)
    81         return NULL;
    82 
    83     for (size_t i = 0; i < composedIndexes.length(); i++) {
    84         Descriptor *desc = Descriptor::cast(type->fields()->at(composedIndexes[i]));
    85         composed->set(zone, i, desc);
    86     }
    87 
    88     size_t bytesNeeded = sizeof(StructMap) +
    89                          (builder.traceableOffsetCount() * sizeof(unsigned));
    90 
    91     Local<StructMap> map(zone);
    92     map = StructMap::cast(zone->allocateMap(MapKind_Struct, bytesNeeded, MapKind_MetaStruct));
    93     if (!map)
    94         return NULL;
    95 
    96     map->structureSize_ = builder.structureSize();
    97     map->traceOffsetCount_ = builder.traceableOffsetCount();
    98     map->type_ = type;
    99     map->composed_ = composed;
   100     memcpy(const_cast<unsigned *>(map->traceOffsets()), builder.offsets(),
   101            sizeof(unsigned) * builder.traceableOffsetCount());
   102 
   103     return map;
   104 }
   105 
   106 Struct *
   107 Struct::New(Zone *zone, Handle<StructMap> map, Heap::Tenure tenure)
   108 {
   109     size_t bytesNeeded = sizeof(Struct) + map->structureSize();
   110     Local<Struct> obj(zone, Struct::cast(zone->allocate(map, bytesNeeded, tenure)));
   111     if (!obj)
   112         return NULL;
   113 
   114     memset((Struct *)obj + 1, 0, map->structureSize());
   115 
   116     // Initialize any sub-structures. Right now, this is performed as part of
   117     // struct allocation, rather than inlined in bytecode, for simplicity.
   118     if (map->composed()) {
   119         Local<Descriptor> desc(zone);
   120         Local<Object> child(zone);
   121         Local<StructMap> childStructMap(zone);
   122         Local<ArrayMap> childArrayMap(zone);
   123 
   124         for (unsigned i = 0; i < map->composed()->length(); i++) {
   125             desc = Descriptor::cast(map->composed()->at(i));
   126 
   127             if (desc->type()->isStruct()) {
   128                 childStructMap = StructMap::cast(StructType::cast(desc->type())->newMap());
   129                 child = Struct::New(zone, childStructMap, tenure);
   130             } else if (desc->type()->isArray()) {
   131                 assert(false);
   132 #if 0
   133                 childArrayMap = ArrayMap::cast(desc->type()->newMap());
   134                 if (desc->type()->isFixedLength())
   135                     child = Array::NewFixed(zone, childArrayMap, tenure);
   136                 else
   137                     child = Array::NewEmpty(zone, childArrayMap, tenure);
   138 #endif
   139             }
   140             if (!child)
   141                 return NULL;
   142 
   143             obj->set(zone, desc, child);
   144         }
   145     }
   146 
   147     return obj;
   148 }
   149