Normalise line endings.
authorAsher Baker <asherkin@gmail.com>
Mon Jun 10 01:04:43 2013 +0100 (2013-06-10)
changeset 263ba85a47ee414
parent 262 c4b1341297e5
child 264 70b8f318c379
Normalise line endings.
jitcraft.sln
product.version
src/Array.cpp
src/Array.h
src/Code.h
src/CompactBuffer.h
src/Environments.cpp
src/Environments.h
src/Exception.cpp
src/FixedArray.cpp
src/FixedArray.h
src/Functions.cpp
src/Functions.h
src/Interpreter.cpp
src/Interpreter.h
src/Messages.h
src/Modules.cpp
src/Modules.h
src/NativeTable.cpp
src/NativeTable.h
src/OldByCo.cpp
src/OldByCo.h
src/OldSema.cpp
src/OldSema.h
src/Opcodes.cpp
src/Opcodes.h
src/Packages.cpp
src/Packages.h
src/PoolAllocator.cpp
src/PoolAllocator.h
src/Reference.cpp
src/Reference.h
src/RootScopes.h
src/Stack.h
src/StringPool.cpp
src/StringPool.h
src/Strings.cpp
src/Strings.h
src/Structures.cpp
src/Structures.h
src/TypeManager.cpp
src/TypeManager.h
src/Types.cpp
src/Zone.cpp
src/Zone.h
src/compiler/AST.h
src/compiler/BytecodeEmitter.cpp
src/compiler/BytecodeEmitter.h
src/compiler/CompileContext.h
src/compiler/ConstantEvaluator.cpp
src/compiler/ConstantEvaluator.h
src/compiler/HIR.cpp
src/compiler/HIR.h
src/compiler/NameBinding.cpp
src/compiler/NameBinding.h
src/compiler/Parser.cpp
src/compiler/Parser.h
src/compiler/Scanner.cpp
src/compiler/Scanner.h
src/compiler/Scopes.cpp
src/compiler/Scopes.h
src/compiler/SemanticAnalysis.cpp
src/compiler/SemanticAnalysis.h
src/compiler/Symbols.cpp
src/compiler/Symbols.h
src/compiler/Token.h
tests/basic/assignadd.out
tests/basic/assignadd.sp
tests/basic/bitops.out
tests/basic/bitops.sp
tests/basic/break-continue-in-for.out
tests/basic/break-continue-in-for.sp
tests/basic/const-arg-1.err
tests/basic/const-arg-1.sp
tests/basic/const-arg-2.err
tests/basic/const-arg-2.sp
tests/basic/const-arg-3.err
tests/basic/const-arg-3.sp
tests/basic/const-arg-4.err
tests/basic/const-arg-4.sp
tests/basic/const-arg-5.out
tests/basic/const-arg-5.sp
tests/basic/const-global-1.err
tests/basic/const-global-1.sp
tests/basic/const-global-2.err
tests/basic/const-global-2.sp
tests/basic/const-global-3.err
tests/basic/const-global-3.sp
tests/basic/const-local-1.err
tests/basic/const-local-1.sp
tests/basic/const-local-2.err
tests/basic/const-local-2.sp
tests/basic/const-local-3.out
tests/basic/const-local-3.sp
tests/basic/continue-in-while.out
tests/basic/continue-in-while.sp
tests/basic/decl-void.err
tests/basic/decl-void.sp
tests/basic/dependent-strings.out
tests/basic/dependent-strings.sp
tests/basic/divide-by-zero.err
tests/basic/divide-by-zero.sp
tests/basic/do.out
tests/basic/do.sp
tests/basic/enum-bad.err
tests/basic/enum-bad.sp
tests/basic/enum-redecl.err
tests/basic/enum-redecl.sp
tests/basic/enum-use.out
tests/basic/enum-use.sp
tests/basic/float-arrays.out
tests/basic/float-arrays.sp
tests/basic/floats.out
tests/basic/floats.sp
tests/basic/import-sysroot-all.out
tests/basic/import-sysroot-all.sp
tests/basic/import-sysroot-module.out
tests/basic/import-sysroot-module.sp
tests/basic/import-sysroot-select.out
tests/basic/import-sysroot-select.sp
tests/basic/import_enum_a.out
tests/basic/import_enum_a.sp
tests/basic/import_enum_b.sp
tests/basic/passarray.out
tests/basic/passarray.sp
tests/basic/postinc-array.out
tests/basic/postinc-array.sp
tests/basic/postinc-local.out
tests/basic/postinc-local.sp
tests/basic/postinc-ref.out
tests/basic/postinc-ref.sp
tests/basic/precall-void-used.out
tests/basic/precall-void-used.sp
tests/basic/preinc-array.out
tests/basic/preinc-array.sp
tests/basic/preinc-local.out
tests/basic/preinc-local.sp
tests/basic/preinc-ref.out
tests/basic/preinc-ref.sp
tests/basic/recursive_import_1_a.out
tests/basic/recursive_import_1_a.sp
tests/basic/recursive_import_1_b.sp
tests/basic/ref-arg.out
tests/basic/ref-arg.sp
tests/basic/ref-expr.out
tests/basic/ref-expr.sp
tests/basic/ref-var.out
tests/basic/ref-var.sp
tests/basic/return-analyze-for-1.sp
tests/basic/return-analyze-for-2.out
tests/basic/return-analyze-for-2.sp
tests/basic/return-analyze-for-3.err
tests/basic/return-analyze-for-3.sp
tests/basic/return-analyze-for-4.err
tests/basic/return-analyze-for-4.sp
tests/basic/return-analyze-for-5.out
tests/basic/return-analyze-for-5.sp
tests/basic/return-analyze-if-1.out
tests/basic/return-analyze-if-1.sp
tests/basic/return-analyze-if-2.err
tests/basic/return-analyze-if-2.sp
tests/basic/return-analyze-if-3.out
tests/basic/return-analyze-if-3.sp
tests/basic/return-analyze-if-4.err
tests/basic/return-analyze-if-4.sp
tests/basic/return-analyze-if-5.out
tests/basic/return-analyze-if-5.sp
tests/basic/shell.sp
tests/basic/string-lit-1.out
tests/basic/string-lit-1.sp
tests/basic/string-lit-2.out
tests/basic/string-lit-2.sp
tests/basic/while.out
tests/basic/while.sp
tests/display.py
tests/harness.py
tests/prototype/string-1.sp
tests/ref-array.sp
tests/test.py
     1.1 --- a/jitcraft.sln	Mon Jun 10 00:46:29 2013 +0100
     1.2 +++ b/jitcraft.sln	Mon Jun 10 01:04:43 2013 +0100
     1.3 @@ -1,23 +1,23 @@
     1.4 -
     1.5 -Microsoft Visual Studio Solution File, Format Version 11.00
     1.6 -# Visual C++ Express 2010
     1.7 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jitcraft", "src\jitcraft.vcxproj", "{E12034DC-E8CB-4B49-AC0A-0D27CDED9A50}"
     1.8 -EndProject
     1.9 -Global
    1.10 -	GlobalSection(SolutionConfigurationPlatforms) = preSolution
    1.11 -		Debug - Library|Win32 = Debug - Library|Win32
    1.12 -		Debug|Win32 = Debug|Win32
    1.13 -		Release|Win32 = Release|Win32
    1.14 -	EndGlobalSection
    1.15 -	GlobalSection(ProjectConfigurationPlatforms) = postSolution
    1.16 -		{E12034DC-E8CB-4B49-AC0A-0D27CDED9A50}.Debug - Library|Win32.ActiveCfg = Debug - Library|Win32
    1.17 -		{E12034DC-E8CB-4B49-AC0A-0D27CDED9A50}.Debug - Library|Win32.Build.0 = Debug - Library|Win32
    1.18 -		{E12034DC-E8CB-4B49-AC0A-0D27CDED9A50}.Debug|Win32.ActiveCfg = Debug|Win32
    1.19 -		{E12034DC-E8CB-4B49-AC0A-0D27CDED9A50}.Debug|Win32.Build.0 = Debug|Win32
    1.20 -		{E12034DC-E8CB-4B49-AC0A-0D27CDED9A50}.Release|Win32.ActiveCfg = Release|Win32
    1.21 -		{E12034DC-E8CB-4B49-AC0A-0D27CDED9A50}.Release|Win32.Build.0 = Release|Win32
    1.22 -	EndGlobalSection
    1.23 -	GlobalSection(SolutionProperties) = preSolution
    1.24 -		HideSolutionNode = FALSE
    1.25 -	EndGlobalSection
    1.26 -EndGlobal
    1.27 +
    1.28 +Microsoft Visual Studio Solution File, Format Version 11.00
    1.29 +# Visual C++ Express 2010
    1.30 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jitcraft", "src\jitcraft.vcxproj", "{E12034DC-E8CB-4B49-AC0A-0D27CDED9A50}"
    1.31 +EndProject
    1.32 +Global
    1.33 +	GlobalSection(SolutionConfigurationPlatforms) = preSolution
    1.34 +		Debug - Library|Win32 = Debug - Library|Win32
    1.35 +		Debug|Win32 = Debug|Win32
    1.36 +		Release|Win32 = Release|Win32
    1.37 +	EndGlobalSection
    1.38 +	GlobalSection(ProjectConfigurationPlatforms) = postSolution
    1.39 +		{E12034DC-E8CB-4B49-AC0A-0D27CDED9A50}.Debug - Library|Win32.ActiveCfg = Debug - Library|Win32
    1.40 +		{E12034DC-E8CB-4B49-AC0A-0D27CDED9A50}.Debug - Library|Win32.Build.0 = Debug - Library|Win32
    1.41 +		{E12034DC-E8CB-4B49-AC0A-0D27CDED9A50}.Debug|Win32.ActiveCfg = Debug|Win32
    1.42 +		{E12034DC-E8CB-4B49-AC0A-0D27CDED9A50}.Debug|Win32.Build.0 = Debug|Win32
    1.43 +		{E12034DC-E8CB-4B49-AC0A-0D27CDED9A50}.Release|Win32.ActiveCfg = Release|Win32
    1.44 +		{E12034DC-E8CB-4B49-AC0A-0D27CDED9A50}.Release|Win32.Build.0 = Release|Win32
    1.45 +	EndGlobalSection
    1.46 +	GlobalSection(SolutionProperties) = preSolution
    1.47 +		HideSolutionNode = FALSE
    1.48 +	EndGlobalSection
    1.49 +EndGlobal
     2.1 --- a/product.version	Mon Jun 10 00:46:29 2013 +0100
     2.2 +++ b/product.version	Mon Jun 10 01:04:43 2013 +0100
     2.3 @@ -1,1 +1,1 @@
     2.4 -0.0.2-alpha
     2.5 +0.0.2-alpha
     3.1 --- a/src/Array.cpp	Mon Jun 10 00:46:29 2013 +0100
     3.2 +++ b/src/Array.cpp	Mon Jun 10 01:04:43 2013 +0100
     3.3 @@ -1,378 +1,378 @@
     3.4 -/* vim: set ts=4 sw=4 tw=99 et:
     3.5 - *
     3.6 - * Copyright (C) 2012 David Anderson
     3.7 - *
     3.8 - * This file is part of SourcePawn.
     3.9 - *
    3.10 - * SourcePawn is free software: you can redistribute it and/or modify it under
    3.11 - * the terms of the GNU General Public License as published by the Free
    3.12 - * Software Foundation, either version 3 of the License, or (at your option)
    3.13 - * any later version.
    3.14 - * 
    3.15 - * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
    3.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    3.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    3.18 - *
    3.19 - * You should have received a copy of the GNU General Public License along with
    3.20 - * SourcePawn. If not, see http://www.gnu.org/licenses/.
    3.21 - */
    3.22 -#include <string.h>
    3.23 -#include "Array.h"
    3.24 -#include "FixedArray.h"
    3.25 -#include "Heap.h"
    3.26 -#include "Zone.h"
    3.27 -#include "Structures.h"
    3.28 -#include "Heap-inl.h"
    3.29 -
    3.30 -using namespace ke;
    3.31 -
    3.32 -ArrayMap *
    3.33 -ArrayMap::New(Zone *zone, Handle<ArrayType> type)
    3.34 -{
    3.35 -    Local<Map> obj(zone, zone->allocateMap(MapKind_Array, sizeof(ArrayMap), MapKind_MetaArray));
    3.36 -    if (!obj)
    3.37 -        return NULL;
    3.38 -
    3.39 -    Local<ArrayMap> map(zone, ArrayMap::cast(obj));
    3.40 -    map->type_ = type;
    3.41 -    return map;
    3.42 -}
    3.43 -
    3.44 -ArrayMap *
    3.45 -ArrayMap::NewDependent(Zone *zone, Handle<ArrayType> type)
    3.46 -{
    3.47 -    Local<Map> obj(zone, zone->allocateMap(MapKind_DependentArray, sizeof(ArrayMap), MapKind_MetaArray));
    3.48 -    if (!obj)
    3.49 -        return NULL;
    3.50 -
    3.51 -    Local<ArrayMap> map(zone, ArrayMap::cast(obj));
    3.52 -    map->type_ = type;
    3.53 -    return map;
    3.54 -}
    3.55 -
    3.56 -Array *
    3.57 -Array::NewRaw(Zone *zone, Handle<ArrayMap> map, unsigned nelements, Heap::Tenure tenure)
    3.58 -{
    3.59 -    assert(!map->type()->isFixedLength() || nelements == map->type()->fixedLength());
    3.60 -
    3.61 -    if (nelements > (INT_MAX / SizeForElement(map->type()))) {
    3.62 -        zone->reportError(Message_ArraySizeTooBig);
    3.63 -        return NULL;
    3.64 -    }
    3.65 -
    3.66 -    size_t bytes = sizeof(Array);
    3.67 -    if (map->type()->hasInlineElements())
    3.68 -        bytes += SizeForElement(map->type()) * nelements;
    3.69 -
    3.70 -    Local<Array> array(zone, Array::cast(zone->allocate(map, bytes, tenure)));
    3.71 -    if (!array)
    3.72 -        return NULL;
    3.73 -
    3.74 -    array->length_ = 0;
    3.75 -    array->elements_ = NULL;
    3.76 -
    3.77 -    if (map->type()->hasInlineElements()) {
    3.78 -        // This must be a fixed array containing no traceables.
    3.79 -        assert(nelements > 0);
    3.80 -        assert(map->type()->isFixedLength());
    3.81 -        assert(!map->type()->contained()->isTraceable());
    3.82 -
    3.83 -        // Compute an interior |elements_| pointer, such that if elements_
    3.84 -        // is accessed like a FixedArray, we reach the appropriate vector.
    3.85 -        array->elements_ = Address((Array *)array + 1) - ByteArray::offsetToElements();
    3.86 -        array->length_ = nelements;
    3.87 -        memset(array->bytes(), 0, SizeForElement(map->type()) * nelements);
    3.88 -        return array;
    3.89 -    }
    3.90 -
    3.91 -    // If there is nothing to allocate, we don't bother creating elements yet.
    3.92 -    if (!nelements)
    3.93 -        return array;
    3.94 -
    3.95 -    if (!map->type()->contained()->isTraceable()) {
    3.96 -        size_t nbytes = SizeForElement(map->type()) * nelements;
    3.97 -        Local<ByteArray> elements(zone, ByteArray::New(zone, nbytes, tenure));
    3.98 -        if (!elements)
    3.99 -            return NULL;
   3.100 -
   3.101 -        array->updateLengthAndElements(zone, nelements, elements);
   3.102 -        return array;
   3.103 -    }
   3.104 -
   3.105 -    Local<FixedArray> elements(zone, FixedArray::New(zone, nelements, tenure));
   3.106 -    if (!elements)
   3.107 -        return NULL;
   3.108 -
   3.109 -    array->updateLengthAndElements(zone, nelements, elements);
   3.110 -
   3.111 -    // If this is an array of structs, we're required to allocate those structs now.
   3.112 -    if (map->type()->contained()->isStruct()) {
   3.113 -        Local<StructType> childType(zone, StructType::cast(map->type()->contained()));
   3.114 -        Local<StructMap> childMap(zone, childType->newMap());
   3.115 -        Local<Struct> child(zone);
   3.116 -        for (unsigned i = 0; i < nelements; i++) {
   3.117 -            child = Struct::New(zone, childMap, tenure);
   3.118 -            if (!child)
   3.119 -                return NULL;
   3.120 -
   3.121 -            elements->set(zone, i, child);
   3.122 -        }
   3.123 -    }
   3.124 -
   3.125 -    return array;
   3.126 -}
   3.127 -
   3.128 -static Array *
   3.129 -ConstructSizedArray(Zone *zone, Handle<ArrayMap> map, int dims[MAX_ARRAY_DEPTH],
   3.130 -                    unsigned level, Heap::Tenure tenure)
   3.131 -{
   3.132 -    Local<Array> array(zone, Array::NewRaw(zone, map, dims[level], tenure));
   3.133 -    if (!array)
   3.134 -        return NULL;
   3.135 -
   3.136 -    if (map->type()->contained()->isArray()) {
   3.137 -        Local<ArrayType> childType(zone, ArrayType::cast(map->type()->contained()));
   3.138 -        Local<ArrayMap> childMap(zone, childType->newMap());
   3.139 -        Local<Array> child(zone);
   3.140 -
   3.141 -        for (unsigned i = 0; i < unsigned(dims[level]); i++) {
   3.142 -            child = ConstructSizedArray(zone, childMap, dims, level + 1, tenure);
   3.143 -            if (!child)
   3.144 -                return NULL;
   3.145 -
   3.146 -            array->writeObject(zone, i, child);
   3.147 -        }
   3.148 -    }
   3.149 -
   3.150 -    return array;
   3.151 -}
   3.152 -
   3.153 -Array *
   3.154 -Array::NewSized(Zone *zone, Handle<ArrayMap> map, int dims[MAX_ARRAY_DEPTH], Heap::Tenure tenure)
   3.155 -{
   3.156 -    for (size_t i = 0; i < map->type()->levels(); i++) {
   3.157 -        if (dims[i] < 0) {
   3.158 -            zone->reportError(Message_InvalidDimensionSize, dims[i], i);
   3.159 -            return NULL;
   3.160 -        }
   3.161 -    }
   3.162 -
   3.163 -    return ConstructSizedArray(zone, map, dims, 0, tenure);
   3.164 -}
   3.165 -
   3.166 -static Array *
   3.167 -ConstructFixedArray(Zone *zone, Handle<ArrayMap> map, Heap::Tenure tenure)
   3.168 -{
   3.169 -    unsigned length = map->type()->fixedLength();
   3.170 -    Local<Array> array(zone, Array::NewRaw(zone, map, length, tenure));
   3.171 -    if (!array)
   3.172 -        return NULL;
   3.173 -
   3.174 -    if (map->type()->contained()->isArray()) {
   3.175 -        Local<ArrayType> childType(zone, ArrayType::cast(map->type()->contained()));
   3.176 -        Local<ArrayMap> childMap(zone, childType->newMap());
   3.177 -        Local<Array> child(zone);
   3.178 -
   3.179 -        if (childMap->type()->isFixedLength()) {
   3.180 -            for (unsigned i = 0; i < length; i++) {
   3.181 -                child = ConstructFixedArray(zone, childMap, tenure);
   3.182 -                if (!child)
   3.183 -                    return NULL;
   3.184 -
   3.185 -                array->writeObject(zone, i, child);
   3.186 -            }
   3.187 -        } else {
   3.188 -            for (unsigned i = 0; i < length; i++) {
   3.189 -                child = Array::NewRaw(zone, childMap, 0, tenure);
   3.190 -                if (!child)
   3.191 -                    return NULL;
   3.192 -
   3.193 -                array->writeObject(zone, i, child);
   3.194 -            }
   3.195 -        }
   3.196 -    }
   3.197 -
   3.198 -    return array;
   3.199 -}
   3.200 -
   3.201 -Array *
   3.202 -Array::NewFixed(Zone *zone, Handle<ArrayMap> map, Heap::Tenure tenure)
   3.203 -{
   3.204 -    return ConstructFixedArray(zone, map, tenure);
   3.205 -}
   3.206 -
   3.207 -Array *
   3.208 -Array::NewString(Zone *zone, Handle<ArrayMap> map, char *buffer, size_t length, Heap::Tenure tenure)
   3.209 -{
   3.210 -    assert(map->type()->isCharArray());
   3.211 -
   3.212 -    Local<Array> array(zone);
   3.213 -    
   3.214 -    if (map->type()->isFixedLength())
   3.215 -        array = Array::NewFixed(zone, map, tenure);
   3.216 -    else
   3.217 -        array = Array::New1D(zone, map, length + 1, tenure);
   3.218 -    if (!array)
   3.219 -        return NULL;
   3.220 -
   3.221 -    assert(array->length() >= length + 1);
   3.222 -    memcpy(array->chars(), buffer, length + 1);
   3.223 -    return array;
   3.224 -}
   3.225 -
   3.226 -Array *
   3.227 -Array::New1D(Zone *zone, Handle<ArrayMap> map, uint32 elements, Heap::Tenure tenure)
   3.228 -{
   3.229 -    assert(map->type()->levels());
   3.230 -    return Array::NewRaw(zone, map, elements, tenure);
   3.231 -}
   3.232 -
   3.233 -Array *
   3.234 -Array::NewEmpty(Zone *zone, Handle<ArrayMap> map, Heap::Tenure tenure)
   3.235 -{
   3.236 -    assert(!map->type()->isFixedLength());
   3.237 -
   3.238 -    return Array::NewRaw(zone, map, 0, tenure);
   3.239 -}
   3.240 -
   3.241 -Array *
   3.242 -Array::NewExternal(Zone *zone, Handle<ArrayMap> map, void *buffer, unsigned length,
   3.243 -                   Heap::Tenure tenure)
   3.244 -{
   3.245 -    Local<Array> array(zone, Array::cast(zone->allocate(map, sizeof(Array), tenure)));
   3.246 -    if (!array)
   3.247 -        return NULL;
   3.248 -
   3.249 -    array->length_ = length;
   3.250 -    array->elements_ = Address(buffer) - ByteArray::offsetToElements();
   3.251 -    return array;
   3.252 -}
   3.253 -
   3.254 -static bool
   3.255 -CopyArrayElements(Zone *zone, Handle<Type> contained, Handle<Array> dest, Handle<Array> source)
   3.256 -{
   3.257 -    if (contained->isTraceable()) {
   3.258 -        if (contained->isStruct()) {
   3.259 -            assert(dest->type()->contained() == contained);
   3.260 -            assert(source->length() == dest->length());
   3.261 -
   3.262 -            Local<Struct> left(zone);
   3.263 -            Local<Struct> right(zone);
   3.264 -            for (unsigned i = 0; i < source->length(); i++) {
   3.265 -                left = Struct::cast(dest->readObject(i));
   3.266 -                right = Struct::cast(source->readObject(i));
   3.267 -                if (!Struct::Copy(zone, left, right))
   3.268 -                    return false;
   3.269 -            }
   3.270 -        } else if (contained->isArray() && ArrayType::cast(contained)->isFixedLength()) {
   3.271 -            assert(ArrayType::cast(source->type())->fixedLength() ==
   3.272 -                   ArrayType::cast(contained)->fixedLength());
   3.273 -
   3.274 -            Local<Array> left(zone);
   3.275 -            Local<Array> right(zone);
   3.276 -            for (unsigned i = 0; i < source->length(); i++) {
   3.277 -                left = Array::cast(dest->readObject(i));
   3.278 -                right = Array::cast(source->readObject(i));
   3.279 -                if (!Array::ShallowCopy(zone, left, right))
   3.280 -                    return false;
   3.281 -            }
   3.282 -        } else {
   3.283 -            assert(dest->length() == source->length());
   3.284 -            for (unsigned i = 0; i < source->length(); i++)
   3.285 -                dest->writeObject(zone, i, source->readObject(i));
   3.286 -        }
   3.287 -    } else {
   3.288 -        assert(contained->pod() == dest->type()->contained()->pod());
   3.289 -        assert(contained->pod() == PrimitiveType_Char
   3.290 -               ? source->length() <= dest->length()
   3.291 -               : source->length() == dest->length());
   3.292 -    
   3.293 -        assert(dest->length());
   3.294 -        memcpy(dest->bytes(), source->bytes(), source->length() * Array::SizeForElement(dest->type()));
   3.295 -    }
   3.296 -    return true;
   3.297 -}
   3.298 -
   3.299 -// Shallow copy an array. Fixed slots in the destination are copied from
   3.300 -// the source, but otherwise, references are assigned.
   3.301 -bool
   3.302 -Array::ShallowCopy(Zone *zone, Handle<Array> dest, Handle<Array> source)
   3.303 -{
   3.304 -    Local<Type> contained(zone, dest->type()->contained());
   3.305 -
   3.306 -    return CopyArrayElements(zone, contained, dest, source);
   3.307 -}
   3.308 -
   3.309 -Array *
   3.310 -Array::DeepCopy(Zone *zone, Handle<Array> source, Heap::Tenure tenure)
   3.311 -{
   3.312 -    Local<ArrayMap> map(zone, ArrayMap::cast(source->map()));
   3.313 -
   3.314 -    Local<Array> dest(zone, Array::NewRaw(zone, map, source->length(), tenure));
   3.315 -    if (!dest)
   3.316 -        return NULL;
   3.317 -
   3.318 -    Local<Type> contained(zone, source->type()->contained());
   3.319 -    if (contained->isArray()) {
   3.320 -        assert(false);
   3.321 -        Local<Array> sub(zone);
   3.322 -        for (size_t i = 0; i < source->length(); i++) {
   3.323 -            sub = Array::cast(source->readObject(i));
   3.324 -            sub = DeepCopy(zone, sub, tenure);
   3.325 -            if (!sub)
   3.326 -                return NULL;
   3.327 -            dest->writeObject(zone, i, sub);
   3.328 -        }
   3.329 -    } else {
   3.330 -        if (!CopyArrayElements(zone, contained, dest, source))
   3.331 -            return NULL;
   3.332 -    }
   3.333 -
   3.334 -    return dest;
   3.335 -}
   3.336 -
   3.337 -Array *
   3.338 -DependentArray::New(Zone *zone, Handle<Array> source, Handle<ArrayMap> map, unsigned index)
   3.339 -{
   3.340 -    Local<ArrayType> sourcetype(zone, source->type());
   3.341 -
   3.342 -    // Right now we only support char arrays, to avoid nasty deep cloning
   3.343 -    // and to maybe cut off this feature as far as we can.
   3.344 -    assert(sourcetype->isCharArray());
   3.345 -    assert(map->type()->isCharArray());
   3.346 -
   3.347 -    // We allow taking 0-length dependent strings. It's safe because any reads
   3.348 -    // or writes will fail.
   3.349 -    assert(index <= source->length());
   3.350 -
   3.351 -    unsigned newlen = source->length() - index;
   3.352 -    unsigned eltsize = SizeForElement(sourcetype);
   3.353 -    
   3.354 -    if (!sourcetype->isFixedLength()) {
   3.355 -        // Simple case, just copy the array.
   3.356 -        Local<ArrayMap> map(zone, sourcetype->newMap());
   3.357 -        
   3.358 -        Local<Array> dest(zone, Array::NewRaw(zone, map, newlen, Heap::Tenure_Default));
   3.359 -        if (!dest)
   3.360 -            return NULL;
   3.361 -
   3.362 -        memcpy(dest->bytes(),
   3.363 -               (Address)source->bytes() + (index * eltsize),
   3.364 -               newlen * eltsize);
   3.365 -        return dest;
   3.366 -    }
   3.367 -
   3.368 -    Local<DependentArray> array(zone, DependentArray::cast(zone->allocate(map, sizeof(DependentArray), Heap::Tenure_Default)));
   3.369 -    if (!array)
   3.370 -        return NULL;
   3.371 -
   3.372 -    // :GC: This is currently not safe for moving GC! Although we will mark
   3.373 -    // the object owning the interior pointer, the interior pointer could be
   3.374 -    // moved later. We will eventually need some way of dealing with this.
   3.375 -    Address elements = Address(source->bytes()) + (index * eltsize);
   3.376 -
   3.377 -    array->root_ = source;
   3.378 -    array->length_ = newlen;
   3.379 -    array->elements_ = elements - ByteArray::offsetToElements();
   3.380 -    return array;
   3.381 -}
   3.382 +/* vim: set ts=4 sw=4 tw=99 et:
   3.383 + *
   3.384 + * Copyright (C) 2012 David Anderson
   3.385 + *
   3.386 + * This file is part of SourcePawn.
   3.387 + *
   3.388 + * SourcePawn is free software: you can redistribute it and/or modify it under
   3.389 + * the terms of the GNU General Public License as published by the Free
   3.390 + * Software Foundation, either version 3 of the License, or (at your option)
   3.391 + * any later version.
   3.392 + * 
   3.393 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
   3.394 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   3.395 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   3.396 + *
   3.397 + * You should have received a copy of the GNU General Public License along with
   3.398 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
   3.399 + */
   3.400 +#include <string.h>
   3.401 +#include "Array.h"
   3.402 +#include "FixedArray.h"
   3.403 +#include "Heap.h"
   3.404 +#include "Zone.h"
   3.405 +#include "Structures.h"
   3.406 +#include "Heap-inl.h"
   3.407 +
   3.408 +using namespace ke;
   3.409 +
   3.410 +ArrayMap *
   3.411 +ArrayMap::New(Zone *zone, Handle<ArrayType> type)
   3.412 +{
   3.413 +    Local<Map> obj(zone, zone->allocateMap(MapKind_Array, sizeof(ArrayMap), MapKind_MetaArray));
   3.414 +    if (!obj)
   3.415 +        return NULL;
   3.416 +
   3.417 +    Local<ArrayMap> map(zone, ArrayMap::cast(obj));
   3.418 +    map->type_ = type;
   3.419 +    return map;
   3.420 +}
   3.421 +
   3.422 +ArrayMap *
   3.423 +ArrayMap::NewDependent(Zone *zone, Handle<ArrayType> type)
   3.424 +{
   3.425 +    Local<Map> obj(zone, zone->allocateMap(MapKind_DependentArray, sizeof(ArrayMap), MapKind_MetaArray));
   3.426 +    if (!obj)
   3.427 +        return NULL;
   3.428 +
   3.429 +    Local<ArrayMap> map(zone, ArrayMap::cast(obj));
   3.430 +    map->type_ = type;
   3.431 +    return map;
   3.432 +}
   3.433 +
   3.434 +Array *
   3.435 +Array::NewRaw(Zone *zone, Handle<ArrayMap> map, unsigned nelements, Heap::Tenure tenure)
   3.436 +{
   3.437 +    assert(!map->type()->isFixedLength() || nelements == map->type()->fixedLength());
   3.438 +
   3.439 +    if (nelements > (INT_MAX / SizeForElement(map->type()))) {
   3.440 +        zone->reportError(Message_ArraySizeTooBig);
   3.441 +        return NULL;
   3.442 +    }
   3.443 +
   3.444 +    size_t bytes = sizeof(Array);
   3.445 +    if (map->type()->hasInlineElements())
   3.446 +        bytes += SizeForElement(map->type()) * nelements;
   3.447 +
   3.448 +    Local<Array> array(zone, Array::cast(zone->allocate(map, bytes, tenure)));
   3.449 +    if (!array)
   3.450 +        return NULL;
   3.451 +
   3.452 +    array->length_ = 0;
   3.453 +    array->elements_ = NULL;
   3.454 +
   3.455 +    if (map->type()->hasInlineElements()) {
   3.456 +        // This must be a fixed array containing no traceables.
   3.457 +        assert(nelements > 0);
   3.458 +        assert(map->type()->isFixedLength());
   3.459 +        assert(!map->type()->contained()->isTraceable());
   3.460 +
   3.461 +        // Compute an interior |elements_| pointer, such that if elements_
   3.462 +        // is accessed like a FixedArray, we reach the appropriate vector.
   3.463 +        array->elements_ = Address((Array *)array + 1) - ByteArray::offsetToElements();
   3.464 +        array->length_ = nelements;
   3.465 +        memset(array->bytes(), 0, SizeForElement(map->type()) * nelements);
   3.466 +        return array;
   3.467 +    }
   3.468 +
   3.469 +    // If there is nothing to allocate, we don't bother creating elements yet.
   3.470 +    if (!nelements)
   3.471 +        return array;
   3.472 +
   3.473 +    if (!map->type()->contained()->isTraceable()) {
   3.474 +        size_t nbytes = SizeForElement(map->type()) * nelements;
   3.475 +        Local<ByteArray> elements(zone, ByteArray::New(zone, nbytes, tenure));
   3.476 +        if (!elements)
   3.477 +            return NULL;
   3.478 +
   3.479 +        array->updateLengthAndElements(zone, nelements, elements);
   3.480 +        return array;
   3.481 +    }
   3.482 +
   3.483 +    Local<FixedArray> elements(zone, FixedArray::New(zone, nelements, tenure));
   3.484 +    if (!elements)
   3.485 +        return NULL;
   3.486 +
   3.487 +    array->updateLengthAndElements(zone, nelements, elements);
   3.488 +
   3.489 +    // If this is an array of structs, we're required to allocate those structs now.
   3.490 +    if (map->type()->contained()->isStruct()) {
   3.491 +        Local<StructType> childType(zone, StructType::cast(map->type()->contained()));
   3.492 +        Local<StructMap> childMap(zone, childType->newMap());
   3.493 +        Local<Struct> child(zone);
   3.494 +        for (unsigned i = 0; i < nelements; i++) {
   3.495 +            child = Struct::New(zone, childMap, tenure);
   3.496 +            if (!child)
   3.497 +                return NULL;
   3.498 +
   3.499 +            elements->set(zone, i, child);
   3.500 +        }
   3.501 +    }
   3.502 +
   3.503 +    return array;
   3.504 +}
   3.505 +
   3.506 +static Array *
   3.507 +ConstructSizedArray(Zone *zone, Handle<ArrayMap> map, int dims[MAX_ARRAY_DEPTH],
   3.508 +                    unsigned level, Heap::Tenure tenure)
   3.509 +{
   3.510 +    Local<Array> array(zone, Array::NewRaw(zone, map, dims[level], tenure));
   3.511 +    if (!array)
   3.512 +        return NULL;
   3.513 +
   3.514 +    if (map->type()->contained()->isArray()) {
   3.515 +        Local<ArrayType> childType(zone, ArrayType::cast(map->type()->contained()));
   3.516 +        Local<ArrayMap> childMap(zone, childType->newMap());
   3.517 +        Local<Array> child(zone);
   3.518 +
   3.519 +        for (unsigned i = 0; i < unsigned(dims[level]); i++) {
   3.520 +            child = ConstructSizedArray(zone, childMap, dims, level + 1, tenure);
   3.521 +            if (!child)
   3.522 +                return NULL;
   3.523 +
   3.524 +            array->writeObject(zone, i, child);
   3.525 +        }
   3.526 +    }
   3.527 +
   3.528 +    return array;
   3.529 +}
   3.530 +
   3.531 +Array *
   3.532 +Array::NewSized(Zone *zone, Handle<ArrayMap> map, int dims[MAX_ARRAY_DEPTH], Heap::Tenure tenure)
   3.533 +{
   3.534 +    for (size_t i = 0; i < map->type()->levels(); i++) {
   3.535 +        if (dims[i] < 0) {
   3.536 +            zone->reportError(Message_InvalidDimensionSize, dims[i], i);
   3.537 +            return NULL;
   3.538 +        }
   3.539 +    }
   3.540 +
   3.541 +    return ConstructSizedArray(zone, map, dims, 0, tenure);
   3.542 +}
   3.543 +
   3.544 +static Array *
   3.545 +ConstructFixedArray(Zone *zone, Handle<ArrayMap> map, Heap::Tenure tenure)
   3.546 +{
   3.547 +    unsigned length = map->type()->fixedLength();
   3.548 +    Local<Array> array(zone, Array::NewRaw(zone, map, length, tenure));
   3.549 +    if (!array)
   3.550 +        return NULL;
   3.551 +
   3.552 +    if (map->type()->contained()->isArray()) {
   3.553 +        Local<ArrayType> childType(zone, ArrayType::cast(map->type()->contained()));
   3.554 +        Local<ArrayMap> childMap(zone, childType->newMap());
   3.555 +        Local<Array> child(zone);
   3.556 +
   3.557 +        if (childMap->type()->isFixedLength()) {
   3.558 +            for (unsigned i = 0; i < length; i++) {
   3.559 +                child = ConstructFixedArray(zone, childMap, tenure);
   3.560 +                if (!child)
   3.561 +                    return NULL;
   3.562 +
   3.563 +                array->writeObject(zone, i, child);
   3.564 +            }
   3.565 +        } else {
   3.566 +            for (unsigned i = 0; i < length; i++) {
   3.567 +                child = Array::NewRaw(zone, childMap, 0, tenure);
   3.568 +                if (!child)
   3.569 +                    return NULL;
   3.570 +
   3.571 +                array->writeObject(zone, i, child);
   3.572 +            }
   3.573 +        }
   3.574 +    }
   3.575 +
   3.576 +    return array;
   3.577 +}
   3.578 +
   3.579 +Array *
   3.580 +Array::NewFixed(Zone *zone, Handle<ArrayMap> map, Heap::Tenure tenure)
   3.581 +{
   3.582 +    return ConstructFixedArray(zone, map, tenure);
   3.583 +}
   3.584 +
   3.585 +Array *
   3.586 +Array::NewString(Zone *zone, Handle<ArrayMap> map, char *buffer, size_t length, Heap::Tenure tenure)
   3.587 +{
   3.588 +    assert(map->type()->isCharArray());
   3.589 +
   3.590 +    Local<Array> array(zone);
   3.591 +    
   3.592 +    if (map->type()->isFixedLength())
   3.593 +        array = Array::NewFixed(zone, map, tenure);
   3.594 +    else
   3.595 +        array = Array::New1D(zone, map, length + 1, tenure);
   3.596 +    if (!array)
   3.597 +        return NULL;
   3.598 +
   3.599 +    assert(array->length() >= length + 1);
   3.600 +    memcpy(array->chars(), buffer, length + 1);
   3.601 +    return array;
   3.602 +}
   3.603 +
   3.604 +Array *
   3.605 +Array::New1D(Zone *zone, Handle<ArrayMap> map, uint32 elements, Heap::Tenure tenure)
   3.606 +{
   3.607 +    assert(map->type()->levels());
   3.608 +    return Array::NewRaw(zone, map, elements, tenure);
   3.609 +}
   3.610 +
   3.611 +Array *
   3.612 +Array::NewEmpty(Zone *zone, Handle<ArrayMap> map, Heap::Tenure tenure)
   3.613 +{
   3.614 +    assert(!map->type()->isFixedLength());
   3.615 +
   3.616 +    return Array::NewRaw(zone, map, 0, tenure);
   3.617 +}
   3.618 +
   3.619 +Array *
   3.620 +Array::NewExternal(Zone *zone, Handle<ArrayMap> map, void *buffer, unsigned length,
   3.621 +                   Heap::Tenure tenure)
   3.622 +{
   3.623 +    Local<Array> array(zone, Array::cast(zone->allocate(map, sizeof(Array), tenure)));
   3.624 +    if (!array)
   3.625 +        return NULL;
   3.626 +
   3.627 +    array->length_ = length;
   3.628 +    array->elements_ = Address(buffer) - ByteArray::offsetToElements();
   3.629 +    return array;
   3.630 +}
   3.631 +
   3.632 +static bool
   3.633 +CopyArrayElements(Zone *zone, Handle<Type> contained, Handle<Array> dest, Handle<Array> source)
   3.634 +{
   3.635 +    if (contained->isTraceable()) {
   3.636 +        if (contained->isStruct()) {
   3.637 +            assert(dest->type()->contained() == contained);
   3.638 +            assert(source->length() == dest->length());
   3.639 +
   3.640 +            Local<Struct> left(zone);
   3.641 +            Local<Struct> right(zone);
   3.642 +            for (unsigned i = 0; i < source->length(); i++) {
   3.643 +                left = Struct::cast(dest->readObject(i));
   3.644 +                right = Struct::cast(source->readObject(i));
   3.645 +                if (!Struct::Copy(zone, left, right))
   3.646 +                    return false;
   3.647 +            }
   3.648 +        } else if (contained->isArray() && ArrayType::cast(contained)->isFixedLength()) {
   3.649 +            assert(ArrayType::cast(source->type())->fixedLength() ==
   3.650 +                   ArrayType::cast(contained)->fixedLength());
   3.651 +
   3.652 +            Local<Array> left(zone);
   3.653 +            Local<Array> right(zone);
   3.654 +            for (unsigned i = 0; i < source->length(); i++) {
   3.655 +                left = Array::cast(dest->readObject(i));
   3.656 +                right = Array::cast(source->readObject(i));
   3.657 +                if (!Array::ShallowCopy(zone, left, right))
   3.658 +                    return false;
   3.659 +            }
   3.660 +        } else {
   3.661 +            assert(dest->length() == source->length());
   3.662 +            for (unsigned i = 0; i < source->length(); i++)
   3.663 +                dest->writeObject(zone, i, source->readObject(i));
   3.664 +        }
   3.665 +    } else {
   3.666 +        assert(contained->pod() == dest->type()->contained()->pod());
   3.667 +        assert(contained->pod() == PrimitiveType_Char
   3.668 +               ? source->length() <= dest->length()
   3.669 +               : source->length() == dest->length());
   3.670 +    
   3.671 +        assert(dest->length());
   3.672 +        memcpy(dest->bytes(), source->bytes(), source->length() * Array::SizeForElement(dest->type()));
   3.673 +    }
   3.674 +    return true;
   3.675 +}
   3.676 +
   3.677 +// Shallow copy an array. Fixed slots in the destination are copied from
   3.678 +// the source, but otherwise, references are assigned.
   3.679 +bool
   3.680 +Array::ShallowCopy(Zone *zone, Handle<Array> dest, Handle<Array> source)
   3.681 +{
   3.682 +    Local<Type> contained(zone, dest->type()->contained());
   3.683 +
   3.684 +    return CopyArrayElements(zone, contained, dest, source);
   3.685 +}
   3.686 +
   3.687 +Array *
   3.688 +Array::DeepCopy(Zone *zone, Handle<Array> source, Heap::Tenure tenure)
   3.689 +{
   3.690 +    Local<ArrayMap> map(zone, ArrayMap::cast(source->map()));
   3.691 +
   3.692 +    Local<Array> dest(zone, Array::NewRaw(zone, map, source->length(), tenure));
   3.693 +    if (!dest)
   3.694 +        return NULL;
   3.695 +
   3.696 +    Local<Type> contained(zone, source->type()->contained());
   3.697 +    if (contained->isArray()) {
   3.698 +        assert(false);
   3.699 +        Local<Array> sub(zone);
   3.700 +        for (size_t i = 0; i < source->length(); i++) {
   3.701 +            sub = Array::cast(source->readObject(i));
   3.702 +            sub = DeepCopy(zone, sub, tenure);
   3.703 +            if (!sub)
   3.704 +                return NULL;
   3.705 +            dest->writeObject(zone, i, sub);
   3.706 +        }
   3.707 +    } else {
   3.708 +        if (!CopyArrayElements(zone, contained, dest, source))
   3.709 +            return NULL;
   3.710 +    }
   3.711 +
   3.712 +    return dest;
   3.713 +}
   3.714 +
   3.715 +Array *
   3.716 +DependentArray::New(Zone *zone, Handle<Array> source, Handle<ArrayMap> map, unsigned index)
   3.717 +{
   3.718 +    Local<ArrayType> sourcetype(zone, source->type());
   3.719 +
   3.720 +    // Right now we only support char arrays, to avoid nasty deep cloning
   3.721 +    // and to maybe cut off this feature as far as we can.
   3.722 +    assert(sourcetype->isCharArray());
   3.723 +    assert(map->type()->isCharArray());
   3.724 +
   3.725 +    // We allow taking 0-length dependent strings. It's safe because any reads
   3.726 +    // or writes will fail.
   3.727 +    assert(index <= source->length());
   3.728 +
   3.729 +    unsigned newlen = source->length() - index;
   3.730 +    unsigned eltsize = SizeForElement(sourcetype);
   3.731 +    
   3.732 +    if (!sourcetype->isFixedLength()) {
   3.733 +        // Simple case, just copy the array.
   3.734 +        Local<ArrayMap> map(zone, sourcetype->newMap());
   3.735 +        
   3.736 +        Local<Array> dest(zone, Array::NewRaw(zone, map, newlen, Heap::Tenure_Default));
   3.737 +        if (!dest)
   3.738 +            return NULL;
   3.739 +
   3.740 +        memcpy(dest->bytes(),
   3.741 +               (Address)source->bytes() + (index * eltsize),
   3.742 +               newlen * eltsize);
   3.743 +        return dest;
   3.744 +    }
   3.745 +
   3.746 +    Local<DependentArray> array(zone, DependentArray::cast(zone->allocate(map, sizeof(DependentArray), Heap::Tenure_Default)));
   3.747 +    if (!array)
   3.748 +        return NULL;
   3.749 +
   3.750 +    // :GC: This is currently not safe for moving GC! Although we will mark
   3.751 +    // the object owning the interior pointer, the interior pointer could be
   3.752 +    // moved later. We will eventually need some way of dealing with this.
   3.753 +    Address elements = Address(source->bytes()) + (index * eltsize);
   3.754 +
   3.755 +    array->root_ = source;
   3.756 +    array->length_ = newlen;
   3.757 +    array->elements_ = elements - ByteArray::offsetToElements();
   3.758 +    return array;
   3.759 +}
     4.1 --- a/src/Array.h	Mon Jun 10 00:46:29 2013 +0100
     4.2 +++ b/src/Array.h	Mon Jun 10 01:04:43 2013 +0100
     4.3 @@ -1,244 +1,244 @@
     4.4 -/* vim: set ts=4 sw=4 tw=99 et:
     4.5 - *
     4.6 - * Copyright (C) 2012 David Anderson
     4.7 - *
     4.8 - * This file is part of SourcePawn.
     4.9 - *
    4.10 - * SourcePawn is free software: you can redistribute it and/or modify it under
    4.11 - * the terms of the GNU General Public License as published by the Free
    4.12 - * Software Foundation, either version 3 of the License, or (at your option)
    4.13 - * any later version.
    4.14 - * 
    4.15 - * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
    4.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    4.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    4.18 - *
    4.19 - * You should have received a copy of the GNU General Public License along with
    4.20 - * SourcePawn. If not, see http://www.gnu.org/licenses/.
    4.21 - */
    4.22 -#ifndef _include_jitcraft_array_h_
    4.23 -#define _include_jitcraft_array_h_
    4.24 -
    4.25 -#include "Heap.h"
    4.26 -#include "Handles.h"
    4.27 -#include "Types.h"
    4.28 -#include "FixedArray.h"
    4.29 -
    4.30 -namespace ke {
    4.31 -
    4.32 -class ArrayMap;
    4.33 -
    4.34 -class Array : public Object
    4.35 -{
    4.36 -    friend class ArrayMap;
    4.37 -
    4.38 -  protected:
    4.39 -    // Note: we do not write barrier |elements_|, since it can be set to
    4.40 -    // arbitrary pointers.
    4.41 -    uint32 length_;
    4.42 -    union {
    4.43 -        void *elements_;
    4.44 -        Object *objelements_;
    4.45 -    };
    4.46 -
    4.47 -  protected:
    4.48 -    void updateLengthAndElements(Zone *zone, unsigned length, Object *array) {
    4.49 -        length_ = length;
    4.50 -        write(zone, &objelements_, array);
    4.51 -    }
    4.52 -
    4.53 -  public:
    4.54 -    static Array *NewFixed(Zone *zone, Handle<ArrayMap> map, Heap::Tenure = Heap::Tenure_Default);
    4.55 -    static Array *NewString(Zone *zone, Handle<ArrayMap> map, char *buffer, size_t length, Heap::Tenure = Heap::Tenure_Default);
    4.56 -    static Array *NewSized(Zone *zone, Handle<ArrayMap> map, int sizes[MAX_ARRAY_DEPTH], Heap::Tenure = Heap::Tenure_Default);
    4.57 -
    4.58 -    static Array *New1D(Zone *zone, Handle<ArrayMap> map, uint32 elements, Heap::Tenure tenure = Heap::Tenure_Default);
    4.59 -    static Array *NewEmpty(Zone *zone, Handle<ArrayMap> map, Heap::Tenure tenure = Heap::Tenure_Default);
    4.60 -    static Array *NewRaw(Zone *zone, Handle<ArrayMap> map, unsigned nelements, Heap::Tenure tenure);
    4.61 -
    4.62 -    static Array *NewExternal(Zone *zone,
    4.63 -                              Handle<ArrayMap> map,
    4.64 -                              void *buffer,
    4.65 -                              unsigned length,
    4.66 -                              Heap::Tenure tenure = Heap::Tenure_Default);
    4.67 -
    4.68 -    // Copies an array from one reference to another, obeying language semantics.
    4.69 -    static bool ShallowCopy(Zone *zone, Handle<Array> dest, Handle<Array> source);
    4.70 -
    4.71 -    // Creates a full duplicate of an array, following all array references as if
    4.72 -    // they were fixed. Array references inside structs or objects use ShallowCopy
    4.73 -    // semantics, as this is only intended for duplicating array literals, which
    4.74 -    // cannot contain structs.
    4.75 -    static Array *DeepCopy(Zone *zone, Handle<Array> source, Heap::Tenure tenure);
    4.76 -
    4.77 -    uint32 length() {
    4.78 -        return length_;
    4.79 -    }
    4.80 -
    4.81 -    inline ArrayType *type();
    4.82 -
    4.83 -    inline int *int32Vec();
    4.84 -    inline float *floatVec();
    4.85 -    inline char *chars();
    4.86 -    inline void *bytes();
    4.87 -
    4.88 -    bool resize(Zone *zone, size_t newLength);
    4.89 -
    4.90 -    static inline size_t SizeForElement(ArrayType *type) {
    4.91 -        if (type->contained()->isTraceable())
    4.92 -            return sizeof(ke::Object *);
    4.93 -        if (type->contained()->isInt32())
    4.94 -            return sizeof(int);
    4.95 -        if (type->contained()->primitive() == PrimitiveType_Char)
    4.96 -            return sizeof(char);
    4.97 -        assert(type->contained()->isFloat());
    4.98 -        return sizeof(float);
    4.99 -    }
   4.100 -
   4.101 -    inline size_t objSize(ArrayMap *map);
   4.102 -
   4.103 -    int readInt32(size_t index) {
   4.104 -        assert(index < length());
   4.105 -        return int32Vec()[index];
   4.106 -    }
   4.107 -    void writeInt32(size_t index, int i) {
   4.108 -        assert(index < length());
   4.109 -        int32Vec()[index] = i;
   4.110 -    }
   4.111 -    char readChar(size_t index) {
   4.112 -        assert(index < length());
   4.113 -        return chars()[index];
   4.114 -    }
   4.115 -    void writeChar(size_t index, char c) {
   4.116 -        assert(index < length());
   4.117 -        chars()[index] = c;
   4.118 -    }
   4.119 -    float readFloat(size_t index) {
   4.120 -        assert(index < length());
   4.121 -        return floatVec()[index];
   4.122 -    }
   4.123 -    void writeFloat(size_t index, float f) {
   4.124 -        assert(index < length());
   4.125 -        floatVec()[index] = f;
   4.126 -    }
   4.127 -    Object *readObject(size_t index) {
   4.128 -        return FixedArray::cast(objelements_)->at(index);
   4.129 -    }
   4.130 -    void writeObject(Zone *zone, size_t index, Object *ptr) {
   4.131 -        FixedArray::cast(objelements_)->set(zone, index, ptr);
   4.132 -    }
   4.133 -
   4.134 -    // GC Descriptor.
   4.135 -    static inline size_t offsetOfElements() {
   4.136 -        return offsetof(Array, objelements_);
   4.137 -    }
   4.138 -    // End GC Descriptor.
   4.139 -
   4.140 -    static Array *cast(Object *obj) {
   4.141 -        assert(!obj ||
   4.142 -               obj->is(MapKind_Array) ||
   4.143 -               obj->is(MapKind_DependentArray));
   4.144 -        return reinterpret_cast<Array *>(obj);
   4.145 -    }
   4.146 -};
   4.147 -
   4.148 -class DependentArray : public Array
   4.149 -{
   4.150 -    Barriered<Array> root_;
   4.151 -
   4.152 -  public:
   4.153 -    static Array *New(Zone *zone, Handle<Array> source, Handle<ArrayMap> map, unsigned index);
   4.154 -
   4.155 -    // GC Descriptor.
   4.156 -    static inline size_t offsetOfRoot() {
   4.157 -        return offsetof(DependentArray, root_);
   4.158 -    }
   4.159 -    // End GC Descriptor.
   4.160 -
   4.161 -    static DependentArray *cast(Object *obj) {
   4.162 -        assert(!obj || obj->is(MapKind_DependentArray));
   4.163 -        return reinterpret_cast<DependentArray *>(obj);
   4.164 -    }
   4.165 -};
   4.166 -
   4.167 -class ArrayMap : public Map
   4.168 -{
   4.169 -    Barriered<ArrayType> type_;
   4.170 -
   4.171 -  public:
   4.172 -    static ArrayMap *New(Zone *zone, Handle<ArrayType> type);
   4.173 -
   4.174 -    // DependentArray maps are never attached, and are just free-floating,
   4.175 -    // rooted ultimately by the bytecode. A :TODO: that we might need to
   4.176 -    // cache these, or attach them somewhere saner like ArrayType, which
   4.177 -    // itself will eventually be cached.
   4.178 -    static ArrayMap *NewDependent(Zone *zone, Handle<ArrayType> type);
   4.179 -
   4.180 -    ArrayType *type() {
   4.181 -        return type_;
   4.182 -    }
   4.183 -
   4.184 -    // GC Descriptor.
   4.185 -    static inline size_t offsetOfType() {
   4.186 -        return OFFSETOF(ArrayMap, type_);
   4.187 -    }
   4.188 -    // End GC Descriptor.
   4.189 -    
   4.190 -    static ArrayMap *cast(Object *obj) {
   4.191 -        assert(!obj || obj->is(MapKind_MetaArray));
   4.192 -        return reinterpret_cast<ArrayMap *>(obj);
   4.193 -    }
   4.194 -};
   4.195 -
   4.196 -inline void *
   4.197 -Array::bytes()
   4.198 -{
   4.199 -    assert(!type()->contained()->isTraceable());
   4.200 -    assert(type()->hasInlineElements() ||
   4.201 -           type()->isExternalArray() ||
   4.202 -           is(MapKind_DependentArray) ||
   4.203 -           !length() ||
   4.204 -           ByteArray::cast((Object *)elements_));
   4.205 -
   4.206 -    return Address(elements_) + ByteArray::offsetToElements();
   4.207 -}
   4.208 -
   4.209 -inline int *
   4.210 -Array::int32Vec()
   4.211 -{
   4.212 -    assert(type()->contained()->isInt32());
   4.213 -    return reinterpret_cast<int *>(bytes());
   4.214 -}
   4.215 -
   4.216 -inline float *
   4.217 -Array::floatVec()
   4.218 -{
   4.219 -    assert(type()->contained()->isFloat());
   4.220 -    return reinterpret_cast<float *>(bytes());
   4.221 -}
   4.222 -
   4.223 -inline char *
   4.224 -Array::chars()
   4.225 -{
   4.226 -    assert(type()->isCharArray());
   4.227 -    return reinterpret_cast<char *>(bytes());
   4.228 -}
   4.229 -
   4.230 -inline ArrayType *
   4.231 -Array::type()
   4.232 -{
   4.233 -    return ArrayMap::cast(map())->type();
   4.234 -}
   4.235 -
   4.236 -inline size_t
   4.237 -Array::objSize(ArrayMap *map)
   4.238 -{
   4.239 -    assert(this->map() == map);
   4.240 -    if (map->type()->hasInlineElements())
   4.241 -        return sizeof(Array) + Array::SizeForElement(map->type()) * length();
   4.242 -    return sizeof(Array);
   4.243 -}
   4.244 -
   4.245 -}
   4.246 -
   4.247 -#endif // _include_jitcraft_array_h_
   4.248 +/* vim: set ts=4 sw=4 tw=99 et:
   4.249 + *
   4.250 + * Copyright (C) 2012 David Anderson
   4.251 + *
   4.252 + * This file is part of SourcePawn.
   4.253 + *
   4.254 + * SourcePawn is free software: you can redistribute it and/or modify it under
   4.255 + * the terms of the GNU General Public License as published by the Free
   4.256 + * Software Foundation, either version 3 of the License, or (at your option)
   4.257 + * any later version.
   4.258 + * 
   4.259 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
   4.260 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   4.261 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   4.262 + *
   4.263 + * You should have received a copy of the GNU General Public License along with
   4.264 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
   4.265 + */
   4.266 +#ifndef _include_jitcraft_array_h_
   4.267 +#define _include_jitcraft_array_h_
   4.268 +
   4.269 +#include "Heap.h"
   4.270 +#include "Handles.h"
   4.271 +#include "Types.h"
   4.272 +#include "FixedArray.h"
   4.273 +
   4.274 +namespace ke {
   4.275 +
   4.276 +class ArrayMap;
   4.277 +
   4.278 +class Array : public Object
   4.279 +{
   4.280 +    friend class ArrayMap;
   4.281 +
   4.282 +  protected:
   4.283 +    // Note: we do not write barrier |elements_|, since it can be set to
   4.284 +    // arbitrary pointers.
   4.285 +    uint32 length_;
   4.286 +    union {
   4.287 +        void *elements_;
   4.288 +        Object *objelements_;
   4.289 +    };
   4.290 +
   4.291 +  protected:
   4.292 +    void updateLengthAndElements(Zone *zone, unsigned length, Object *array) {
   4.293 +        length_ = length;
   4.294 +        write(zone, &objelements_, array);
   4.295 +    }
   4.296 +
   4.297 +  public:
   4.298 +    static Array *NewFixed(Zone *zone, Handle<ArrayMap> map, Heap::Tenure = Heap::Tenure_Default);
   4.299 +    static Array *NewString(Zone *zone, Handle<ArrayMap> map, char *buffer, size_t length, Heap::Tenure = Heap::Tenure_Default);
   4.300 +    static Array *NewSized(Zone *zone, Handle<ArrayMap> map, int sizes[MAX_ARRAY_DEPTH], Heap::Tenure = Heap::Tenure_Default);
   4.301 +
   4.302 +    static Array *New1D(Zone *zone, Handle<ArrayMap> map, uint32 elements, Heap::Tenure tenure = Heap::Tenure_Default);
   4.303 +    static Array *NewEmpty(Zone *zone, Handle<ArrayMap> map, Heap::Tenure tenure = Heap::Tenure_Default);
   4.304 +    static Array *NewRaw(Zone *zone, Handle<ArrayMap> map, unsigned nelements, Heap::Tenure tenure);
   4.305 +
   4.306 +    static Array *NewExternal(Zone *zone,
   4.307 +                              Handle<ArrayMap> map,
   4.308 +                              void *buffer,
   4.309 +                              unsigned length,
   4.310 +                              Heap::Tenure tenure = Heap::Tenure_Default);
   4.311 +
   4.312 +    // Copies an array from one reference to another, obeying language semantics.
   4.313 +    static bool ShallowCopy(Zone *zone, Handle<Array> dest, Handle<Array> source);
   4.314 +
   4.315 +    // Creates a full duplicate of an array, following all array references as if
   4.316 +    // they were fixed. Array references inside structs or objects use ShallowCopy
   4.317 +    // semantics, as this is only intended for duplicating array literals, which
   4.318 +    // cannot contain structs.
   4.319 +    static Array *DeepCopy(Zone *zone, Handle<Array> source, Heap::Tenure tenure);
   4.320 +
   4.321 +    uint32 length() {
   4.322 +        return length_;
   4.323 +    }
   4.324 +
   4.325 +    inline ArrayType *type();
   4.326 +
   4.327 +    inline int *int32Vec();
   4.328 +    inline float *floatVec();
   4.329 +    inline char *chars();
   4.330 +    inline void *bytes();
   4.331 +
   4.332 +    bool resize(Zone *zone, size_t newLength);
   4.333 +
   4.334 +    static inline size_t SizeForElement(ArrayType *type) {
   4.335 +        if (type->contained()->isTraceable())
   4.336 +            return sizeof(ke::Object *);
   4.337 +        if (type->contained()->isInt32())
   4.338 +            return sizeof(int);
   4.339 +        if (type->contained()->primitive() == PrimitiveType_Char)
   4.340 +            return sizeof(char);
   4.341 +        assert(type->contained()->isFloat());
   4.342 +        return sizeof(float);
   4.343 +    }
   4.344 +
   4.345 +    inline size_t objSize(ArrayMap *map);
   4.346 +
   4.347 +    int readInt32(size_t index) {
   4.348 +        assert(index < length());
   4.349 +        return int32Vec()[index];
   4.350 +    }
   4.351 +    void writeInt32(size_t index, int i) {
   4.352 +        assert(index < length());
   4.353 +        int32Vec()[index] = i;
   4.354 +    }
   4.355 +    char readChar(size_t index) {
   4.356 +        assert(index < length());
   4.357 +        return chars()[index];
   4.358 +    }
   4.359 +    void writeChar(size_t index, char c) {
   4.360 +        assert(index < length());
   4.361 +        chars()[index] = c;
   4.362 +    }
   4.363 +    float readFloat(size_t index) {
   4.364 +        assert(index < length());
   4.365 +        return floatVec()[index];
   4.366 +    }
   4.367 +    void writeFloat(size_t index, float f) {
   4.368 +        assert(index < length());
   4.369 +        floatVec()[index] = f;
   4.370 +    }
   4.371 +    Object *readObject(size_t index) {
   4.372 +        return FixedArray::cast(objelements_)->at(index);
   4.373 +    }
   4.374 +    void writeObject(Zone *zone, size_t index, Object *ptr) {
   4.375 +        FixedArray::cast(objelements_)->set(zone, index, ptr);
   4.376 +    }
   4.377 +
   4.378 +    // GC Descriptor.
   4.379 +    static inline size_t offsetOfElements() {
   4.380 +        return offsetof(Array, objelements_);
   4.381 +    }
   4.382 +    // End GC Descriptor.
   4.383 +
   4.384 +    static Array *cast(Object *obj) {
   4.385 +        assert(!obj ||
   4.386 +               obj->is(MapKind_Array) ||
   4.387 +               obj->is(MapKind_DependentArray));
   4.388 +        return reinterpret_cast<Array *>(obj);
   4.389 +    }
   4.390 +};
   4.391 +
   4.392 +class DependentArray : public Array
   4.393 +{
   4.394 +    Barriered<Array> root_;
   4.395 +
   4.396 +  public:
   4.397 +    static Array *New(Zone *zone, Handle<Array> source, Handle<ArrayMap> map, unsigned index);
   4.398 +
   4.399 +    // GC Descriptor.
   4.400 +    static inline size_t offsetOfRoot() {
   4.401 +        return offsetof(DependentArray, root_);
   4.402 +    }
   4.403 +    // End GC Descriptor.
   4.404 +
   4.405 +    static DependentArray *cast(Object *obj) {
   4.406 +        assert(!obj || obj->is(MapKind_DependentArray));
   4.407 +        return reinterpret_cast<DependentArray *>(obj);
   4.408 +    }
   4.409 +};
   4.410 +
   4.411 +class ArrayMap : public Map
   4.412 +{
   4.413 +    Barriered<ArrayType> type_;
   4.414 +
   4.415 +  public:
   4.416 +    static ArrayMap *New(Zone *zone, Handle<ArrayType> type);
   4.417 +
   4.418 +    // DependentArray maps are never attached, and are just free-floating,
   4.419 +    // rooted ultimately by the bytecode. A :TODO: that we might need to
   4.420 +    // cache these, or attach them somewhere saner like ArrayType, which
   4.421 +    // itself will eventually be cached.
   4.422 +    static ArrayMap *NewDependent(Zone *zone, Handle<ArrayType> type);
   4.423 +
   4.424 +    ArrayType *type() {
   4.425 +        return type_;
   4.426 +    }
   4.427 +
   4.428 +    // GC Descriptor.
   4.429 +    static inline size_t offsetOfType() {
   4.430 +        return OFFSETOF(ArrayMap, type_);
   4.431 +    }
   4.432 +    // End GC Descriptor.
   4.433 +    
   4.434 +    static ArrayMap *cast(Object *obj) {
   4.435 +        assert(!obj || obj->is(MapKind_MetaArray));
   4.436 +        return reinterpret_cast<ArrayMap *>(obj);
   4.437 +    }
   4.438 +};
   4.439 +
   4.440 +inline void *
   4.441 +Array::bytes()
   4.442 +{
   4.443 +    assert(!type()->contained()->isTraceable());
   4.444 +    assert(type()->hasInlineElements() ||
   4.445 +           type()->isExternalArray() ||
   4.446 +           is(MapKind_DependentArray) ||
   4.447 +           !length() ||
   4.448 +           ByteArray::cast((Object *)elements_));
   4.449 +
   4.450 +    return Address(elements_) + ByteArray::offsetToElements();
   4.451 +}
   4.452 +
   4.453 +inline int *
   4.454 +Array::int32Vec()
   4.455 +{
   4.456 +    assert(type()->contained()->isInt32());
   4.457 +    return reinterpret_cast<int *>(bytes());
   4.458 +}
   4.459 +
   4.460 +inline float *
   4.461 +Array::floatVec()
   4.462 +{
   4.463 +    assert(type()->contained()->isFloat());
   4.464 +    return reinterpret_cast<float *>(bytes());
   4.465 +}
   4.466 +
   4.467 +inline char *
   4.468 +Array::chars()
   4.469 +{
   4.470 +    assert(type()->isCharArray());
   4.471 +    return reinterpret_cast<char *>(bytes());
   4.472 +}
   4.473 +
   4.474 +inline ArrayType *
   4.475 +Array::type()
   4.476 +{
   4.477 +    return ArrayMap::cast(map())->type();
   4.478 +}
   4.479 +
   4.480 +inline size_t
   4.481 +Array::objSize(ArrayMap *map)
   4.482 +{
   4.483 +    assert(this->map() == map);
   4.484 +    if (map->type()->hasInlineElements())
   4.485 +        return sizeof(Array) + Array::SizeForElement(map->type()) * length();
   4.486 +    return sizeof(Array);
   4.487 +}
   4.488 +
   4.489 +}
   4.490 +
   4.491 +#endif // _include_jitcraft_array_h_
     5.1 --- a/src/Code.h	Mon Jun 10 00:46:29 2013 +0100
     5.2 +++ b/src/Code.h	Mon Jun 10 01:04:43 2013 +0100
     5.3 @@ -1,140 +1,140 @@
     5.4 -/* vim: set ts=4 sw=4 tw=99 et:
     5.5 - *
     5.6 - * Copyright (C) 2012 David Anderson
     5.7 - *
     5.8 - * This file is part of JITCraft.
     5.9 - *
    5.10 - * JITCraft is free software: you can redistribute it and/or modify it under
    5.11 - * the terms of the GNU General Public License as published by the Free
    5.12 - * Software Foundation, either version 3 of the License, or (at your option)
    5.13 - * any later version.
    5.14 - * 
    5.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    5.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    5.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    5.18 - *
    5.19 - * You should have received a copy of the GNU General Public License along with
    5.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
    5.21 - */
    5.22 -#ifndef _include_jc_code_h_
    5.23 -#define _include_jc_code_h_
    5.24 -
    5.25 -#include "Opcodes.h"
    5.26 -#include "Barriers.h"
    5.27 -#include "Heap.h"
    5.28 -#include "Types.h"
    5.29 -#include "FixedArray.h"
    5.30 -
    5.31 -namespace ke {
    5.32 -
    5.33 -class Module;
    5.34 -class Type;
    5.35 -
    5.36 -// A code object contains the bytecode compiled from a function (or global
    5.37 -// script), as well as all information needed to interpret or JIT-compile
    5.38 -// the bytecode.
    5.39 -class Code : public Object
    5.40 -{
    5.41 -    Barriered<Module> module_;
    5.42 -    Barriered<ByteArray> bytecode_;
    5.43 -    Barriered<FixedArray> locals_;
    5.44 -    Barriered<FixedArray> objects_;
    5.45 -    Barriered<FixedArray> strings_;
    5.46 -    Barriered<ByteArray> safepoints_;
    5.47 -    Barriered<ByteArray> sourcemap_;
    5.48 -    unsigned maxStackDepth_;
    5.49 -    unsigned lineNumber_;
    5.50 -    unsigned maxLoopDepth_;
    5.51 -
    5.52 -  public:
    5.53 -    static inline size_t BytesPerSafepoint(size_t stackDepth) {
    5.54 -        return (Align(stackDepth, 8) / 8) + sizeof(unsigned);
    5.55 -    }
    5.56 -
    5.57 -  public:
    5.58 -    static Code *New(Zone *zone, Handle<ByteArray> bytecode, Handle<FixedArray> locals,
    5.59 -                     Handle<FixedArray> objects, Handle<FixedArray> strings, unsigned maxStackDepth,
    5.60 -                     unsigned maxLoopDepth, Handle<ByteArray> safepoints, Handle<ByteArray> sourcemap);
    5.61 -
    5.62 -    Module *module() {
    5.63 -        return module_;
    5.64 -    }
    5.65 -    bytecode *start() {
    5.66 -        return bytecode_->raw();
    5.67 -    }
    5.68 -    unsigned length() {
    5.69 -        return bytecode_->length();
    5.70 -    }
    5.71 -    Type *localType(size_t index) {
    5.72 -        return Type::cast(locals_->at(index));
    5.73 -    }
    5.74 -    unsigned nlocals() {
    5.75 -        return locals_ ? locals_->length() : 0;
    5.76 -    }
    5.77 -    unsigned maxStackDepth() {
    5.78 -        return maxStackDepth_;
    5.79 -    }
    5.80 -    unsigned maxLoopDepth() {
    5.81 -        return maxLoopDepth_;
    5.82 -    }
    5.83 -    Map *map(size_t index) {
    5.84 -        return Map::cast(objects_->at(index));
    5.85 -    }
    5.86 -    Object *object(size_t index) {
    5.87 -        return objects_->at(index);
    5.88 -    }
    5.89 -    ByteArray *safepoints() {
    5.90 -        return safepoints_;
    5.91 -    }
    5.92 -    FixedArray *strings() {
    5.93 -        return strings_;
    5.94 -    }
    5.95 -    uint8 *safepointAt(unsigned pcOffset);
    5.96 -
    5.97 -    void setModule(Handle<Module> module) {
    5.98 -        module_ = module;
    5.99 -    }
   5.100 -
   5.101 -    unsigned pcToOffset(bytecode *pc) {
   5.102 -        assert(pc >= start() && pc < start() + length());
   5.103 -        return unsigned(pc - start());
   5.104 -    }
   5.105 -
   5.106 -    SourcePosition pcToSource(unsigned pc);
   5.107 -    unsigned lineNumber() {
   5.108 -        return lineNumber_;
   5.109 -    }
   5.110 -
   5.111 -    // GC Descriptor.
   5.112 -    static inline size_t offsetOfModule() {
   5.113 -        return OFFSETOF(Code, module_);
   5.114 -    }
   5.115 -    static inline size_t offsetOfBytecode() {
   5.116 -        return OFFSETOF(Code, bytecode_);
   5.117 -    }
   5.118 -    static inline size_t offsetOfLocals() {
   5.119 -        return OFFSETOF(Code, locals_);
   5.120 -    }
   5.121 -    static inline size_t offsetOfObjects() {
   5.122 -        return OFFSETOF(Code, objects_);
   5.123 -    }
   5.124 -    static inline size_t offsetOfStrings() {
   5.125 -        return OFFSETOF(Code, strings_);
   5.126 -    }
   5.127 -    static inline size_t offsetOfSafepoints() {
   5.128 -        return OFFSETOF(Code, safepoints_);
   5.129 -    }
   5.130 -    static inline size_t offsetOfSourceMap() {
   5.131 -        return OFFSETOF(Code, sourcemap_);
   5.132 -    }
   5.133 -    // End GC Descriptor.
   5.134 -
   5.135 -    static Code *cast(Object *obj) {
   5.136 -        assert(!obj || obj->is(MapKind_Code));
   5.137 -        return reinterpret_cast<Code *>(obj);
   5.138 -    }
   5.139 -};
   5.140 -
   5.141 -}
   5.142 -
   5.143 -#endif // _include_jc_code_h_
   5.144 +/* vim: set ts=4 sw=4 tw=99 et:
   5.145 + *
   5.146 + * Copyright (C) 2012 David Anderson
   5.147 + *
   5.148 + * This file is part of JITCraft.
   5.149 + *
   5.150 + * JITCraft is free software: you can redistribute it and/or modify it under
   5.151 + * the terms of the GNU General Public License as published by the Free
   5.152 + * Software Foundation, either version 3 of the License, or (at your option)
   5.153 + * any later version.
   5.154 + * 
   5.155 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
   5.156 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   5.157 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   5.158 + *
   5.159 + * You should have received a copy of the GNU General Public License along with
   5.160 + * JITCraft. If not, see http://www.gnu.org/licenses/.
   5.161 + */
   5.162 +#ifndef _include_jc_code_h_
   5.163 +#define _include_jc_code_h_
   5.164 +
   5.165 +#include "Opcodes.h"
   5.166 +#include "Barriers.h"
   5.167 +#include "Heap.h"
   5.168 +#include "Types.h"
   5.169 +#include "FixedArray.h"
   5.170 +
   5.171 +namespace ke {
   5.172 +
   5.173 +class Module;
   5.174 +class Type;
   5.175 +
   5.176 +// A code object contains the bytecode compiled from a function (or global
   5.177 +// script), as well as all information needed to interpret or JIT-compile
   5.178 +// the bytecode.
   5.179 +class Code : public Object
   5.180 +{
   5.181 +    Barriered<Module> module_;
   5.182 +    Barriered<ByteArray> bytecode_;
   5.183 +    Barriered<FixedArray> locals_;
   5.184 +    Barriered<FixedArray> objects_;
   5.185 +    Barriered<FixedArray> strings_;
   5.186 +    Barriered<ByteArray> safepoints_;
   5.187 +    Barriered<ByteArray> sourcemap_;
   5.188 +    unsigned maxStackDepth_;
   5.189 +    unsigned lineNumber_;
   5.190 +    unsigned maxLoopDepth_;
   5.191 +
   5.192 +  public:
   5.193 +    static inline size_t BytesPerSafepoint(size_t stackDepth) {
   5.194 +        return (Align(stackDepth, 8) / 8) + sizeof(unsigned);
   5.195 +    }
   5.196 +
   5.197 +  public:
   5.198 +    static Code *New(Zone *zone, Handle<ByteArray> bytecode, Handle<FixedArray> locals,
   5.199 +                     Handle<FixedArray> objects, Handle<FixedArray> strings, unsigned maxStackDepth,
   5.200 +                     unsigned maxLoopDepth, Handle<ByteArray> safepoints, Handle<ByteArray> sourcemap);
   5.201 +
   5.202 +    Module *module() {
   5.203 +        return module_;
   5.204 +    }
   5.205 +    bytecode *start() {
   5.206 +        return bytecode_->raw();
   5.207 +    }
   5.208 +    unsigned length() {
   5.209 +        return bytecode_->length();
   5.210 +    }
   5.211 +    Type *localType(size_t index) {
   5.212 +        return Type::cast(locals_->at(index));
   5.213 +    }
   5.214 +    unsigned nlocals() {
   5.215 +        return locals_ ? locals_->length() : 0;
   5.216 +    }
   5.217 +    unsigned maxStackDepth() {
   5.218 +        return maxStackDepth_;
   5.219 +    }
   5.220 +    unsigned maxLoopDepth() {
   5.221 +        return maxLoopDepth_;
   5.222 +    }
   5.223 +    Map *map(size_t index) {
   5.224 +        return Map::cast(objects_->at(index));
   5.225 +    }
   5.226 +    Object *object(size_t index) {
   5.227 +        return objects_->at(index);
   5.228 +    }
   5.229 +    ByteArray *safepoints() {
   5.230 +        return safepoints_;
   5.231 +    }
   5.232 +    FixedArray *strings() {
   5.233 +        return strings_;
   5.234 +    }
   5.235 +    uint8 *safepointAt(unsigned pcOffset);
   5.236 +
   5.237 +    void setModule(Handle<Module> module) {
   5.238 +        module_ = module;
   5.239 +    }
   5.240 +
   5.241 +    unsigned pcToOffset(bytecode *pc) {
   5.242 +        assert(pc >= start() && pc < start() + length());
   5.243 +        return unsigned(pc - start());
   5.244 +    }
   5.245 +
   5.246 +    SourcePosition pcToSource(unsigned pc);
   5.247 +    unsigned lineNumber() {
   5.248 +        return lineNumber_;
   5.249 +    }
   5.250 +
   5.251 +    // GC Descriptor.
   5.252 +    static inline size_t offsetOfModule() {
   5.253 +        return OFFSETOF(Code, module_);
   5.254 +    }
   5.255 +    static inline size_t offsetOfBytecode() {
   5.256 +        return OFFSETOF(Code, bytecode_);
   5.257 +    }
   5.258 +    static inline size_t offsetOfLocals() {
   5.259 +        return OFFSETOF(Code, locals_);
   5.260 +    }
   5.261 +    static inline size_t offsetOfObjects() {
   5.262 +        return OFFSETOF(Code, objects_);
   5.263 +    }
   5.264 +    static inline size_t offsetOfStrings() {
   5.265 +        return OFFSETOF(Code, strings_);
   5.266 +    }
   5.267 +    static inline size_t offsetOfSafepoints() {
   5.268 +        return OFFSETOF(Code, safepoints_);
   5.269 +    }
   5.270 +    static inline size_t offsetOfSourceMap() {
   5.271 +        return OFFSETOF(Code, sourcemap_);
   5.272 +    }
   5.273 +    // End GC Descriptor.
   5.274 +
   5.275 +    static Code *cast(Object *obj) {
   5.276 +        assert(!obj || obj->is(MapKind_Code));
   5.277 +        return reinterpret_cast<Code *>(obj);
   5.278 +    }
   5.279 +};
   5.280 +
   5.281 +}
   5.282 +
   5.283 +#endif // _include_jc_code_h_
     6.1 --- a/src/CompactBuffer.h	Mon Jun 10 00:46:29 2013 +0100
     6.2 +++ b/src/CompactBuffer.h	Mon Jun 10 01:04:43 2013 +0100
     6.3 @@ -1,100 +1,100 @@
     6.4 -/* vim: set ts=4 sw=4 tw=99 et:
     6.5 - *
     6.6 - * Copyright (C) 2012 David Anderson
     6.7 - *
     6.8 - * This file is part of JITCraft.
     6.9 - *
    6.10 - * JITCraft is free software: you can redistribute it and/or modify it under
    6.11 - * the terms of the GNU General Public License as published by the Free
    6.12 - * Software Foundation, either version 3 of the License, or (at your option)
    6.13 - * any later version.
    6.14 - * 
    6.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    6.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    6.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    6.18 - *
    6.19 - * You should have received a copy of the GNU General Public License along with
    6.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
    6.21 - */
    6.22 -#ifndef _include_jc_compact_buffer_h_
    6.23 -#define _include_jc_compact_buffer_h_
    6.24 -
    6.25 -#include "AllocatorPolicies.h"
    6.26 -#include "Utility.h"
    6.27 -#include "Vector.h"
    6.28 -
    6.29 -namespace ke {
    6.30 -
    6.31 -class CompactBufferReader
    6.32 -{
    6.33 -    const uint8 *pos_;
    6.34 -    const uint8 *end_;
    6.35 -
    6.36 -  public:
    6.37 -    CompactBufferReader(const uint8 *start, const uint8 *end)
    6.38 -      : pos_(start),
    6.39 -        end_(end)
    6.40 -    {
    6.41 -    }
    6.42 -
    6.43 -    uint8 readUint8() {
    6.44 -        assert(pos_ < end_);
    6.45 -        return *pos_++;
    6.46 -    }
    6.47 -
    6.48 -    uint32 readUint32() {
    6.49 -        uint32 value = 0;
    6.50 -        uint32 shift = 0;
    6.51 -
    6.52 -        uint8 byte;
    6.53 -        do {
    6.54 -            byte = readUint8();
    6.55 -            value |= (byte >> 1) << shift;
    6.56 -            shift += 7;
    6.57 -        } while (byte & 1);
    6.58 -
    6.59 -        assert(shift < 32);
    6.60 -        return value;
    6.61 -    }
    6.62 -
    6.63 -    bool done() const {
    6.64 -        return pos_ == end_;
    6.65 -    }
    6.66 -};
    6.67 -
    6.68 -class CompactBufferWriter
    6.69 -{
    6.70 -    Vector<uint8, ZoneAllocatorPolicy> buffer_;
    6.71 -    bool enoughMemory_;
    6.72 -
    6.73 -  public:
    6.74 -    CompactBufferWriter()
    6.75 -      : enoughMemory_(true)
    6.76 -    {
    6.77 -    }
    6.78 -
    6.79 -    void writeUint8(unsigned value) {
    6.80 -        enoughMemory_ &= buffer_.append(value);
    6.81 -    }
    6.82 -    void writeUint32(unsigned value) {
    6.83 -        do {
    6.84 -            writeUint8(((value & 0x7F) << 1) | (value > 0x7F));
    6.85 -            value >>= 7;
    6.86 -        } while (value);
    6.87 -    }
    6.88 -
    6.89 -    uint8 *buffer() const {
    6.90 -        return buffer_.buffer();
    6.91 -    }
    6.92 -    size_t length() const {
    6.93 -        return buffer_.length();
    6.94 -    }
    6.95 -
    6.96 -    bool oom() const {
    6.97 -        return !enoughMemory_;
    6.98 -    }
    6.99 -};
   6.100 -
   6.101 -}
   6.102 -
   6.103 -#endif // _include_jc_compact_buffer_h_
   6.104 +/* vim: set ts=4 sw=4 tw=99 et:
   6.105 + *
   6.106 + * Copyright (C) 2012 David Anderson
   6.107 + *
   6.108 + * This file is part of JITCraft.
   6.109 + *
   6.110 + * JITCraft is free software: you can redistribute it and/or modify it under
   6.111 + * the terms of the GNU General Public License as published by the Free
   6.112 + * Software Foundation, either version 3 of the License, or (at your option)
   6.113 + * any later version.
   6.114 + * 
   6.115 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
   6.116 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   6.117 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   6.118 + *
   6.119 + * You should have received a copy of the GNU General Public License along with
   6.120 + * JITCraft. If not, see http://www.gnu.org/licenses/.
   6.121 + */
   6.122 +#ifndef _include_jc_compact_buffer_h_
   6.123 +#define _include_jc_compact_buffer_h_
   6.124 +
   6.125 +#include "AllocatorPolicies.h"
   6.126 +#include "Utility.h"
   6.127 +#include "Vector.h"
   6.128 +
   6.129 +namespace ke {
   6.130 +
   6.131 +class CompactBufferReader
   6.132 +{
   6.133 +    const uint8 *pos_;
   6.134 +    const uint8 *end_;
   6.135 +
   6.136 +  public:
   6.137 +    CompactBufferReader(const uint8 *start, const uint8 *end)
   6.138 +      : pos_(start),
   6.139 +        end_(end)
   6.140 +    {
   6.141 +    }
   6.142 +
   6.143 +    uint8 readUint8() {
   6.144 +        assert(pos_ < end_);
   6.145 +        return *pos_++;
   6.146 +    }
   6.147 +
   6.148 +    uint32 readUint32() {
   6.149 +        uint32 value = 0;
   6.150 +        uint32 shift = 0;
   6.151 +
   6.152 +        uint8 byte;
   6.153 +        do {
   6.154 +            byte = readUint8();
   6.155 +            value |= (byte >> 1) << shift;
   6.156 +            shift += 7;
   6.157 +        } while (byte & 1);
   6.158 +
   6.159 +        assert(shift < 32);
   6.160 +        return value;
   6.161 +    }
   6.162 +
   6.163 +    bool done() const {
   6.164 +        return pos_ == end_;
   6.165 +    }
   6.166 +};
   6.167 +
   6.168 +class CompactBufferWriter
   6.169 +{
   6.170 +    Vector<uint8, ZoneAllocatorPolicy> buffer_;
   6.171 +    bool enoughMemory_;
   6.172 +
   6.173 +  public:
   6.174 +    CompactBufferWriter()
   6.175 +      : enoughMemory_(true)
   6.176 +    {
   6.177 +    }
   6.178 +
   6.179 +    void writeUint8(unsigned value) {
   6.180 +        enoughMemory_ &= buffer_.append(value);
   6.181 +    }
   6.182 +    void writeUint32(unsigned value) {
   6.183 +        do {
   6.184 +            writeUint8(((value & 0x7F) << 1) | (value > 0x7F));
   6.185 +            value >>= 7;
   6.186 +        } while (value);
   6.187 +    }
   6.188 +
   6.189 +    uint8 *buffer() const {
   6.190 +        return buffer_.buffer();
   6.191 +    }
   6.192 +    size_t length() const {
   6.193 +        return buffer_.length();
   6.194 +    }
   6.195 +
   6.196 +    bool oom() const {
   6.197 +        return !enoughMemory_;
   6.198 +    }
   6.199 +};
   6.200 +
   6.201 +}
   6.202 +
   6.203 +#endif // _include_jc_compact_buffer_h_
     7.1 --- a/src/Environments.cpp	Mon Jun 10 00:46:29 2013 +0100
     7.2 +++ b/src/Environments.cpp	Mon Jun 10 01:04:43 2013 +0100
     7.3 @@ -1,102 +1,102 @@
     7.4 -/*
     7.5 - * Copyright (C) 2012 David Anderson
     7.6 - *
     7.7 - * This file is part of SourcePawn.
     7.8 - *
     7.9 - * SourcePawn is free software: you can redistribute it and/or modify it under
    7.10 - * the terms of the GNU General Public License as published by the Free
    7.11 - * Software Foundation, either version 3 of the License, or (at your option)
    7.12 - * any later version.
    7.13 - * 
    7.14 - * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
    7.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    7.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    7.17 - *
    7.18 - * You should have received a copy of the GNU General Public License along with
    7.19 - * SourcePawn. If not, see http://www.gnu.org/licenses/.
    7.20 - */
    7.21 -#include <string.h>
    7.22 -#include "Utility.h"
    7.23 -#include "Environments.h"
    7.24 -#include "Structures.h"
    7.25 -#include "FixedArray.h"
    7.26 -#include "Zone.h"
    7.27 -#include "compiler/NameBinding.h"
    7.28 -#include "Spaces-inl.h"
    7.29 -#include "Heap-inl.h"
    7.30 -
    7.31 -using namespace ke;
    7.32 -
    7.33 -EnvironmentSlotDescriptorArray *
    7.34 -EnvironmentSlotDescriptorArray::New(Zone *zone, unsigned nslots)
    7.35 -{
    7.36 -    size_t bytesNeeded = sizeof(EnvironmentSlotDescriptorArray) +
    7.37 -                         sizeof(EnvironmentSlotDescriptor) * nslots;
    7.38 -
    7.39 -    Local<EnvironmentSlotDescriptorArray> array(zone);
    7.40 -    Local<Map> map(zone, zone->getMap(MapKind_EnvironmentSlotDescriptorArray));
    7.41 -
    7.42 -    array = EnvironmentSlotDescriptorArray::cast(zone->allocate(map, bytesNeeded, Heap::Tenure_Old));
    7.43 -    if (!array)
    7.44 -        return NULL;
    7.45 -
    7.46 -    // We zero the array for safety, since we could GC or fail before initialization.
    7.47 -    array->length_ = nslots;
    7.48 -    memset(array->slots(), 0, sizeof(EnvironmentSlotDescriptor) * nslots);
    7.49 -    return array;
    7.50 -}
    7.51 -
    7.52 -Environment *
    7.53 -Environment::New(Zone *zone, Handle<EnvironmentMap> map, Heap::Tenure tenure)
    7.54 -{
    7.55 -    size_t bytesNeeded = sizeof(Environment) + map->structureSize();
    7.56 -    Local<Environment> env(zone, Environment::cast(zone->allocate(map, bytesNeeded, tenure)));
    7.57 -    if (!env)
    7.58 -        return NULL;
    7.59 -
    7.60 -    // Initialize when called from C++, to make sure object slots are NULL.
    7.61 -    memset((Object *)env + 1, 0, map->structureSize());
    7.62 -    return env;
    7.63 -}
    7.64 -
    7.65 -#if 0
    7.66 -EnvironmentMap *
    7.67 -EnvironmentMap::New(Zone *zone, unsigned nvars, Variable **vars)
    7.68 -{
    7.69 -    StructureBufferBuilder structure;
    7.70 -
    7.71 -    Local<EnvironmentSlotDescriptorArray> slots(zone);
    7.72 -    slots = EnvironmentSlotDescriptorArray::New(zone, nvars);
    7.73 -    if (!slots)
    7.74 -        return NULL;
    7.75 -
    7.76 -    // Build the descriptor table, mapping each slot to an offset and type.
    7.77 -    Local<Type> type(zone);
    7.78 -    for (unsigned i = 0; i < nvars; i++) {
    7.79 -        assert(vars[i]->slot() == i);
    7.80 -        type = vars[i]->type();
    7.81 -
    7.82 -        EnvironmentSlotDescriptor &desc = slots->slots()[i];
    7.83 -        if (!structure.add(type, &desc.offset))
    7.84 -            return NULL;
    7.85 -
    7.86 -        desc.type = type;
    7.87 -    }
    7.88 -
    7.89 -    // Allocate the actual map now.
    7.90 -    size_t bytesNeeded = sizeof(EnvironmentMap) + structure.traceableOffsetCount() * sizeof(unsigned);
    7.91 -
    7.92 -    Local<EnvironmentMap> map(zone);
    7.93 -    map = EnvironmentMap::cast(zone->allocateMap(MapKind_Environment, bytesNeeded, MapKind_MetaEnvironment));
    7.94 -    if (!map)
    7.95 -        return NULL;
    7.96 -    
    7.97 -    // Fill in the map fields, and copy the traceable offsets structure.
    7.98 -    map->structureSize_ = structure.structureSize();
    7.99 -    map->traceOffsetCount_ = structure.traceableOffsetCount();
   7.100 -    map->slots_ = slots;
   7.101 -    memcpy(const_cast<unsigned *>(map->traceOffsets()), structure.offsets(), sizeof(unsigned) * structure.traceableOffsetCount());
   7.102 -
   7.103 -    return map;
   7.104 -}
   7.105 +/*
   7.106 + * Copyright (C) 2012 David Anderson
   7.107 + *
   7.108 + * This file is part of SourcePawn.
   7.109 + *
   7.110 + * SourcePawn is free software: you can redistribute it and/or modify it under
   7.111 + * the terms of the GNU General Public License as published by the Free
   7.112 + * Software Foundation, either version 3 of the License, or (at your option)
   7.113 + * any later version.
   7.114 + * 
   7.115 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
   7.116 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   7.117 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   7.118 + *
   7.119 + * You should have received a copy of the GNU General Public License along with
   7.120 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
   7.121 + */
   7.122 +#include <string.h>
   7.123 +#include "Utility.h"
   7.124 +#include "Environments.h"
   7.125 +#include "Structures.h"
   7.126 +#include "FixedArray.h"
   7.127 +#include "Zone.h"
   7.128 +#include "compiler/NameBinding.h"
   7.129 +#include "Spaces-inl.h"
   7.130 +#include "Heap-inl.h"
   7.131 +
   7.132 +using namespace ke;
   7.133 +
   7.134 +EnvironmentSlotDescriptorArray *
   7.135 +EnvironmentSlotDescriptorArray::New(Zone *zone, unsigned nslots)
   7.136 +{
   7.137 +    size_t bytesNeeded = sizeof(EnvironmentSlotDescriptorArray) +
   7.138 +                         sizeof(EnvironmentSlotDescriptor) * nslots;
   7.139 +
   7.140 +    Local<EnvironmentSlotDescriptorArray> array(zone);
   7.141 +    Local<Map> map(zone, zone->getMap(MapKind_EnvironmentSlotDescriptorArray));
   7.142 +
   7.143 +    array = EnvironmentSlotDescriptorArray::cast(zone->allocate(map, bytesNeeded, Heap::Tenure_Old));
   7.144 +    if (!array)
   7.145 +        return NULL;
   7.146 +
   7.147 +    // We zero the array for safety, since we could GC or fail before initialization.
   7.148 +    array->length_ = nslots;
   7.149 +    memset(array->slots(), 0, sizeof(EnvironmentSlotDescriptor) * nslots);
   7.150 +    return array;
   7.151 +}
   7.152 +
   7.153 +Environment *
   7.154 +Environment::New(Zone *zone, Handle<EnvironmentMap> map, Heap::Tenure tenure)
   7.155 +{
   7.156 +    size_t bytesNeeded = sizeof(Environment) + map->structureSize();
   7.157 +    Local<Environment> env(zone, Environment::cast(zone->allocate(map, bytesNeeded, tenure)));
   7.158 +    if (!env)
   7.159 +        return NULL;
   7.160 +
   7.161 +    // Initialize when called from C++, to make sure object slots are NULL.
   7.162 +    memset((Object *)env + 1, 0, map->structureSize());
   7.163 +    return env;
   7.164 +}
   7.165 +
   7.166 +#if 0
   7.167 +EnvironmentMap *
   7.168 +EnvironmentMap::New(Zone *zone, unsigned nvars, Variable **vars)
   7.169 +{
   7.170 +    StructureBufferBuilder structure;
   7.171 +
   7.172 +    Local<EnvironmentSlotDescriptorArray> slots(zone);
   7.173 +    slots = EnvironmentSlotDescriptorArray::New(zone, nvars);
   7.174 +    if (!slots)
   7.175 +        return NULL;
   7.176 +
   7.177 +    // Build the descriptor table, mapping each slot to an offset and type.
   7.178 +    Local<Type> type(zone);
   7.179 +    for (unsigned i = 0; i < nvars; i++) {
   7.180 +        assert(vars[i]->slot() == i);
   7.181 +        type = vars[i]->type();
   7.182 +
   7.183 +        EnvironmentSlotDescriptor &desc = slots->slots()[i];
   7.184 +        if (!structure.add(type, &desc.offset))
   7.185 +            return NULL;
   7.186 +
   7.187 +        desc.type = type;
   7.188 +    }
   7.189 +
   7.190 +    // Allocate the actual map now.
   7.191 +    size_t bytesNeeded = sizeof(EnvironmentMap) + structure.traceableOffsetCount() * sizeof(unsigned);
   7.192 +
   7.193 +    Local<EnvironmentMap> map(zone);
   7.194 +    map = EnvironmentMap::cast(zone->allocateMap(MapKind_Environment, bytesNeeded, MapKind_MetaEnvironment));
   7.195 +    if (!map)
   7.196 +        return NULL;
   7.197 +    
   7.198 +    // Fill in the map fields, and copy the traceable offsets structure.
   7.199 +    map->structureSize_ = structure.structureSize();
   7.200 +    map->traceOffsetCount_ = structure.traceableOffsetCount();
   7.201 +    map->slots_ = slots;
   7.202 +    memcpy(const_cast<unsigned *>(map->traceOffsets()), structure.offsets(), sizeof(unsigned) * structure.traceableOffsetCount());
   7.203 +
   7.204 +    return map;
   7.205 +}
   7.206  #endif
   7.207 \ No newline at end of file
     8.1 --- a/src/Environments.h	Mon Jun 10 00:46:29 2013 +0100
     8.2 +++ b/src/Environments.h	Mon Jun 10 01:04:43 2013 +0100
     8.3 @@ -1,169 +1,169 @@
     8.4 -/*
     8.5 - * Copyright (C) 2012 David Anderson
     8.6 - *
     8.7 - * This file is part of JITCraft.
     8.8 - *
     8.9 - * JITCraft is free software: you can redistribute it and/or modify it under
    8.10 - * the terms of the GNU General Public License as published by the Free
    8.11 - * Software Foundation, either version 3 of the License, or (at your option)
    8.12 - * any later version.
    8.13 - * 
    8.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    8.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    8.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    8.17 - *
    8.18 - * You should have received a copy of the GNU General Public License along with
    8.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
    8.20 - */
    8.21 -#ifndef _include_ke_environment_h_
    8.22 -#define _include_ke_environment_h_
    8.23 -
    8.24 -#include "Objects.h"
    8.25 -#include "Handles.h"
    8.26 -#include "Heap.h"
    8.27 -#include "FixedArray.h"
    8.28 -
    8.29 -namespace ke {
    8.30 -
    8.31 -class EnvironmentMap;
    8.32 -class Variable;
    8.33 -class ByteArray;
    8.34 -class Type;
    8.35 -
    8.36 -// An environment represents the lexical environment of a code or function
    8.37 -// object. It used for variables which may be accessed outside a function's
    8.38 -// normal activation (i.e., upvars).
    8.39 -//
    8.40 -// A module uses an Environment to store its global variables.
    8.41 -class Environment : public Object
    8.42 -{
    8.43 -    template <typename T>
    8.44 -    inline T *pointerToSlot(unsigned slot);
    8.45 -
    8.46 -  public:
    8.47 -    static Environment *New(Zone *zone, Handle<EnvironmentMap> map, Heap::Tenure tenure = Heap::Tenure_Default);
    8.48 -
    8.49 -    inline EnvironmentMap *map();
    8.50 -    inline size_t objSize();
    8.51 -
    8.52 -    float getFloat(unsigned slot) {
    8.53 -        return *pointerToSlot<float>(slot);
    8.54 -    }
    8.55 -    int getInt32(unsigned slot) {
    8.56 -        return *pointerToSlot<int>(slot);
    8.57 -    }
    8.58 -    Object *getObject(unsigned slot) {
    8.59 -        return *pointerToSlot<Object *>(slot);
    8.60 -    }
    8.61 -    void setFloat(unsigned slot, float f) {
    8.62 -        *pointerToSlot<float>(slot) = f;
    8.63 -    }
    8.64 -    void setInt32(unsigned slot, int i) {
    8.65 -        *pointerToSlot<int>(slot) = i;
    8.66 -    }
    8.67 -    void setObject(unsigned slot, Object *obj) {
    8.68 -        // :TODO: write barrier
    8.69 -        *pointerToSlot<Object *>(slot) = obj;
    8.70 -    }
    8.71 -
    8.72 -    static inline size_t offsetOfSlotOffset(unsigned offset) {
    8.73 -        return sizeof(Environment) + offset;
    8.74 -    }
    8.75 -
    8.76 -    static inline Environment *cast(Object *obj) {
    8.77 -        assert(!obj || obj->is(MapKind_Environment));
    8.78 -        return reinterpret_cast<Environment *>(obj);
    8.79 -    }
    8.80 -};
    8.81 -
    8.82 -struct EnvironmentSlotDescriptor
    8.83 -{
    8.84 -    Barriered<Type> type;
    8.85 -    unsigned offset;
    8.86 -};
    8.87 -
    8.88 -class EnvironmentSlotDescriptorArray : public Object
    8.89 -{
    8.90 -    unsigned length_;
    8.91 -
    8.92 -  public:
    8.93 -    static EnvironmentSlotDescriptorArray *New(Zone *zone, unsigned length);
    8.94 -
    8.95 -    EnvironmentSlotDescriptor *slots() {
    8.96 -        return reinterpret_cast<EnvironmentSlotDescriptor *>(this + 1);
    8.97 -    }
    8.98 -    EnvironmentSlotDescriptor &at(unsigned slot) {
    8.99 -        assert(slot < length_);
   8.100 -        return slots()[slot];
   8.101 -    }
   8.102 -    unsigned length() {
   8.103 -        return length_;
   8.104 -    }
   8.105 -    unsigned objSize() {
   8.106 -        return sizeof(*this) + length() * sizeof(EnvironmentSlotDescriptorArray);
   8.107 -    }
   8.108 -
   8.109 -    static inline EnvironmentSlotDescriptorArray *cast(Object *obj) {
   8.110 -        assert(!obj || obj->is(MapKind_EnvironmentSlotDescriptorArray));
   8.111 -        return reinterpret_cast<EnvironmentSlotDescriptorArray *>(obj);
   8.112 -    }
   8.113 -};
   8.114 -
   8.115 -class EnvironmentMap : public Map
   8.116 -{
   8.117 -    unsigned structureSize_;
   8.118 -    unsigned traceOffsetCount_;
   8.119 -    Barriered<EnvironmentSlotDescriptorArray> slots_;
   8.120 -
   8.121 -  public:
   8.122 -    static EnvironmentMap *New(Zone *zone, unsigned nvars, Variable **vars);
   8.123 -
   8.124 -    unsigned structureSize() {
   8.125 -        return structureSize_;
   8.126 -    }
   8.127 -    unsigned traceOffsetCount() {
   8.128 -        return traceOffsetCount_;
   8.129 -    }
   8.130 -    const unsigned *traceOffsets() {
   8.131 -        return reinterpret_cast<unsigned *>(this + 1);
   8.132 -    }
   8.133 -    size_t objSize() {
   8.134 -        return sizeof(EnvironmentMap) + sizeof(unsigned) * traceOffsetCount();
   8.135 -    }
   8.136 -    EnvironmentSlotDescriptor &slotDescriptor(unsigned slot) {
   8.137 -        return slots_->at(slot);
   8.138 -    }
   8.139 -
   8.140 -    // Begin GC descriptors.
   8.141 -    static inline size_t offsetOfSlots() {
   8.142 -        return OFFSETOF(EnvironmentMap, slots_);
   8.143 -    }
   8.144 -    // End GC descriptors.
   8.145 -
   8.146 -    static inline EnvironmentMap *cast(Object *obj) {
   8.147 -        assert(!obj || obj->is(MapKind_MetaEnvironment));
   8.148 -        return reinterpret_cast<EnvironmentMap *>(obj);
   8.149 -    }
   8.150 -};
   8.151 -
   8.152 -size_t
   8.153 -Environment::objSize()
   8.154 -{
   8.155 -    return sizeof(Environment) + map()->structureSize();
   8.156 -}
   8.157 -
   8.158 -EnvironmentMap *
   8.159 -Environment::map()
   8.160 -{
   8.161 -    return EnvironmentMap::cast(Object::map());
   8.162 -}
   8.163 -
   8.164 -template <typename T> T *
   8.165 -Environment::pointerToSlot(unsigned slot)
   8.166 -{
   8.167 -    return reinterpret_cast<T *>(reinterpret_cast<char *>(this + 1) + map()->slotDescriptor(slot).offset);
   8.168 -}
   8.169 -
   8.170 -}
   8.171 -
   8.172 -#endif // _include_ke_environment_h_
   8.173 +/*
   8.174 + * Copyright (C) 2012 David Anderson
   8.175 + *
   8.176 + * This file is part of JITCraft.
   8.177 + *
   8.178 + * JITCraft is free software: you can redistribute it and/or modify it under
   8.179 + * the terms of the GNU General Public License as published by the Free
   8.180 + * Software Foundation, either version 3 of the License, or (at your option)
   8.181 + * any later version.
   8.182 + * 
   8.183 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
   8.184 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   8.185 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   8.186 + *
   8.187 + * You should have received a copy of the GNU General Public License along with
   8.188 + * JITCraft. If not, see http://www.gnu.org/licenses/.
   8.189 + */
   8.190 +#ifndef _include_ke_environment_h_
   8.191 +#define _include_ke_environment_h_
   8.192 +
   8.193 +#include "Objects.h"
   8.194 +#include "Handles.h"
   8.195 +#include "Heap.h"
   8.196 +#include "FixedArray.h"
   8.197 +
   8.198 +namespace ke {
   8.199 +
   8.200 +class EnvironmentMap;
   8.201 +class Variable;
   8.202 +class ByteArray;
   8.203 +class Type;
   8.204 +
   8.205 +// An environment represents the lexical environment of a code or function
   8.206 +// object. It used for variables which may be accessed outside a function's
   8.207 +// normal activation (i.e., upvars).
   8.208 +//
   8.209 +// A module uses an Environment to store its global variables.
   8.210 +class Environment : public Object
   8.211 +{
   8.212 +    template <typename T>
   8.213 +    inline T *pointerToSlot(unsigned slot);
   8.214 +
   8.215 +  public:
   8.216 +    static Environment *New(Zone *zone, Handle<EnvironmentMap> map, Heap::Tenure tenure = Heap::Tenure_Default);
   8.217 +
   8.218 +    inline EnvironmentMap *map();
   8.219 +    inline size_t objSize();
   8.220 +
   8.221 +    float getFloat(unsigned slot) {
   8.222 +        return *pointerToSlot<float>(slot);
   8.223 +    }
   8.224 +    int getInt32(unsigned slot) {
   8.225 +        return *pointerToSlot<int>(slot);
   8.226 +    }
   8.227 +    Object *getObject(unsigned slot) {
   8.228 +        return *pointerToSlot<Object *>(slot);
   8.229 +    }
   8.230 +    void setFloat(unsigned slot, float f) {
   8.231 +        *pointerToSlot<float>(slot) = f;
   8.232 +    }
   8.233 +    void setInt32(unsigned slot, int i) {
   8.234 +        *pointerToSlot<int>(slot) = i;
   8.235 +    }
   8.236 +    void setObject(unsigned slot, Object *obj) {
   8.237 +        // :TODO: write barrier
   8.238 +        *pointerToSlot<Object *>(slot) = obj;
   8.239 +    }
   8.240 +
   8.241 +    static inline size_t offsetOfSlotOffset(unsigned offset) {
   8.242 +        return sizeof(Environment) + offset;
   8.243 +    }
   8.244 +
   8.245 +    static inline Environment *cast(Object *obj) {
   8.246 +        assert(!obj || obj->is(MapKind_Environment));
   8.247 +        return reinterpret_cast<Environment *>(obj);
   8.248 +    }
   8.249 +};
   8.250 +
   8.251 +struct EnvironmentSlotDescriptor
   8.252 +{
   8.253 +    Barriered<Type> type;
   8.254 +    unsigned offset;
   8.255 +};
   8.256 +
   8.257 +class EnvironmentSlotDescriptorArray : public Object
   8.258 +{
   8.259 +    unsigned length_;
   8.260 +
   8.261 +  public:
   8.262 +    static EnvironmentSlotDescriptorArray *New(Zone *zone, unsigned length);
   8.263 +
   8.264 +    EnvironmentSlotDescriptor *slots() {
   8.265 +        return reinterpret_cast<EnvironmentSlotDescriptor *>(this + 1);
   8.266 +    }
   8.267 +    EnvironmentSlotDescriptor &at(unsigned slot) {
   8.268 +        assert(slot < length_);
   8.269 +        return slots()[slot];
   8.270 +    }
   8.271 +    unsigned length() {
   8.272 +        return length_;
   8.273 +    }
   8.274 +    unsigned objSize() {
   8.275 +        return sizeof(*this) + length() * sizeof(EnvironmentSlotDescriptorArray);
   8.276 +    }
   8.277 +
   8.278 +    static inline EnvironmentSlotDescriptorArray *cast(Object *obj) {
   8.279 +        assert(!obj || obj->is(MapKind_EnvironmentSlotDescriptorArray));
   8.280 +        return reinterpret_cast<EnvironmentSlotDescriptorArray *>(obj);
   8.281 +    }
   8.282 +};
   8.283 +
   8.284 +class EnvironmentMap : public Map
   8.285 +{
   8.286 +    unsigned structureSize_;
   8.287 +    unsigned traceOffsetCount_;
   8.288 +    Barriered<EnvironmentSlotDescriptorArray> slots_;
   8.289 +
   8.290 +  public:
   8.291 +    static EnvironmentMap *New(Zone *zone, unsigned nvars, Variable **vars);
   8.292 +
   8.293 +    unsigned structureSize() {
   8.294 +        return structureSize_;
   8.295 +    }
   8.296 +    unsigned traceOffsetCount() {
   8.297 +        return traceOffsetCount_;
   8.298 +    }
   8.299 +    const unsigned *traceOffsets() {
   8.300 +        return reinterpret_cast<unsigned *>(this + 1);
   8.301 +    }
   8.302 +    size_t objSize() {
   8.303 +        return sizeof(EnvironmentMap) + sizeof(unsigned) * traceOffsetCount();
   8.304 +    }
   8.305 +    EnvironmentSlotDescriptor &slotDescriptor(unsigned slot) {
   8.306 +        return slots_->at(slot);
   8.307 +    }
   8.308 +
   8.309 +    // Begin GC descriptors.
   8.310 +    static inline size_t offsetOfSlots() {
   8.311 +        return OFFSETOF(EnvironmentMap, slots_);
   8.312 +    }
   8.313 +    // End GC descriptors.
   8.314 +
   8.315 +    static inline EnvironmentMap *cast(Object *obj) {
   8.316 +        assert(!obj || obj->is(MapKind_MetaEnvironment));
   8.317 +        return reinterpret_cast<EnvironmentMap *>(obj);
   8.318 +    }
   8.319 +};
   8.320 +
   8.321 +size_t
   8.322 +Environment::objSize()
   8.323 +{
   8.324 +    return sizeof(Environment) + map()->structureSize();
   8.325 +}
   8.326 +
   8.327 +EnvironmentMap *
   8.328 +Environment::map()
   8.329 +{
   8.330 +    return EnvironmentMap::cast(Object::map());
   8.331 +}
   8.332 +
   8.333 +template <typename T> T *
   8.334 +Environment::pointerToSlot(unsigned slot)
   8.335 +{
   8.336 +    return reinterpret_cast<T *>(reinterpret_cast<char *>(this + 1) + map()->slotDescriptor(slot).offset);
   8.337 +}
   8.338 +
   8.339 +}
   8.340 +
   8.341 +#endif // _include_ke_environment_h_
     9.1 --- a/src/Exception.cpp	Mon Jun 10 00:46:29 2013 +0100
     9.2 +++ b/src/Exception.cpp	Mon Jun 10 01:04:43 2013 +0100
     9.3 @@ -1,31 +1,31 @@
     9.4 -/* vim: set ts=4 sw=4 tw=99 et:
     9.5 - *
     9.6 - * Copyright (C) 2012 David Anderson
     9.7 - *
     9.8 - * This file is part of SourcePawn.
     9.9 - *
    9.10 - * SourcePawn is free software: you can redistribute it and/or modify it under
    9.11 - * the terms of the GNU General Public License as published by the Free
    9.12 - * Software Foundation, either version 3 of the License, or (at your option)
    9.13 - * any later version.
    9.14 - * 
    9.15 - * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
    9.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    9.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    9.18 - *
    9.19 - * You should have received a copy of the GNU General Public License along with
    9.20 - * SourcePawn. If not, see http://www.gnu.org/licenses/.
    9.21 - */
    9.22 -#include "Utility.h"
    9.23 -#include "Messages.h"
    9.24 -
    9.25 -using namespace ke;
    9.26 -
    9.27 -const MessageInfo ke::Messages[] =
    9.28 -{
    9.29 -#define MSG(Name, Type, String) \
    9.30 -    { MessageType_##Type, String },
    9.31 -# include "Messages.tbl"
    9.32 -#undef MSG
    9.33 -    { MessageType_SyntaxError, NULL }
    9.34 -};
    9.35 +/* vim: set ts=4 sw=4 tw=99 et:
    9.36 + *
    9.37 + * Copyright (C) 2012 David Anderson
    9.38 + *
    9.39 + * This file is part of SourcePawn.
    9.40 + *
    9.41 + * SourcePawn is free software: you can redistribute it and/or modify it under
    9.42 + * the terms of the GNU General Public License as published by the Free
    9.43 + * Software Foundation, either version 3 of the License, or (at your option)
    9.44 + * any later version.
    9.45 + * 
    9.46 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
    9.47 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    9.48 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    9.49 + *
    9.50 + * You should have received a copy of the GNU General Public License along with
    9.51 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
    9.52 + */
    9.53 +#include "Utility.h"
    9.54 +#include "Messages.h"
    9.55 +
    9.56 +using namespace ke;
    9.57 +
    9.58 +const MessageInfo ke::Messages[] =
    9.59 +{
    9.60 +#define MSG(Name, Type, String) \
    9.61 +    { MessageType_##Type, String },
    9.62 +# include "Messages.tbl"
    9.63 +#undef MSG
    9.64 +    { MessageType_SyntaxError, NULL }
    9.65 +};
    10.1 --- a/src/FixedArray.cpp	Mon Jun 10 00:46:29 2013 +0100
    10.2 +++ b/src/FixedArray.cpp	Mon Jun 10 01:04:43 2013 +0100
    10.3 @@ -1,78 +1,78 @@
    10.4 -/*
    10.5 - * Copyright (C) 2012 David Anderson
    10.6 - *
    10.7 - * This file is part of SourcePawn.
    10.8 - *
    10.9 - * SourcePawn is free software: you can redistribute it and/or modify it under
   10.10 - * the terms of the GNU General Public License as published by the Free
   10.11 - * Software Foundation, either version 3 of the License, or (at your option)
   10.12 - * any later version.
   10.13 - * 
   10.14 - * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
   10.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   10.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   10.17 - *
   10.18 - * You should have received a copy of the GNU General Public License along with
   10.19 - * SourcePawn. If not, see http://www.gnu.org/licenses/.
   10.20 - */
   10.21 -#include <limits.h>
   10.22 -#include <string.h>
   10.23 -#include "FixedArray.h"
   10.24 -#include "Zone.h"
   10.25 -#include "Heap-inl.h"
   10.26 -
   10.27 -using namespace ke;
   10.28 -
   10.29 -static const unsigned kMaxFixedArrayLength = ((INT_MAX - sizeof(FixedArray)) / sizeof(ke::Object *));
   10.30 -
   10.31 -FixedArray *
   10.32 -FixedArray::New(Zone *zone, unsigned length, Heap::Tenure tenure)
   10.33 -{
   10.34 -    if (length >= kMaxFixedArrayLength) {
   10.35 -        zone->reportError(Message_ArrayTooBig);
   10.36 -        return NULL;
   10.37 -    }
   10.38 -
   10.39 -    Local<FixedArray> array(zone, FixedArray::cast(zone->allocate(MapKind_FixedArray, SizeFor(length), tenure)));
   10.40 -    if (!array)
   10.41 -        return NULL;
   10.42 -
   10.43 -    array->length_ = length;
   10.44 -    memset(array->vec(), 0, length * sizeof(Object *));
   10.45 -    return array;
   10.46 -}
   10.47 -
   10.48 -ByteArray *
   10.49 -ByteArray::New(Zone *zone, unsigned length, Heap::Tenure tenure)
   10.50 -{
   10.51 -    if (length >= kMaxFixedArrayLength) {
   10.52 -        zone->reportError(Message_ArrayTooBig);
   10.53 -        return NULL;
   10.54 -    }
   10.55 -
   10.56 -    Local<ByteArray> array(zone, ByteArray::cast(zone->allocate(MapKind_ByteArray, SizeFor(length), tenure)));
   10.57 -    if (!array)
   10.58 -        return NULL;
   10.59 -
   10.60 -    array->length_ = length;
   10.61 -    memset(array->raw(), 0, length);
   10.62 -    return array;
   10.63 -}
   10.64 -
   10.65 -ByteArray *
   10.66 -ByteArray::New(Zone *zone, Handle<Map> map, unsigned length, Heap::Tenure tenure)
   10.67 -{
   10.68 -    if (length >= kMaxFixedArrayLength) {
   10.69 -        zone->reportError(Message_ArrayTooBig);
   10.70 -        return NULL;
   10.71 -    }
   10.72 -
   10.73 -    Local<ByteArray> array(zone, ByteArray::cast(zone->allocate(map, SizeFor(length), tenure)));
   10.74 -    if (!array)
   10.75 -        return NULL;
   10.76 -
   10.77 -    array->length_ = length;
   10.78 -    memset(array->raw(), 0, length);
   10.79 -    return array;
   10.80 -}
   10.81 -
   10.82 +/*
   10.83 + * Copyright (C) 2012 David Anderson
   10.84 + *
   10.85 + * This file is part of SourcePawn.
   10.86 + *
   10.87 + * SourcePawn is free software: you can redistribute it and/or modify it under
   10.88 + * the terms of the GNU General Public License as published by the Free
   10.89 + * Software Foundation, either version 3 of the License, or (at your option)
   10.90 + * any later version.
   10.91 + * 
   10.92 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
   10.93 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   10.94 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   10.95 + *
   10.96 + * You should have received a copy of the GNU General Public License along with
   10.97 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
   10.98 + */
   10.99 +#include <limits.h>
  10.100 +#include <string.h>
  10.101 +#include "FixedArray.h"
  10.102 +#include "Zone.h"
  10.103 +#include "Heap-inl.h"
  10.104 +
  10.105 +using namespace ke;
  10.106 +
  10.107 +static const unsigned kMaxFixedArrayLength = ((INT_MAX - sizeof(FixedArray)) / sizeof(ke::Object *));
  10.108 +
  10.109 +FixedArray *
  10.110 +FixedArray::New(Zone *zone, unsigned length, Heap::Tenure tenure)
  10.111 +{
  10.112 +    if (length >= kMaxFixedArrayLength) {
  10.113 +        zone->reportError(Message_ArrayTooBig);
  10.114 +        return NULL;
  10.115 +    }
  10.116 +
  10.117 +    Local<FixedArray> array(zone, FixedArray::cast(zone->allocate(MapKind_FixedArray, SizeFor(length), tenure)));
  10.118 +    if (!array)
  10.119 +        return NULL;
  10.120 +
  10.121 +    array->length_ = length;
  10.122 +    memset(array->vec(), 0, length * sizeof(Object *));
  10.123 +    return array;
  10.124 +}
  10.125 +
  10.126 +ByteArray *
  10.127 +ByteArray::New(Zone *zone, unsigned length, Heap::Tenure tenure)
  10.128 +{
  10.129 +    if (length >= kMaxFixedArrayLength) {
  10.130 +        zone->reportError(Message_ArrayTooBig);
  10.131 +        return NULL;
  10.132 +    }
  10.133 +
  10.134 +    Local<ByteArray> array(zone, ByteArray::cast(zone->allocate(MapKind_ByteArray, SizeFor(length), tenure)));
  10.135 +    if (!array)
  10.136 +        return NULL;
  10.137 +
  10.138 +    array->length_ = length;
  10.139 +    memset(array->raw(), 0, length);
  10.140 +    return array;
  10.141 +}
  10.142 +
  10.143 +ByteArray *
  10.144 +ByteArray::New(Zone *zone, Handle<Map> map, unsigned length, Heap::Tenure tenure)
  10.145 +{
  10.146 +    if (length >= kMaxFixedArrayLength) {
  10.147 +        zone->reportError(Message_ArrayTooBig);
  10.148 +        return NULL;
  10.149 +    }
  10.150 +
  10.151 +    Local<ByteArray> array(zone, ByteArray::cast(zone->allocate(map, SizeFor(length), tenure)));
  10.152 +    if (!array)
  10.153 +        return NULL;
  10.154 +
  10.155 +    array->length_ = length;
  10.156 +    memset(array->raw(), 0, length);
  10.157 +    return array;
  10.158 +}
  10.159 +
    11.1 --- a/src/FixedArray.h	Mon Jun 10 00:46:29 2013 +0100
    11.2 +++ b/src/FixedArray.h	Mon Jun 10 01:04:43 2013 +0100
    11.3 @@ -1,99 +1,99 @@
    11.4 -/* vim: set ts=4 sw=4 tw=99 et:
    11.5 - *
    11.6 - * Copyright (C) 2012 David Anderson
    11.7 - *
    11.8 - * This file is part of SourcePawn.
    11.9 - *
   11.10 - * SourcePawn is free software: you can redistribute it and/or modify it under
   11.11 - * the terms of the GNU General Public License as published by the Free
   11.12 - * Software Foundation, either version 3 of the License, or (at your option)
   11.13 - * any later version.
   11.14 - * 
   11.15 - * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
   11.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   11.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   11.18 - *
   11.19 - * You should have received a copy of the GNU General Public License along with
   11.20 - * SourcePawn. If not, see http://www.gnu.org/licenses/.
   11.21 - */
   11.22 -#ifndef _include_jitcraft_fixedarray_h_
   11.23 -#define _include_jitcraft_fixedarray_h_
   11.24 -
   11.25 -#include "Heap.h"
   11.26 -
   11.27 -namespace ke {
   11.28 -
   11.29 -// A fixed-length array that contains Object * slots.
   11.30 -class FixedArray : public Object
   11.31 -{
   11.32 -    uint32 length_;
   11.33 -
   11.34 -  private:
   11.35 -    Object **vec() {
   11.36 -        return reinterpret_cast<Object **>(this + 1);
   11.37 -    }
   11.38 -
   11.39 -  public:
   11.40 -    static FixedArray *New(Zone *zone, unsigned length, Heap::Tenure tenure);
   11.41 -
   11.42 -    unsigned length() {
   11.43 -        return length_;
   11.44 -    }
   11.45 -    Object *at(size_t i) {
   11.46 -        assert(i < length());
   11.47 -        return vec()[i];
   11.48 -    }
   11.49 -    void set(Zone *zone, size_t i, Object *obj) {
   11.50 -        assert(i < length());
   11.51 -        write(zone, &vec()[i], obj);
   11.52 -    }
   11.53 -    size_t objSize() {
   11.54 -        return SizeFor(length());
   11.55 -    }
   11.56 -
   11.57 -    static inline size_t SizeFor(unsigned length) {
   11.58 -        return sizeof(FixedArray) + sizeof(Object *) * length;
   11.59 -    }
   11.60 -
   11.61 -    static inline FixedArray *cast(Object *obj) {
   11.62 -        assert(!obj || obj->is(MapKind_FixedArray));
   11.63 -        return reinterpret_cast<FixedArray *>(obj);
   11.64 -    }
   11.65 -};
   11.66 -
   11.67 -// A fixed-length array containing raw bytes.
   11.68 -class ByteArray : public Object
   11.69 -{
   11.70 -    uint32 length_;
   11.71 -
   11.72 -  public:
   11.73 -    static ByteArray *New(Zone *zone, unsigned length, Heap::Tenure tenure = Heap::Tenure_Default);
   11.74 -    static ByteArray *New(Zone *zone, Handle<Map> map, unsigned length, Heap::Tenure tenure = Heap::Tenure_Default);
   11.75 -
   11.76 -    unsigned length() {
   11.77 -        return length_;
   11.78 -    }
   11.79 -    Address raw() {
   11.80 -        return Address(this) + offsetToElements();
   11.81 -    }
   11.82 -    size_t objSize() {
   11.83 -        return SizeFor(length());
   11.84 -    }
   11.85 -
   11.86 -    static inline size_t offsetToElements() {
   11.87 -        return sizeof(ByteArray);
   11.88 -    }
   11.89 -
   11.90 -    static inline size_t SizeFor(unsigned length) {
   11.91 -        return sizeof(ByteArray) + sizeof(uint8) * length;
   11.92 -    }
   11.93 -
   11.94 -    static inline ByteArray *cast(Object *obj) {
   11.95 -        assert(!obj || obj->is(MapKind_ByteArray));
   11.96 -        return reinterpret_cast<ByteArray *>(obj);
   11.97 -    }
   11.98 -};
   11.99 -
  11.100 -}
  11.101 -
  11.102 -#endif // _include_jitcraft_fixedarray_h_
  11.103 +/* vim: set ts=4 sw=4 tw=99 et:
  11.104 + *
  11.105 + * Copyright (C) 2012 David Anderson
  11.106 + *
  11.107 + * This file is part of SourcePawn.
  11.108 + *
  11.109 + * SourcePawn is free software: you can redistribute it and/or modify it under
  11.110 + * the terms of the GNU General Public License as published by the Free
  11.111 + * Software Foundation, either version 3 of the License, or (at your option)
  11.112 + * any later version.
  11.113 + * 
  11.114 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
  11.115 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  11.116 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  11.117 + *
  11.118 + * You should have received a copy of the GNU General Public License along with
  11.119 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
  11.120 + */
  11.121 +#ifndef _include_jitcraft_fixedarray_h_
  11.122 +#define _include_jitcraft_fixedarray_h_
  11.123 +
  11.124 +#include "Heap.h"
  11.125 +
  11.126 +namespace ke {
  11.127 +
  11.128 +// A fixed-length array that contains Object * slots.
  11.129 +class FixedArray : public Object
  11.130 +{
  11.131 +    uint32 length_;
  11.132 +
  11.133 +  private:
  11.134 +    Object **vec() {
  11.135 +        return reinterpret_cast<Object **>(this + 1);
  11.136 +    }
  11.137 +
  11.138 +  public:
  11.139 +    static FixedArray *New(Zone *zone, unsigned length, Heap::Tenure tenure);
  11.140 +
  11.141 +    unsigned length() {
  11.142 +        return length_;
  11.143 +    }
  11.144 +    Object *at(size_t i) {
  11.145 +        assert(i < length());
  11.146 +        return vec()[i];
  11.147 +    }
  11.148 +    void set(Zone *zone, size_t i, Object *obj) {
  11.149 +        assert(i < length());
  11.150 +        write(zone, &vec()[i], obj);
  11.151 +    }
  11.152 +    size_t objSize() {
  11.153 +        return SizeFor(length());
  11.154 +    }
  11.155 +
  11.156 +    static inline size_t SizeFor(unsigned length) {
  11.157 +        return sizeof(FixedArray) + sizeof(Object *) * length;
  11.158 +    }
  11.159 +
  11.160 +    static inline FixedArray *cast(Object *obj) {
  11.161 +        assert(!obj || obj->is(MapKind_FixedArray));
  11.162 +        return reinterpret_cast<FixedArray *>(obj);
  11.163 +    }
  11.164 +};
  11.165 +
  11.166 +// A fixed-length array containing raw bytes.
  11.167 +class ByteArray : public Object
  11.168 +{
  11.169 +    uint32 length_;
  11.170 +
  11.171 +  public:
  11.172 +    static ByteArray *New(Zone *zone, unsigned length, Heap::Tenure tenure = Heap::Tenure_Default);
  11.173 +    static ByteArray *New(Zone *zone, Handle<Map> map, unsigned length, Heap::Tenure tenure = Heap::Tenure_Default);
  11.174 +
  11.175 +    unsigned length() {
  11.176 +        return length_;
  11.177 +    }
  11.178 +    Address raw() {
  11.179 +        return Address(this) + offsetToElements();
  11.180 +    }
  11.181 +    size_t objSize() {
  11.182 +        return SizeFor(length());
  11.183 +    }
  11.184 +
  11.185 +    static inline size_t offsetToElements() {
  11.186 +        return sizeof(ByteArray);
  11.187 +    }
  11.188 +
  11.189 +    static inline size_t SizeFor(unsigned length) {
  11.190 +        return sizeof(ByteArray) + sizeof(uint8) * length;
  11.191 +    }
  11.192 +
  11.193 +    static inline ByteArray *cast(Object *obj) {
  11.194 +        assert(!obj || obj->is(MapKind_ByteArray));
  11.195 +        return reinterpret_cast<ByteArray *>(obj);
  11.196 +    }
  11.197 +};
  11.198 +
  11.199 +}
  11.200 +
  11.201 +#endif // _include_jitcraft_fixedarray_h_
    12.1 --- a/src/Functions.cpp	Mon Jun 10 00:46:29 2013 +0100
    12.2 +++ b/src/Functions.cpp	Mon Jun 10 01:04:43 2013 +0100
    12.3 @@ -1,50 +1,50 @@
    12.4 -/*
    12.5 - * Copyright (C) 2012 David Anderson
    12.6 - *
    12.7 - * This file is part of SourcePawn.
    12.8 - *
    12.9 - * SourcePawn is free software: you can redistribute it and/or modify it under
   12.10 - * the terms of the GNU General Public License as published by the Free
   12.11 - * Software Foundation, either version 3 of the License, or (at your option)
   12.12 - * any later version.
   12.13 - * 
   12.14 - * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
   12.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   12.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   12.17 - *
   12.18 - * You should have received a copy of the GNU General Public License along with
   12.19 - * SourcePawn. If not, see http://www.gnu.org/licenses/.
   12.20 - */
   12.21 -#include "Functions.h"
   12.22 -#include "Modules.h"
   12.23 -#include "Zone.h"
   12.24 -#include "Heap-inl.h"
   12.25 -
   12.26 -using namespace ke;
   12.27 -
   12.28 -Function *
   12.29 -Function::New(Zone *zone, Handle<Code> code, Handle<FunctionType> type, Handle<String> name,
   12.30 -              const SourcePosition &pos)
   12.31 -{
   12.32 -    Function *fun = Function::cast(zone->allocate(MapKind_Function, sizeof(Function), Heap::Tenure_Old));
   12.33 -    if (!fun)
   12.34 -        return NULL;
   12.35 -
   12.36 -    fun->code_ = code;
   12.37 -    fun->pos_ = pos;
   12.38 -    fun->type_ = type;
   12.39 -    fun->name_ = name;
   12.40 -    return fun;
   12.41 -}
   12.42 -
   12.43 -Native *
   12.44 -Native::New(Zone *zone, Handle<FunctionType> type, size_t index)
   12.45 -{
   12.46 -    Native *fun = Native::cast(zone->allocate(MapKind_Native, sizeof(Native), Heap::Tenure_Old));
   12.47 -    if (!fun)
   12.48 -        return NULL;
   12.49 -
   12.50 -    fun->type_ = type;
   12.51 -    fun->index_ = index;
   12.52 -    return fun;
   12.53 -}
   12.54 +/*
   12.55 + * Copyright (C) 2012 David Anderson
   12.56 + *
   12.57 + * This file is part of SourcePawn.
   12.58 + *
   12.59 + * SourcePawn is free software: you can redistribute it and/or modify it under
   12.60 + * the terms of the GNU General Public License as published by the Free
   12.61 + * Software Foundation, either version 3 of the License, or (at your option)
   12.62 + * any later version.
   12.63 + * 
   12.64 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
   12.65 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   12.66 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   12.67 + *
   12.68 + * You should have received a copy of the GNU General Public License along with
   12.69 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
   12.70 + */
   12.71 +#include "Functions.h"
   12.72 +#include "Modules.h"
   12.73 +#include "Zone.h"
   12.74 +#include "Heap-inl.h"
   12.75 +
   12.76 +using namespace ke;
   12.77 +
   12.78 +Function *
   12.79 +Function::New(Zone *zone, Handle<Code> code, Handle<FunctionType> type, Handle<String> name,
   12.80 +              const SourcePosition &pos)
   12.81 +{
   12.82 +    Function *fun = Function::cast(zone->allocate(MapKind_Function, sizeof(Function), Heap::Tenure_Old));
   12.83 +    if (!fun)
   12.84 +        return NULL;
   12.85 +
   12.86 +    fun->code_ = code;
   12.87 +    fun->pos_ = pos;
   12.88 +    fun->type_ = type;
   12.89 +    fun->name_ = name;
   12.90 +    return fun;
   12.91 +}
   12.92 +
   12.93 +Native *
   12.94 +Native::New(Zone *zone, Handle<FunctionType> type, size_t index)
   12.95 +{
   12.96 +    Native *fun = Native::cast(zone->allocate(MapKind_Native, sizeof(Native), Heap::Tenure_Old));
   12.97 +    if (!fun)
   12.98 +        return NULL;
   12.99 +
  12.100 +    fun->type_ = type;
  12.101 +    fun->index_ = index;
  12.102 +    return fun;
  12.103 +}
    13.1 --- a/src/Functions.h	Mon Jun 10 00:46:29 2013 +0100
    13.2 +++ b/src/Functions.h	Mon Jun 10 01:04:43 2013 +0100
    13.3 @@ -1,113 +1,113 @@
    13.4 -/*
    13.5 - * Copyright (C) 2012 David Anderson
    13.6 - *
    13.7 - * This file is part of SourcePawn.
    13.8 - *
    13.9 - * SourcePawn is free software: you can redistribute it and/or modify it under
   13.10 - * the terms of the GNU General Public License as published by the Free
   13.11 - * Software Foundation, either version 3 of the License, or (at your option)
   13.12 - * any later version.
   13.13 - * 
   13.14 - * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
   13.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   13.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   13.17 - *
   13.18 - * You should have received a copy of the GNU General Public License along with
   13.19 - * SourcePawn. If not, see http://www.gnu.org/licenses/.
   13.20 - */
   13.21 -#ifndef _include_jitcraft_function_h_
   13.22 -#define _include_jitcraft_function_h_
   13.23 -
   13.24 -#include "Heap.h"
   13.25 -#include "Barriers.h"
   13.26 -#include "Types.h"
   13.27 -#include "Opcodes.h"
   13.28 -
   13.29 -namespace ke {
   13.30 -
   13.31 -class Code;
   13.32 -class Module;
   13.33 -class String;
   13.34 -
   13.35 -class Function : public Object
   13.36 -{
   13.37 -    Barriered<Code> code_;
   13.38 -    Barriered<FunctionType> type_;
   13.39 -    Barriered<String> name_;
   13.40 -    SourcePosition pos_;
   13.41 -
   13.42 - public:
   13.43 -    static Function *New(Zone *zone, Handle<Code> code, Handle<FunctionType> type, Handle<String> name,
   13.44 -                         const SourcePosition &pos);
   13.45 -
   13.46 -    Code *code() const {
   13.47 -        return code_;
   13.48 -    }
   13.49 -    FunctionType *type() const {
   13.50 -        return type_;
   13.51 -    }
   13.52 -    String *name() const {
   13.53 -        return name_;
   13.54 -    }
   13.55 -    const SourcePosition &pos() {
   13.56 -        return pos_;
   13.57 -    }
   13.58 -    unsigned nargs() {
   13.59 -        return type()->parameters()->length();
   13.60 -    }
   13.61 -    Type *argType(size_t index) {
   13.62 -        return type()->parameterAt(index);
   13.63 -    }
   13.64 -
   13.65 -    // Begin GC Descriptor.
   13.66 -    static inline size_t offsetOfCode() {
   13.67 -        return OFFSETOF(Function, code_);
   13.68 -    }
   13.69 -    static inline size_t offsetOfType() {
   13.70 -        return OFFSETOF(Function, type_);
   13.71 -    }
   13.72 -    static inline size_t offsetOfName() {
   13.73 -        return OFFSETOF(Function, name_);
   13.74 -    }
   13.75 -    // End GC Descriptor.
   13.76 -
   13.77 -    static inline Function *cast(Object *obj) {
   13.78 -        assert(!obj || obj->is(MapKind_Function));
   13.79 -        return reinterpret_cast<Function *>(obj);
   13.80 -    }
   13.81 -};
   13.82 -
   13.83 -// A Native is a function with a very specialized calling convention, intended
   13.84 -// for earlier ISourcePawnEngine API compatibility.
   13.85 -class Native : public Object
   13.86 -{
   13.87 -    Barriered<FunctionType> type_;
   13.88 -
   13.89 -    // Index into the Zone's native table.
   13.90 -    size_t index_;
   13.91 -
   13.92 -  public:
   13.93 -    static Native *New(Zone *zone, Handle<FunctionType> type, size_t index);
   13.94 -
   13.95 -    FunctionType *type() {
   13.96 -        return type_;
   13.97 -    }
   13.98 -    size_t index() const {
   13.99 -        return index_;
  13.100 -    }
  13.101 -
  13.102 -    // Begin GC Descriptor.
  13.103 -    static inline size_t offsetOfType() {
  13.104 -        return OFFSETOF(Native, type_);
  13.105 -    }
  13.106 -    // End GC Descriptor.
  13.107 -
  13.108 -    static inline Native *cast(Object *obj) {
  13.109 -        assert(!obj || obj->is(MapKind_Native));
  13.110 -        return reinterpret_cast<Native *>(obj);
  13.111 -    }
  13.112 -};
  13.113 -
  13.114 -}
  13.115 -
  13.116 -#endif // _include_jitcraft_function_h_
  13.117 +/*
  13.118 + * Copyright (C) 2012 David Anderson
  13.119 + *
  13.120 + * This file is part of SourcePawn.
  13.121 + *
  13.122 + * SourcePawn is free software: you can redistribute it and/or modify it under
  13.123 + * the terms of the GNU General Public License as published by the Free
  13.124 + * Software Foundation, either version 3 of the License, or (at your option)
  13.125 + * any later version.
  13.126 + * 
  13.127 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
  13.128 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  13.129 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13.130 + *
  13.131 + * You should have received a copy of the GNU General Public License along with
  13.132 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
  13.133 + */
  13.134 +#ifndef _include_jitcraft_function_h_
  13.135 +#define _include_jitcraft_function_h_
  13.136 +
  13.137 +#include "Heap.h"
  13.138 +#include "Barriers.h"
  13.139 +#include "Types.h"
  13.140 +#include "Opcodes.h"
  13.141 +
  13.142 +namespace ke {
  13.143 +
  13.144 +class Code;
  13.145 +class Module;
  13.146 +class String;
  13.147 +
  13.148 +class Function : public Object
  13.149 +{
  13.150 +    Barriered<Code> code_;
  13.151 +    Barriered<FunctionType> type_;
  13.152 +    Barriered<String> name_;
  13.153 +    SourcePosition pos_;
  13.154 +
  13.155 + public:
  13.156 +    static Function *New(Zone *zone, Handle<Code> code, Handle<FunctionType> type, Handle<String> name,
  13.157 +                         const SourcePosition &pos);
  13.158 +
  13.159 +    Code *code() const {
  13.160 +        return code_;
  13.161 +    }
  13.162 +    FunctionType *type() const {
  13.163 +        return type_;
  13.164 +    }
  13.165 +    String *name() const {
  13.166 +        return name_;
  13.167 +    }
  13.168 +    const SourcePosition &pos() {
  13.169 +        return pos_;
  13.170 +    }
  13.171 +    unsigned nargs() {
  13.172 +        return type()->parameters()->length();
  13.173 +    }
  13.174 +    Type *argType(size_t index) {
  13.175 +        return type()->parameterAt(index);
  13.176 +    }
  13.177 +
  13.178 +    // Begin GC Descriptor.
  13.179 +    static inline size_t offsetOfCode() {
  13.180 +        return OFFSETOF(Function, code_);
  13.181 +    }
  13.182 +    static inline size_t offsetOfType() {
  13.183 +        return OFFSETOF(Function, type_);
  13.184 +    }
  13.185 +    static inline size_t offsetOfName() {
  13.186 +        return OFFSETOF(Function, name_);
  13.187 +    }
  13.188 +    // End GC Descriptor.
  13.189 +
  13.190 +    static inline Function *cast(Object *obj) {
  13.191 +        assert(!obj || obj->is(MapKind_Function));
  13.192 +        return reinterpret_cast<Function *>(obj);
  13.193 +    }
  13.194 +};
  13.195 +
  13.196 +// A Native is a function with a very specialized calling convention, intended
  13.197 +// for earlier ISourcePawnEngine API compatibility.
  13.198 +class Native : public Object
  13.199 +{
  13.200 +    Barriered<FunctionType> type_;
  13.201 +
  13.202 +    // Index into the Zone's native table.
  13.203 +    size_t index_;
  13.204 +
  13.205 +  public:
  13.206 +    static Native *New(Zone *zone, Handle<FunctionType> type, size_t index);
  13.207 +
  13.208 +    FunctionType *type() {
  13.209 +        return type_;
  13.210 +    }
  13.211 +    size_t index() const {
  13.212 +        return index_;
  13.213 +    }
  13.214 +
  13.215 +    // Begin GC Descriptor.
  13.216 +    static inline size_t offsetOfType() {
  13.217 +        return OFFSETOF(Native, type_);
  13.218 +    }
  13.219 +    // End GC Descriptor.
  13.220 +
  13.221 +    static inline Native *cast(Object *obj) {
  13.222 +        assert(!obj || obj->is(MapKind_Native));
  13.223 +        return reinterpret_cast<Native *>(obj);
  13.224 +    }
  13.225 +};
  13.226 +
  13.227 +}
  13.228 +
  13.229 +#endif // _include_jitcraft_function_h_
    14.1 --- a/src/Interpreter.cpp	Mon Jun 10 00:46:29 2013 +0100
    14.2 +++ b/src/Interpreter.cpp	Mon Jun 10 01:04:43 2013 +0100
    14.3 @@ -1,1041 +1,1041 @@
    14.4 -/* vim: set ts=4 sw=4 tw=99 et:
    14.5 - *
    14.6 - * Copyright (C) 2012 David Anderson
    14.7 - *
    14.8 - * This file is part of JITCraft.
    14.9 - *
   14.10 - * JITCraft is free software: you can redistribute it and/or modify it under
   14.11 - * the terms of the GNU General Public License as published by the Free
   14.12 - * Software Foundation, either version 3 of the License, or (at your option)
   14.13 - * any later version.
   14.14 - * 
   14.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
   14.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   14.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   14.18 - *
   14.19 - * You should have received a copy of the GNU General Public License along with
   14.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
   14.21 - */
   14.22 -#include <string.h>
   14.23 -#include "Interpreter.h"
   14.24 -#include "Modules.h"
   14.25 -#include "Zone.h"
   14.26 -#include "Types.h"
   14.27 -#include "Array.h"
   14.28 -#include "Reference.h"
   14.29 -#include "Strings.h"
   14.30 -#include "Environments.h"
   14.31 -#include "Structures.h"
   14.32 -#include "NativeTable.h"
   14.33 -#include "Packages.h"
   14.34 -#include "Heap-inl.h"
   14.35 -
   14.36 -using namespace ke;
   14.37 -
   14.38 -#define PUSH_I32(top, value)    \
   14.39 -    do {                        \
   14.40 -        top.sp->i32 = value;    \
   14.41 -        top.sp++;               \
   14.42 -   } while (0)
   14.43 -
   14.44 -#define PUSH_F(top, value)      \
   14.45 -    do {                        \
   14.46 -        top.sp->f = value;      \
   14.47 -        top.sp++;               \
   14.48 -   } while (0)
   14.49 -
   14.50 -static inline int
   14.51 -POP_I32(Top &top)
   14.52 -{
   14.53 -    int value = top.sp[-1].i32;
   14.54 -    top.sp--;
   14.55 -    return value;
   14.56 -}
   14.57 -
   14.58 -static inline float
   14.59 -POP_F(Top &top)
   14.60 -{
   14.61 -    float value = top.sp[-1].f;
   14.62 -    top.sp--;
   14.63 -    return value;
   14.64 -}
   14.65 -
   14.66 -// Pawn's original semantics specify some kind of floor operation, so
   14.67 -// (8 / -3 == -3) and (-8 / 3 == -1). The SourcePawn 1 compiler (spcomp) uses
   14.68 -// the upstream algorithm when constant folding. However the SourcePawn 1 JIT
   14.69 -// does not. My guess is that Borja freaked out seeing the 13-instruction x86
   14.70 -// sequence necessary to get this functionality (I vaguely recall a thread
   14.71 -// where we discussed this with Mark Peter? But the ITB forums are gone...),
   14.72 -// and we just decided to break the damn thing. So SP1 was inconsistent, but
   14.73 -// we are not. And for completeness, we assert that the C compiler does the
   14.74 -// right thing, since C89 leaves it unspecified.
   14.75 -STATIC_ASSERT(8 / -3 == -2);
   14.76 -STATIC_ASSERT(-8 / 3 == -2);
   14.77 -
   14.78 -static inline bool
   14.79 -PushNewRef(Zone *zone, Top &top, void *location, Heap::Tenure tenure)
   14.80 -{
   14.81 -    Reference *ref = Reference::NewStack(zone, location, tenure);
   14.82 -    if (!ref)
   14.83 -        return false;
   14.84 -    top.sp->ref = ref;
   14.85 -    top.sp++;
   14.86 -    return true;
   14.87 -}
   14.88 -
   14.89 -static void
   14.90 -GetElement(Array *array, int index, LocalSlot *vp)
   14.91 -{
   14.92 -    if (array->type()->contained()->isTraceable()) {
   14.93 -        vp->obj = array->readObject(index);
   14.94 -        return;
   14.95 -    }
   14.96 -
   14.97 -    switch (array->type()->contained()->pod()) {
   14.98 -      case PrimitiveType_Float:
   14.99 -        vp->f = array->readFloat(index);
  14.100 -        break;
  14.101 -
  14.102 -      case PrimitiveType_Char:
  14.103 -        vp->i32 = array->readChar(index);
  14.104 -        break;
  14.105 -
  14.106 -      default:
  14.107 -        assert(array->type()->contained()->pod() == PrimitiveType_Int32);
  14.108 -        vp->i32 = array->readInt32(index);
  14.109 -        break;
  14.110 -    }
  14.111 -}
  14.112 -
  14.113 -static void
  14.114 -SetElement(Zone *zone, Array *array, int index, const LocalSlot &v)
  14.115 -{
  14.116 -    if (array->type()->contained()->isTraceable()) {
  14.117 -        array->writeObject(zone, index, v.obj);
  14.118 -        return;
  14.119 -    }
  14.120 -
  14.121 -    switch (array->type()->contained()->pod()) {
  14.122 -      case PrimitiveType_Float:
  14.123 -        array->writeFloat(index, v.f);
  14.124 -        break;
  14.125 -
  14.126 -      case PrimitiveType_Char:
  14.127 -        array->writeChar(index, v.i32);
  14.128 -        break;
  14.129 -
  14.130 -      default:
  14.131 -        assert(array->type()->contained()->pod() == PrimitiveType_Int32);
  14.132 -        array->writeInt32(index, v.i32);
  14.133 -        break;
  14.134 -    }
  14.135 -}
  14.136 -
  14.137 -static void
  14.138 -FetchField(Struct *obj, Descriptor *desc, LocalSlot *vp)
  14.139 -{
  14.140 -    // :TODO: assert no GC.
  14.141 -    if (desc->type()->isTraceable()) {
  14.142 -        vp->obj = obj->get<Object *>(desc);
  14.143 -        return;
  14.144 -    }
  14.145 -
  14.146 -    switch (desc->type()->pod()) {
  14.147 -      case PrimitiveType_Float:
  14.148 -        vp->f = obj->get<float>(desc);
  14.149 -        break;
  14.150 -
  14.151 -      default:
  14.152 -        assert(desc->type()->pod() == PrimitiveType_Int32);
  14.153 -        vp->i32 = obj->get<int>(desc);
  14.154 -        break;
  14.155 -    }
  14.156 -}
  14.157 -
  14.158 -static void
  14.159 -GetField(Struct *obj, unsigned index, LocalSlot *vp)
  14.160 -{
  14.161 -    StructType *type = StructType::cast(obj->map()->type());
  14.162 -    Descriptor *desc = Descriptor::cast(type->fields()->at(index));
  14.163 -    FetchField(obj, desc, vp);
  14.164 -}
  14.165 -
  14.166 -static void
  14.167 -GetGlobal(Zone *zone, Handle<Struct> obj, Handle<String> name, LocalSlot *vp)
  14.168 -{
  14.169 -    Local<StructType> type(zone, StructType::cast(obj->map()->type()));
  14.170 -    Local<Descriptor> desc(zone, type->lookupField(name, NULL));
  14.171 -    FetchField(obj, desc, vp);
  14.172 -}
  14.173 -
  14.174 -static void
  14.175 -StoreField(Zone *zone, Struct *obj, Descriptor *desc, const LocalSlot &v)
  14.176 -{
  14.177 -    // :TODO: assert no GC.
  14.178 -    if (desc->type()->isTraceable()) {
  14.179 -        obj->set(zone, desc, v.obj);
  14.180 -        return;
  14.181 -    }
  14.182 -
  14.183 -    switch (desc->type()->pod()) {
  14.184 -      case PrimitiveType_Float:
  14.185 -        obj->set<float>(desc, v.f);
  14.186 -        break;
  14.187 -
  14.188 -      default:
  14.189 -        assert(desc->type()->pod() == PrimitiveType_Int32);
  14.190 -        obj->set<int>(desc, v.i32);
  14.191 -        break;
  14.192 -    }
  14.193 -}
  14.194 -
  14.195 -static void
  14.196 -SetField(Zone *zone, Struct *obj, unsigned index, const LocalSlot &v)
  14.197 -{
  14.198 -    StructType *type = StructType::cast(obj->map()->type());
  14.199 -    Descriptor *desc = Descriptor::cast(type->fields()->at(index));
  14.200 -    StoreField(zone, obj, desc, v);
  14.201 -}
  14.202 -
  14.203 -static void
  14.204 -SetGlobal(Zone *zone, Handle<Struct> obj, Handle<String> name, LocalSlot &v)
  14.205 -{
  14.206 -    Local<StructType> type(zone, StructType::cast(obj->map()->type()));
  14.207 -    Local<Descriptor> desc(zone, type->lookupField(name, NULL));
  14.208 -    StoreField(zone, obj, desc, v);
  14.209 -}
  14.210 -
  14.211 -static bool
  14.212 -InvokeNative(Zone *zone, Handle<Native> native, void *identity, LocalSlot *args, unsigned argc,
  14.213 -             int *result)
  14.214 -{
  14.215 -    NativeArgs guard;
  14.216 -
  14.217 -    void *address = zone->nativeTable()->address(native->index());
  14.218 -    if (!address) {
  14.219 -        Local<String> name(zone, zone->nativeTable()->name(native->index()));
  14.220 -        zone->reportError(Message_NativeNotBound, name->chars());
  14.221 -        return false;
  14.222 -    }
  14.223 -
  14.224 -    if (!zone->stack().pushNativeFrame(native, guard, argc + 1))
  14.225 -        return false;
  14.226 -
  14.227 -    intptr_t *cells = guard.args();
  14.228 -
  14.229 -    // params[0] == argc, in ISPE
  14.230 -    cells[0] = argc;
  14.231 -
  14.232 -    // Pass the formal arguments.
  14.233 -    Local<FunctionType> type(zone, native->type());
  14.234 -    Local<Type> param(zone);
  14.235 -    for (unsigned i = 0; i < type->parameters()->length(); i++) {
  14.236 -        param = type->parameterAt(i);
  14.237 -        
  14.238 -        // For floats, we rely on the aliasing of |i32| and |f|.
  14.239 -        LocalSlot &arg = args[-int(i) - 1];
  14.240 -        if (param->isInt32() || param->isFloat()) {
  14.241 -            cells[i + 1] = arg.i32;
  14.242 -        } else if (param->isReference()) {
  14.243 -            cells[i + 1] = reinterpret_cast<intptr_t>(arg.ref->location());
  14.244 -        } else {
  14.245 -            assert(param->isArray());
  14.246 -            cells[i + 1] = reinterpret_cast<intptr_t>(arg.array->bytes());
  14.247 -        }
  14.248 -    }
  14.249 -
  14.250 -    // For variadic arguments, the compiler left either arrays or references.
  14.251 -    for (unsigned i = type->parameters()->length(); i < argc; i++) {
  14.252 -        LocalSlot &arg = args[-int(i) - 1];
  14.253 -
  14.254 -        if (arg.obj->is(MapKind_Reference)) {
  14.255 -            cells[i + 1] = reinterpret_cast<intptr_t>(arg.ref->location());
  14.256 -        } else {
  14.257 -            assert(arg.obj->is(MapKind_Array));
  14.258 -            cells[i + 1] = reinterpret_cast<intptr_t>(arg.array->bytes());
  14.259 -        }
  14.260 -    }
  14.261 -
  14.262 -    typedef intptr_t (*INVOKE)(void *, intptr_t *);
  14.263 -    INVOKE invoke = (INVOKE)address;
  14.264 -    *result = invoke(identity, cells);
  14.265 -
  14.266 -    return !zone->hasPendingException();
  14.267 -}
  14.268 -
  14.269 -bool
  14.270 -ke::Interpret(Zone *zone, Frame *entryFrame, LocalSlot *result)
  14.271 -{
  14.272 -    Top &top = *zone->stack().top();
  14.273 -    if (!entryFrame)
  14.274 -        entryFrame = top.fp;
  14.275 -
  14.276 -    LocalSlot *locals = entryFrame->locals();
  14.277 -
  14.278 -    for (;;) {
  14.279 -        Opcode op = Opcode(*top.pc);
  14.280 -
  14.281 -        if (OpcodeInfo[op].nuses > 0)
  14.282 -            assert(top.sp - OpcodeInfo[op].nuses >= top.fp->stackBase());
  14.283 -
  14.284 -        switch (op) {
  14.285 -
  14.286 -case OP_NOP:
  14.287 -    break;
  14.288 -
  14.289 -case OP_INT:
  14.290 -    PUSH_I32(top, READ_INT32(top.pc));
  14.291 -    break;
  14.292 -
  14.293 -case OP_FLOAT:
  14.294 -    PUSH_F(top, READ_FLOAT(top.pc));
  14.295 -    break;
  14.296 -
  14.297 -case OP_RETURN:
  14.298 -case OP_RETURNVOID:
  14.299 -case OP_STOP:
  14.300 -{
  14.301 -    if (op == OP_RETURN)
  14.302 -        *result = *--top.sp;
  14.303 -
  14.304 -    if (top.fp == entryFrame)
  14.305 -        goto done;
  14.306 -
  14.307 -    // This must not GC.
  14.308 -    zone->stack().popInlineFrame();
  14.309 -    locals = top.fp->locals();
  14.310 -
  14.311 -    if (op == OP_RETURN)
  14.312 -        *top.sp++ = *result;
  14.313 -
  14.314 -    top.pc += OpcodeInfo[*top.pc].length;
  14.315 -    continue;
  14.316 -}
  14.317 -
  14.318 -case OP_POP:
  14.319 -{
  14.320 -    top.sp--;
  14.321 -    break;
  14.322 -}
  14.323 -
  14.324 -case OP_JT:
  14.325 -{
  14.326 -    int value = POP_I32(top);
  14.327 -    if (value) {
  14.328 -        top.pc += READ_INT32(top.pc);
  14.329 -        continue;
  14.330 -    }
  14.331 -    break;
  14.332 -}
  14.333 -
  14.334 -case OP_JF:
  14.335 -{
  14.336 -    int value = POP_I32(top);
  14.337 -    if (!value) {
  14.338 -        top.pc += READ_INT32(top.pc);
  14.339 -        continue;
  14.340 -    }
  14.341 -    break;
  14.342 -}
  14.343 -
  14.344 -case OP_JUMP:
  14.345 -{
  14.346 -    top.pc += READ_INT32(top.pc);
  14.347 -    continue;
  14.348 -}
  14.349 -
  14.350 -case OP_BREAK:
  14.351 -case OP_CONTINUE:
  14.352 -{
  14.353 -    top.fp->leaveLoop(zone);
  14.354 -    top.pc += READ_INT32(top.pc);
  14.355 -    continue;
  14.356 -}
  14.357 -
  14.358 -case OP_GETLOCAL:
  14.359 -{
  14.360 -    unsigned slot = READ_UINT32(top.pc);
  14.361 -    assert(slot < top.fp->code()->nlocals());
  14.362 -    *top.sp++ = locals[slot];
  14.363 -    break;
  14.364 -}
  14.365 -
  14.366 -case OP_SETLOCAL:
  14.367 -{
  14.368 -    unsigned slot = READ_UINT32(top.pc);
  14.369 -    assert(slot < top.fp->code()->nlocals());
  14.370 -    locals[slot] = top.sp[-1];
  14.371 -    break;
  14.372 -}
  14.373 -
  14.374 -case OP_ADD:
  14.375 -{
  14.376 -    top.sp[-2].i32 = top.sp[-2].i32 + top.sp[-1].i32;
  14.377 -    top.sp--;
  14.378 -    break;
  14.379 -}
  14.380 -
  14.381 -case OP_SUB:
  14.382 -{
  14.383 -    top.sp[-2].i32 = top.sp[-2].i32 - top.sp[-1].i32;
  14.384 -    top.sp--;
  14.385 -    break;
  14.386 -}
  14.387 -
  14.388 -case OP_MUL:
  14.389 -{
  14.390 -    top.sp[-2].i32 = top.sp[-2].i32 * top.sp[-1].i32;
  14.391 -    top.sp--;
  14.392 -    break;
  14.393 -}
  14.394 -
  14.395 -case OP_DIV:
  14.396 -{
  14.397 -    if (top.sp[-1].i32 == 0) {
  14.398 -        zone->reportError(Message_IntegerDivideByZero);
  14.399 -        goto error;
  14.400 -    }
  14.401 -    top.sp[-2].i32 = top.sp[-2].i32 / top.sp[-1].i32;
  14.402 -    top.sp--;
  14.403 -    break;
  14.404 -}
  14.405 -
  14.406 -case OP_MOD:
  14.407 -{
  14.408 -    if (top.sp[-1].i32 == 0) {
  14.409 -        zone->reportError(Message_IntegerDivideByZero);
  14.410 -        goto error;
  14.411 -    }
  14.412 -    top.sp[-2].i32 = top.sp[-2].i32 % top.sp[-1].i32;
  14.413 -    top.sp--;
  14.414 -    break;
  14.415 -}
  14.416 -
  14.417 -case OP_LT:
  14.418 -{
  14.419 -    top.sp[-2].i32 = top.sp[-2].i32 < top.sp[-1].i32;
  14.420 -    top.sp--;
  14.421 -    break;
  14.422 -}
  14.423 -
  14.424 -case OP_LE:
  14.425 -{
  14.426 -    top.sp[-2].i32 = top.sp[-2].i32 <= top.sp[-1].i32;
  14.427 -    top.sp--;
  14.428 -    break;
  14.429 -}
  14.430 -
  14.431 -case OP_GT:
  14.432 -{
  14.433 -    top.sp[-2].i32 = top.sp[-2].i32 > top.sp[-1].i32;
  14.434 -    top.sp--;
  14.435 -    break;
  14.436 -}
  14.437 -
  14.438 -case OP_GE:
  14.439 -{
  14.440 -    top.sp[-2].i32 = top.sp[-2].i32 >= top.sp[-1].i32;
  14.441 -    top.sp--;
  14.442 -    break;
  14.443 -}
  14.444 -
  14.445 -case OP_EQ:
  14.446 -{
  14.447 -    top.sp[-2].i32 = (top.sp[-2].i32 == top.sp[-1].i32);
  14.448 -    top.sp--;
  14.449 -    break;
  14.450 -}
  14.451 -
  14.452 -case OP_NE:
  14.453 -{
  14.454 -    top.sp[-2].i32 = (top.sp[-2].i32 != top.sp[-1].i32);
  14.455 -    top.sp--;
  14.456 -    break;
  14.457 -}
  14.458 -
  14.459 -case OP_ADD_F:
  14.460 -{
  14.461 -    top.sp[-2].f = top.sp[-2].f + top.sp[-1].f;
  14.462 -    top.sp--;
  14.463 -    break;
  14.464 -}
  14.465 -
  14.466 -case OP_SUB_F:
  14.467 -{
  14.468 -    top.sp[-2].f = top.sp[-2].f - top.sp[-1].f;
  14.469 -    top.sp--;
  14.470 -    break;
  14.471 -}
  14.472 -
  14.473 -case OP_MUL_F:
  14.474 -{
  14.475 -    top.sp[-2].f = top.sp[-2].f * top.sp[-1].f;
  14.476 -    top.sp--;
  14.477 -    break;
  14.478 -}
  14.479 -
  14.480 -case OP_DIV_F:
  14.481 -{
  14.482 -    top.sp[-2].f = top.sp[-2].f / top.sp[-1].f;
  14.483 -    top.sp--;
  14.484 -    break;
  14.485 -}
  14.486 -
  14.487 -case OP_LT_F:
  14.488 -{
  14.489 -    top.sp[-2].f = top.sp[-2].f < top.sp[-1].f;
  14.490 -    top.sp--;
  14.491 -    break;
  14.492 -}
  14.493 -
  14.494 -case OP_LE_F:
  14.495 -{
  14.496 -    top.sp[-2].f = top.sp[-2].f <= top.sp[-1].f;
  14.497 -    top.sp--;
  14.498 -    break;
  14.499 -}
  14.500 -
  14.501 -case OP_GT_F:
  14.502 -{
  14.503 -    top.sp[-2].f = top.sp[-2].f > top.sp[-1].f;
  14.504 -    top.sp--;
  14.505 -    break;
  14.506 -}
  14.507 -
  14.508 -case OP_GE_F:
  14.509 -{
  14.510 -    top.sp[-2].f = top.sp[-2].f >= top.sp[-1].f;
  14.511 -    top.sp--;
  14.512 -    break;
  14.513 -}
  14.514 -
  14.515 -case OP_EQ_F:
  14.516 -{
  14.517 -    top.sp[-2].i32 = (top.sp[-2].f == top.sp[-1].f);
  14.518 -    top.sp--;
  14.519 -    break;
  14.520 -}
  14.521 -
  14.522 -case OP_NE_F:
  14.523 -{
  14.524 -    top.sp[-2].i32 = (top.sp[-2].f != top.sp[-1].f);
  14.525 -    top.sp--;
  14.526 -    break;
  14.527 -}
  14.528 -
  14.529 -case OP_SHL:
  14.530 -{
  14.531 -    top.sp[-2].i32 = top.sp[-2].i32 << top.sp[-1].i32;
  14.532 -    top.sp--;
  14.533 -    break;
  14.534 -}
  14.535 -
  14.536 -case OP_SHR:
  14.537 -{
  14.538 -    top.sp[-2].i32 = top.sp[-2].i32 >> top.sp[-1].i32;
  14.539 -    top.sp--;
  14.540 -    break;
  14.541 -}
  14.542 -
  14.543 -case OP_USHR:
  14.544 -{
  14.545 -    top.sp[-2].i32 = unsigned(top.sp[-2].i32) >> unsigned(top.sp[-1].i32);
  14.546 -    top.sp--;
  14.547 -    break;
  14.548 -}
  14.549 -
  14.550 -case OP_BITAND:
  14.551 -{
  14.552 -    top.sp[-2].i32 = top.sp[-2].i32 & top.sp[-1].i32;
  14.553 -    top.sp--;
  14.554 -    break;
  14.555 -}
  14.556 -
  14.557 -case OP_BITOR:
  14.558 -{
  14.559 -    top.sp[-2].i32 = top.sp[-2].i32 | top.sp[-1].i32;
  14.560 -    top.sp--;
  14.561 -    break;
  14.562 -}
  14.563 -
  14.564 -case OP_BITXOR:
  14.565 -{
  14.566 -    top.sp[-2].i32 = top.sp[-2].i32 ^ top.sp[-1].i32;
  14.567 -    top.sp--;
  14.568 -    break;
  14.569 -}
  14.570 -
  14.571 -case OP_BITNOT:
  14.572 -{
  14.573 -    top.sp[-1].i32 = ~top.sp[-1].i32;
  14.574 -    break;
  14.575 -}
  14.576 -
  14.577 -case OP_NOT:
  14.578 -{
  14.579 -    top.sp[-1].i32 = top.sp[-1].i32 ? 0 : 1;
  14.580 -    break;
  14.581 -}
  14.582 -
  14.583 -case OP_NOT_F:
  14.584 -{
  14.585 -    top.sp[-1].i32 = top.sp[-1].f ? 0 : 1;
  14.586 -    break;
  14.587 -}
  14.588 -
  14.589 -case OP_NEG:
  14.590 -{
  14.591 -    top.sp[-1].i32 = -top.sp[-1].i32;
  14.592 -    break;
  14.593 -}
  14.594 -
  14.595 -case OP_NEG_F:
  14.596 -{
  14.597 -    top.sp[-1].f = -top.sp[-1].f;
  14.598 -    break;
  14.599 -}
  14.600 -
  14.601 -case OP_CALL:
  14.602 -{
  14.603 -    Local<Function> newFun(zone, Function::cast(top.sp[-1].obj));
  14.604 -    top.sp--;
  14.605 -
  14.606 -    if (!zone->stack().pushInlineFrame(newFun))
  14.607 -        goto error;
  14.608 -
  14.609 -    locals = top.fp->locals();
  14.610 -    continue;
  14.611 -}
  14.612 -
  14.613 -case OP_GETARG:
  14.614 -{
  14.615 -    unsigned slot = READ_UINT32(top.pc);
  14.616 -    *top.sp++ = top.fp->arg(slot);
  14.617 -    break;
  14.618 -}
  14.619 -
  14.620 -case OP_SETARG:
  14.621 -{
  14.622 -    unsigned slot = READ_UINT32(top.pc);
  14.623 -    top.fp->arg(slot) = top.sp[-1];
  14.624 -    break;
  14.625 -}
  14.626 -
  14.627 -case OP_GETELEM:
  14.628 -{
  14.629 -    Array *array = Array::cast(top.sp[-2].obj);
  14.630 -    int index = top.sp[-1].i32;
  14.631 -
  14.632 -    if (index < 0 || unsigned(index) >= array->length()) {
  14.633 -        zone->reportError(Message_ArrayIndexOutOfBounds, index, array->length());
  14.634 -        goto error;
  14.635 -    }
  14.636 -
  14.637 -    GetElement(array, index, &top.sp[-2]);
  14.638 -    top.sp--;
  14.639 -    break;
  14.640 -}
  14.641 -
  14.642 -case OP_SETELEM:
  14.643 -{
  14.644 -    Array *array = Array::cast(top.sp[-3].obj);
  14.645 -    int index = top.sp[-2].i32;
  14.646 -
  14.647 -    if (index < 0 || unsigned(index) >= array->length()) {
  14.648 -        zone->reportError(Message_ArrayIndexOutOfBounds, index, array->length());
  14.649 -        goto error;
  14.650 -    }
  14.651 -
  14.652 -    SetElement(zone, array, index, top.sp[-1]);
  14.653 -    top.sp[-3] = top.sp[-1];
  14.654 -    top.sp -= 2;
  14.655 -    break;
  14.656 -}
  14.657 -
  14.658 -case OP_CVT_I2F:
  14.659 -{
  14.660 -    int ival = POP_I32(top);
  14.661 -    float fval = (float)ival;
  14.662 -    PUSH_F(top, fval);
  14.663 -    break;
  14.664 -}
  14.665 -
  14.666 -case OP_CVT_I2B:
  14.667 -{
  14.668 -    top.sp[-1].i32 = !!top.sp[-1].i32;
  14.669 -    break;
  14.670 -}
  14.671 -
  14.672 -case OP_DUPARRAY:
  14.673 -{
  14.674 -    Local<Array> src(zone, Array::cast(top.sp[-1].obj));
  14.675 -    top.sp[-1].obj = Array::DeepCopy(zone, src, Heap::Tenure_Default);
  14.676 -    if (!top.sp[-1].obj)
  14.677 -        goto error;
  14.678 -    break;
  14.679 -}
  14.680 -
  14.681 -case OP_NEWFIXED:
  14.682 -{
  14.683 -    Heap::Tenure tenure = (Heap::Tenure)top.pc[1];
  14.684 -    Local<ArrayMap> map(zone, ArrayMap::cast(top.fp->code()->map(READ_UINT32(top.pc + 1))));
  14.685 -    Array *array = Array::NewFixed(zone, map, tenure);
  14.686 -    if (!array)
  14.687 -        goto error;
  14.688 -    top.sp->obj = array;
  14.689 -    top.sp++;
  14.690 -    break;
  14.691 -}
  14.692 -
  14.693 -case OP_NEWEMPTY:
  14.694 -{
  14.695 -    Heap::Tenure tenure = (Heap::Tenure)top.pc[1];
  14.696 -    Local<ArrayMap> map(zone, ArrayMap::cast(top.fp->code()->map(READ_UINT32(top.pc + 1))));
  14.697 -    Array *array = Array::NewEmpty(zone, map, tenure);
  14.698 -    if (!array)
  14.699 -        goto error;
  14.700 -    top.sp->obj = array;
  14.701 -    top.sp++;
  14.702 -    break;
  14.703 -}
  14.704 -
  14.705 -case OP_NEWSIZED:
  14.706 -{
  14.707 -    Heap::Tenure tenure = (Heap::Tenure)top.pc[1];
  14.708 -    Local<ArrayMap> map(zone, ArrayMap::cast(top.fp->code()->map(READ_UINT32(top.pc + 1))));
  14.709 -    assert(map->type()->levels() < MAX_ARRAY_DEPTH);
  14.710 -
  14.711 -    int dims[MAX_ARRAY_DEPTH];
  14.712 -    for (unsigned i = map->type()->levels() - 1; i < map->type()->levels(); i--)
  14.713 -        dims[i] = POP_I32(top);
  14.714 -
  14.715 -    Array *array = Array::NewSized(zone, map, dims, tenure);
  14.716 -    if (!array)
  14.717 -        goto error;
  14.718 -    top.sp->obj = array;
  14.719 -    top.sp++;
  14.720 -    break;
  14.721 -}
  14.722 -
  14.723 -case OP_NEWSTRUCT:
  14.724 -{
  14.725 -    Heap::Tenure tenure = (Heap::Tenure)top.pc[1];
  14.726 -    Local<StructMap> map(zone, StructMap::cast(top.fp->code()->map(READ_UINT32(top.pc + 1))));
  14.727 -    top.sp->obj = Struct::New(zone, map, tenure);
  14.728 -    if (!top.sp->obj)
  14.729 -        goto error;
  14.730 -    top.sp++;
  14.731 -    break;
  14.732 -}
  14.733 -
  14.734 -case OP_SAVELIFO:
  14.735 -{
  14.736 -    unsigned slot = READ_UINT32(top.pc);
  14.737 -    locals[slot].address = zone->heap().lifoPosition();
  14.738 -    break;
  14.739 -}
  14.740 -
  14.741 -case OP_UNWINDLIFO:
  14.742 -{
  14.743 -    unsigned slot = READ_UINT32(top.pc);
  14.744 -    zone->heap().unwindLifo(locals[slot].address);
  14.745 -    break;
  14.746 -}
  14.747 -
  14.748 -case OP_VARREF_LIFO:
  14.749 -{
  14.750 -    unsigned slot = READ_UINT32(top.pc);
  14.751 -    if (!PushNewRef(zone, top, &locals[slot], Heap::Tenure_Stack))
  14.752 -        goto error;
  14.753 -    break;
  14.754 -}
  14.755 -
  14.756 -case OP_ARGREF_LIFO:
  14.757 -{
  14.758 -    unsigned slot = READ_UINT32(top.pc);
  14.759 -    if (!PushNewRef(zone, top, &top.fp->arg(slot), Heap::Tenure_Stack))
  14.760 -        goto error;
  14.761 -    break;
  14.762 -}
  14.763 -
  14.764 -case OP_SLOTREF_LIFO:
  14.765 -{
  14.766 -    Reference *ref = Reference::NewStack(zone, top.sp[-1], Heap::Tenure_Stack);
  14.767 -    if (!ref)
  14.768 -        goto error;
  14.769 -    top.sp[-1].ref = ref;
  14.770 -    break;
  14.771 -}
  14.772 -
  14.773 -case OP_GETREF_I:
  14.774 -{
  14.775 -    top.sp[-1].i32 = top.sp[-1].ref->getInt();
  14.776 -    break;
  14.777 -}
  14.778 -
  14.779 -case OP_SETREF_I:
  14.780 -{
  14.781 -    top.sp[-2].ref->setInt(top.sp[-1].i32);
  14.782 -    top.sp[-2].i32 = top.sp[-1].i32;
  14.783 -    top.sp--;
  14.784 -    break;
  14.785 -}
  14.786 -
  14.787 -case OP_GETREF_F:
  14.788 -{
  14.789 -    top.sp[-1].f = top.sp[-1].ref->getFloat();
  14.790 -    break;
  14.791 -}
  14.792 -
  14.793 -case OP_SETREF_F:
  14.794 -{
  14.795 -    top.sp[-2].ref->setFloat(top.sp[-1].f);
  14.796 -    top.sp[-2].f = top.sp[-1].f;
  14.797 -    break;
  14.798 -}
  14.799 -
  14.800 -case OP_OBJECT:
  14.801 -{
  14.802 -    top.sp->obj = top.fp->code()->object(READ_UINT32(top.pc));
  14.803 -    top.sp++;
  14.804 -    break;
  14.805 -}
  14.806 -
  14.807 -case OP_COPYARRAY:
  14.808 -{
  14.809 -    // Note for this assignment opcode, we return the left-hand side, not the
  14.810 -    // right, since in this case the result of the expression could be different.
  14.811 -    Local<Array> left(zone, Array::cast(top.sp[-2].array));
  14.812 -    Local<Array> right(zone, Array::cast(top.sp[-1].array));
  14.813 -    if (!Array::ShallowCopy(zone, left, right))
  14.814 -        goto error;
  14.815 -    top.sp--;
  14.816 -    break;
  14.817 -}
  14.818 -
  14.819 -case OP_DUP:
  14.820 -{
  14.821 -    top.sp++;
  14.822 -    top.sp[-1] = top.sp[-2];
  14.823 -    break;
  14.824 -}
  14.825 -
  14.826 -case OP_DUP2:
  14.827 -{
  14.828 -    top.sp += 2;
  14.829 -    top.sp[-2] = top.sp[-4];
  14.830 -    top.sp[-1] = top.sp[-3];
  14.831 -    break;
  14.832 -}
  14.833 -
  14.834 -case OP_SWAP:
  14.835 -{
  14.836 -    LocalSlot slot = top.sp[-2];
  14.837 -    top.sp[-2] = top.sp[-1];
  14.838 -    top.sp[-1] = slot;
  14.839 -    break;
  14.840 -}
  14.841 -
  14.842 -case OP_ROLL3:
  14.843 -{
  14.844 -    LocalSlot slot = top.sp[-3];
  14.845 -    top.sp[-3] = top.sp[-2];
  14.846 -    top.sp[-2] = top.sp[-1];
  14.847 -    top.sp[-1] = slot;
  14.848 -    break;
  14.849 -}
  14.850 -
  14.851 -case OP_PICK2:
  14.852 -{
  14.853 -    top.sp++;
  14.854 -    top.sp[-1] = top.sp[-3];
  14.855 -    break;
  14.856 -}
  14.857 -
  14.858 -case OP_PICK3:
  14.859 -{
  14.860 -    top.sp++;
  14.861 -    top.sp[-1] = top.sp[-4];
  14.862 -    break;
  14.863 -}
  14.864 -
  14.865 -case OP_CALLNATIVE:
  14.866 -{
  14.867 -    unsigned argc = READ_UINT32(top.pc);
  14.868 -
  14.869 -    Local<Native> native(zone, Native::cast(top.sp[-1].obj));
  14.870 -    top.sp--;
  14.871 -
  14.872 -    int result;
  14.873 -    void *nativeIdentity = top.fp->code()->module()->parent()->getNativeIdentity();
  14.874 -    if (!InvokeNative(zone, native, nativeIdentity, top.sp, argc, &result))
  14.875 -        goto error;
  14.876 -
  14.877 -    top.sp -= argc;
  14.878 -    PUSH_I32(top, result);
  14.879 -    break;
  14.880 -}
  14.881 -
  14.882 -case OP_BITCAST:
  14.883 -{
  14.884 -    // Because the stack is a union, this is a no-op.
  14.885 -    break;
  14.886 -}
  14.887 -
  14.888 -case OP_TRUE:
  14.889 -{
  14.890 -    top.sp++;
  14.891 -    top.sp[-1].i32 = 1;
  14.892 -    break;
  14.893 -}
  14.894 -
  14.895 -case OP_FALSE:
  14.896 -{
  14.897 -    top.sp++;
  14.898 -    top.sp[-1].i32 = 0;
  14.899 -    break;
  14.900 -}
  14.901 -
  14.902 -case OP_GETFIELD:
  14.903 -{
  14.904 -    Struct *obj;
  14.905 -    if (top.sp[-1].obj->is(MapKind_Module))
  14.906 -        obj = Module::cast(top.sp[-1].obj)->globals();
  14.907 -    else
  14.908 -        obj = Struct::cast(top.sp[-1].obj);
  14.909 -    GetField(obj, READ_UINT32(top.pc), &top.sp[-1]);
  14.910 -    break;
  14.911 -}
  14.912 -
  14.913 -case OP_SETFIELD:
  14.914 -{
  14.915 -    Struct *obj = Struct::cast(top.sp[-2].obj);
  14.916 -    SetField(zone, obj, READ_UINT32(top.pc), top.sp[-1]);
  14.917 -    top.sp[-2] = top.sp[-1];
  14.918 -    top.sp--;
  14.919 -    break;
  14.920 -}
  14.921 -
  14.922 -case OP_COPYSTRUCT:
  14.923 -{
  14.924 -    Local<Struct> left(zone, Struct::cast(top.sp[-2].obj));
  14.925 -    Local<Struct> right(zone, Struct::cast(top.sp[-1].obj));
  14.926 -    if (!Struct::Copy(zone, left, right))
  14.927 -        goto error;
  14.928 -    top.sp[-2].obj = top.sp[-1].obj;
  14.929 -    top.sp--;
  14.930 -    break;
  14.931 -}
  14.932 -
  14.933 -case OP_TABLESWITCH:
  14.934 -{
  14.935 -    int value = top.sp[-1].i32;
  14.936 -    int low = READ_TABLESWITCH_LOW(top.pc);
  14.937 -    int high = READ_TABLESWITCH_HIGH(top.pc);
  14.938 -
  14.939 -    top.sp--;
  14.940 -
  14.941 -    unsigned index = unsigned(value - low);
  14.942 -    unsigned tablesize = TableSwitchEntries(low, high);
  14.943 -    if (index < tablesize) {
  14.944 -        top.pc += OP_TABLESWITCH_LENGTH + OP_JUMP_LENGTH;
  14.945 -        top.pc += index * OP_JUMP_LENGTH;
  14.946 -        continue;
  14.947 -    }
  14.948 -    break;
  14.949 -}
  14.950 -
  14.951 -case OP_SIZEOF:
  14.952 -{
  14.953 -    Array *array = Array::cast(top.sp[-1].obj);
  14.954 -    top.sp[-1].i32 = array->length();
  14.955 -    break;
  14.956 -}
  14.957 -
  14.958 -case OP_PUBLIC:
  14.959 -{
  14.960 -    Local<Function> fun(zone, Function::cast(top.sp[-1].obj));
  14.961 -    zone->registerPublic(fun);
  14.962 -    top.sp--;
  14.963 -    break;
  14.964 -}
  14.965 -
  14.966 -case OP_SETGLOBAL:
  14.967 -{
  14.968 -    Local<Code> code(zone, top.fp->code());
  14.969 -    Local<Struct> obj(zone, code->module()->globals());
  14.970 -    Local<String> name(zone, String::cast(code->strings()->at(READ_UINT32(top.pc))));
  14.971 -    SetGlobal(zone, obj, name, top.sp[-1]);
  14.972 -    break;
  14.973 -}
  14.974 -
  14.975 -case OP_GETGLOBAL:
  14.976 -{
  14.977 -    Local<Code> code(zone, top.fp->code());
  14.978 -    Local<Struct> obj(zone, code->module()->globals());
  14.979 -    Local<String> name(zone, String::cast(code->strings()->at(READ_UINT32(top.pc))));
  14.980 -    GetGlobal(zone, obj, name, top.sp);
  14.981 -    top.sp++;
  14.982 -    break;
  14.983 -}
  14.984 -
  14.985 -case OP_ENTERLOOP:
  14.986 -{
  14.987 -    top.fp->enterLoop(zone);
  14.988 -    break;
  14.989 -}
  14.990 -
  14.991 -case OP_LEAVELOOP:
  14.992 -{
  14.993 -    top.fp->leaveLoop(zone);
  14.994 -    break;
  14.995 -}
  14.996 -
  14.997 -case OP_DEPARRAY:
  14.998 -{
  14.999 -    Local<ArrayMap> map(zone, ArrayMap::cast(top.fp->code()->object(READ_UINT32(top.pc))));
 14.1000 -    Local<Array> array(zone, Array::cast(top.sp[-2].obj));
 14.1001 -    int index = top.sp[-1].i32;
 14.1002 -
 14.1003 -    // We allow taking 0-length dependent arrays.
 14.1004 -    if (index < 0 || unsigned(index) > array->length()) {
 14.1005 -        zone->reportError(Message_ArrayIndexOutOfBounds, index, array->length());
 14.1006 -        goto error;
 14.1007 -    }
 14.1008 -
 14.1009 -    top.sp[-2].obj = DependentArray::New(zone, array, map, index);
 14.1010 -    if (!top.sp[-2].obj)
 14.1011 -        goto error;
 14.1012 -
 14.1013 -    top.sp--;
 14.1014 -    break;
 14.1015 -}
 14.1016 -
 14.1017 -case OP_IMPORT:
 14.1018 -{
 14.1019 -    unsigned index = READ_UINT32(top.pc);
 14.1020 -
 14.1021 -    top.sp++;
 14.1022 -    top.sp[-1].obj = top.fp->code()->module()->getImportAt(index);
 14.1023 -    break;
 14.1024 -}
 14.1025 -
 14.1026 -default:
 14.1027 -    assert(false);
 14.1028 -    return false;
 14.1029 -
 14.1030 -        }
 14.1031 -
 14.1032 -        top.pc += OpcodeInfo[op].length;
 14.1033 -        assert(top.sp >= top.fp->stackBase());
 14.1034 -    }
 14.1035 -
 14.1036 -done:
 14.1037 -    return true;
 14.1038 -
 14.1039 -error:
 14.1040 -    // Unwind frames until we can continue.
 14.1041 -    while (top.fp != entryFrame)
 14.1042 -        zone->stack().popInlineFrame();
 14.1043 -    return false;
 14.1044 -}
 14.1045 +/* vim: set ts=4 sw=4 tw=99 et:
 14.1046 + *
 14.1047 + * Copyright (C) 2012 David Anderson
 14.1048 + *
 14.1049 + * This file is part of JITCraft.
 14.1050 + *
 14.1051 + * JITCraft is free software: you can redistribute it and/or modify it under
 14.1052 + * the terms of the GNU General Public License as published by the Free
 14.1053 + * Software Foundation, either version 3 of the License, or (at your option)
 14.1054 + * any later version.
 14.1055 + * 
 14.1056 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
 14.1057 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 14.1058 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 14.1059 + *
 14.1060 + * You should have received a copy of the GNU General Public License along with
 14.1061 + * JITCraft. If not, see http://www.gnu.org/licenses/.
 14.1062 + */
 14.1063 +#include <string.h>
 14.1064 +#include "Interpreter.h"
 14.1065 +#include "Modules.h"
 14.1066 +#include "Zone.h"
 14.1067 +#include "Types.h"
 14.1068 +#include "Array.h"
 14.1069 +#include "Reference.h"
 14.1070 +#include "Strings.h"
 14.1071 +#include "Environments.h"
 14.1072 +#include "Structures.h"
 14.1073 +#include "NativeTable.h"
 14.1074 +#include "Packages.h"
 14.1075 +#include "Heap-inl.h"
 14.1076 +
 14.1077 +using namespace ke;
 14.1078 +
 14.1079 +#define PUSH_I32(top, value)    \
 14.1080 +    do {                        \
 14.1081 +        top.sp->i32 = value;    \
 14.1082 +        top.sp++;               \
 14.1083 +   } while (0)
 14.1084 +
 14.1085 +#define PUSH_F(top, value)      \
 14.1086 +    do {                        \
 14.1087 +        top.sp->f = value;      \
 14.1088 +        top.sp++;               \
 14.1089 +   } while (0)
 14.1090 +
 14.1091 +static inline int
 14.1092 +POP_I32(Top &top)
 14.1093 +{
 14.1094 +    int value = top.sp[-1].i32;
 14.1095 +    top.sp--;
 14.1096 +    return value;
 14.1097 +}
 14.1098 +
 14.1099 +static inline float
 14.1100 +POP_F(Top &top)
 14.1101 +{
 14.1102 +    float value = top.sp[-1].f;
 14.1103 +    top.sp--;
 14.1104 +    return value;
 14.1105 +}
 14.1106 +
 14.1107 +// Pawn's original semantics specify some kind of floor operation, so
 14.1108 +// (8 / -3 == -3) and (-8 / 3 == -1). The SourcePawn 1 compiler (spcomp) uses
 14.1109 +// the upstream algorithm when constant folding. However the SourcePawn 1 JIT
 14.1110 +// does not. My guess is that Borja freaked out seeing the 13-instruction x86
 14.1111 +// sequence necessary to get this functionality (I vaguely recall a thread
 14.1112 +// where we discussed this with Mark Peter? But the ITB forums are gone...),
 14.1113 +// and we just decided to break the damn thing. So SP1 was inconsistent, but
 14.1114 +// we are not. And for completeness, we assert that the C compiler does the
 14.1115 +// right thing, since C89 leaves it unspecified.
 14.1116 +STATIC_ASSERT(8 / -3 == -2);
 14.1117 +STATIC_ASSERT(-8 / 3 == -2);
 14.1118 +
 14.1119 +static inline bool
 14.1120 +PushNewRef(Zone *zone, Top &top, void *location, Heap::Tenure tenure)
 14.1121 +{
 14.1122 +    Reference *ref = Reference::NewStack(zone, location, tenure);
 14.1123 +    if (!ref)
 14.1124 +        return false;
 14.1125 +    top.sp->ref = ref;
 14.1126 +    top.sp++;
 14.1127 +    return true;
 14.1128 +}
 14.1129 +
 14.1130 +static void
 14.1131 +GetElement(Array *array, int index, LocalSlot *vp)
 14.1132 +{
 14.1133 +    if (array->type()->contained()->isTraceable()) {
 14.1134 +        vp->obj = array->readObject(index);
 14.1135 +        return;
 14.1136 +    }
 14.1137 +
 14.1138 +    switch (array->type()->contained()->pod()) {
 14.1139 +      case PrimitiveType_Float:
 14.1140 +        vp->f = array->readFloat(index);
 14.1141 +        break;
 14.1142 +
 14.1143 +      case PrimitiveType_Char:
 14.1144 +        vp->i32 = array->readChar(index);
 14.1145 +        break;
 14.1146 +
 14.1147 +      default:
 14.1148 +        assert(array->type()->contained()->pod() == PrimitiveType_Int32);
 14.1149 +        vp->i32 = array->readInt32(index);
 14.1150 +        break;
 14.1151 +    }
 14.1152 +}
 14.1153 +
 14.1154 +static void
 14.1155 +SetElement(Zone *zone, Array *array, int index, const LocalSlot &v)
 14.1156 +{
 14.1157 +    if (array->type()->contained()->isTraceable()) {
 14.1158 +        array->writeObject(zone, index, v.obj);
 14.1159 +        return;
 14.1160 +    }
 14.1161 +
 14.1162 +    switch (array->type()->contained()->pod()) {
 14.1163 +      case PrimitiveType_Float:
 14.1164 +        array->writeFloat(index, v.f);
 14.1165 +        break;
 14.1166 +
 14.1167 +      case PrimitiveType_Char:
 14.1168 +        array->writeChar(index, v.i32);
 14.1169 +        break;
 14.1170 +
 14.1171 +      default:
 14.1172 +        assert(array->type()->contained()->pod() == PrimitiveType_Int32);
 14.1173 +        array->writeInt32(index, v.i32);
 14.1174 +        break;
 14.1175 +    }
 14.1176 +}
 14.1177 +
 14.1178 +static void
 14.1179 +FetchField(Struct *obj, Descriptor *desc, LocalSlot *vp)
 14.1180 +{
 14.1181 +    // :TODO: assert no GC.
 14.1182 +    if (desc->type()->isTraceable()) {
 14.1183 +        vp->obj = obj->get<Object *>(desc);
 14.1184 +        return;
 14.1185 +    }
 14.1186 +
 14.1187 +    switch (desc->type()->pod()) {
 14.1188 +      case PrimitiveType_Float:
 14.1189 +        vp->f = obj->get<float>(desc);
 14.1190 +        break;
 14.1191 +
 14.1192 +      default:
 14.1193 +        assert(desc->type()->pod() == PrimitiveType_Int32);
 14.1194 +        vp->i32 = obj->get<int>(desc);
 14.1195 +        break;
 14.1196 +    }
 14.1197 +}
 14.1198 +
 14.1199 +static void
 14.1200 +GetField(Struct *obj, unsigned index, LocalSlot *vp)
 14.1201 +{
 14.1202 +    StructType *type = StructType::cast(obj->map()->type());
 14.1203 +    Descriptor *desc = Descriptor::cast(type->fields()->at(index));
 14.1204 +    FetchField(obj, desc, vp);
 14.1205 +}
 14.1206 +
 14.1207 +static void
 14.1208 +GetGlobal(Zone *zone, Handle<Struct> obj, Handle<String> name, LocalSlot *vp)
 14.1209 +{
 14.1210 +    Local<StructType> type(zone, StructType::cast(obj->map()->type()));
 14.1211 +    Local<Descriptor> desc(zone, type->lookupField(name, NULL));
 14.1212 +    FetchField(obj, desc, vp);
 14.1213 +}
 14.1214 +
 14.1215 +static void
 14.1216 +StoreField(Zone *zone, Struct *obj, Descriptor *desc, const LocalSlot &v)
 14.1217 +{
 14.1218 +    // :TODO: assert no GC.
 14.1219 +    if (desc->type()->isTraceable()) {
 14.1220 +        obj->set(zone, desc, v.obj);
 14.1221 +        return;
 14.1222 +    }
 14.1223 +
 14.1224 +    switch (desc->type()->pod()) {
 14.1225 +      case PrimitiveType_Float:
 14.1226 +        obj->set<float>(desc, v.f);
 14.1227 +        break;
 14.1228 +
 14.1229 +      default:
 14.1230 +        assert(desc->type()->pod() == PrimitiveType_Int32);
 14.1231 +        obj->set<int>(desc, v.i32);
 14.1232 +        break;
 14.1233 +    }
 14.1234 +}
 14.1235 +
 14.1236 +static void
 14.1237 +SetField(Zone *zone, Struct *obj, unsigned index, const LocalSlot &v)
 14.1238 +{
 14.1239 +    StructType *type = StructType::cast(obj->map()->type());
 14.1240 +    Descriptor *desc = Descriptor::cast(type->fields()->at(index));
 14.1241 +    StoreField(zone, obj, desc, v);
 14.1242 +}
 14.1243 +
 14.1244 +static void
 14.1245 +SetGlobal(Zone *zone, Handle<Struct> obj, Handle<String> name, LocalSlot &v)
 14.1246 +{
 14.1247 +    Local<StructType> type(zone, StructType::cast(obj->map()->type()));
 14.1248 +    Local<Descriptor> desc(zone, type->lookupField(name, NULL));
 14.1249 +    StoreField(zone, obj, desc, v);
 14.1250 +}
 14.1251 +
 14.1252 +static bool
 14.1253 +InvokeNative(Zone *zone, Handle<Native> native, void *identity, LocalSlot *args, unsigned argc,
 14.1254 +             int *result)
 14.1255 +{
 14.1256 +    NativeArgs guard;
 14.1257 +
 14.1258 +    void *address = zone->nativeTable()->address(native->index());
 14.1259 +    if (!address) {
 14.1260 +        Local<String> name(zone, zone->nativeTable()->name(native->index()));
 14.1261 +        zone->reportError(Message_NativeNotBound, name->chars());
 14.1262 +        return false;
 14.1263 +    }
 14.1264 +
 14.1265 +    if (!zone->stack().pushNativeFrame(native, guard, argc + 1))
 14.1266 +        return false;
 14.1267 +
 14.1268 +    intptr_t *cells = guard.args();
 14.1269 +
 14.1270 +    // params[0] == argc, in ISPE
 14.1271 +    cells[0] = argc;
 14.1272 +
 14.1273 +    // Pass the formal arguments.
 14.1274 +    Local<FunctionType> type(zone, native->type());
 14.1275 +    Local<Type> param(zone);
 14.1276 +    for (unsigned i = 0; i < type->parameters()->length(); i++) {
 14.1277 +        param = type->parameterAt(i);
 14.1278 +        
 14.1279 +        // For floats, we rely on the aliasing of |i32| and |f|.
 14.1280 +        LocalSlot &arg = args[-int(i) - 1];
 14.1281 +        if (param->isInt32() || param->isFloat()) {
 14.1282 +            cells[i + 1] = arg.i32;
 14.1283 +        } else if (param->isReference()) {
 14.1284 +            cells[i + 1] = reinterpret_cast<intptr_t>(arg.ref->location());
 14.1285 +        } else {
 14.1286 +            assert(param->isArray());
 14.1287 +            cells[i + 1] = reinterpret_cast<intptr_t>(arg.array->bytes());
 14.1288 +        }
 14.1289 +    }
 14.1290 +
 14.1291 +    // For variadic arguments, the compiler left either arrays or references.
 14.1292 +    for (unsigned i = type->parameters()->length(); i < argc; i++) {
 14.1293 +        LocalSlot &arg = args[-int(i) - 1];
 14.1294 +
 14.1295 +        if (arg.obj->is(MapKind_Reference)) {
 14.1296 +            cells[i + 1] = reinterpret_cast<intptr_t>(arg.ref->location());
 14.1297 +        } else {
 14.1298 +            assert(arg.obj->is(MapKind_Array));
 14.1299 +            cells[i + 1] = reinterpret_cast<intptr_t>(arg.array->bytes());
 14.1300 +        }
 14.1301 +    }
 14.1302 +
 14.1303 +    typedef intptr_t (*INVOKE)(void *, intptr_t *);
 14.1304 +    INVOKE invoke = (INVOKE)address;
 14.1305 +    *result = invoke(identity, cells);
 14.1306 +
 14.1307 +    return !zone->hasPendingException();
 14.1308 +}
 14.1309 +
 14.1310 +bool
 14.1311 +ke::Interpret(Zone *zone, Frame *entryFrame, LocalSlot *result)
 14.1312 +{
 14.1313 +    Top &top = *zone->stack().top();
 14.1314 +    if (!entryFrame)
 14.1315 +        entryFrame = top.fp;
 14.1316 +
 14.1317 +    LocalSlot *locals = entryFrame->locals();
 14.1318 +
 14.1319 +    for (;;) {
 14.1320 +        Opcode op = Opcode(*top.pc);
 14.1321 +
 14.1322 +        if (OpcodeInfo[op].nuses > 0)
 14.1323 +            assert(top.sp - OpcodeInfo[op].nuses >= top.fp->stackBase());
 14.1324 +
 14.1325 +        switch (op) {
 14.1326 +
 14.1327 +case OP_NOP:
 14.1328 +    break;
 14.1329 +
 14.1330 +case OP_INT:
 14.1331 +    PUSH_I32(top, READ_INT32(top.pc));
 14.1332 +    break;
 14.1333 +
 14.1334 +case OP_FLOAT:
 14.1335 +    PUSH_F(top, READ_FLOAT(top.pc));
 14.1336 +    break;
 14.1337 +
 14.1338 +case OP_RETURN:
 14.1339 +case OP_RETURNVOID:
 14.1340 +case OP_STOP:
 14.1341 +{
 14.1342 +    if (op == OP_RETURN)
 14.1343 +        *result = *--top.sp;
 14.1344 +
 14.1345 +    if (top.fp == entryFrame)
 14.1346 +        goto done;
 14.1347 +
 14.1348 +    // This must not GC.
 14.1349 +    zone->stack().popInlineFrame();
 14.1350 +    locals = top.fp->locals();
 14.1351 +
 14.1352 +    if (op == OP_RETURN)
 14.1353 +        *top.sp++ = *result;
 14.1354 +
 14.1355 +    top.pc += OpcodeInfo[*top.pc].length;
 14.1356 +    continue;
 14.1357 +}
 14.1358 +
 14.1359 +case OP_POP:
 14.1360 +{
 14.1361 +    top.sp--;
 14.1362 +    break;
 14.1363 +}
 14.1364 +
 14.1365 +case OP_JT:
 14.1366 +{
 14.1367 +    int value = POP_I32(top);
 14.1368 +    if (value) {
 14.1369 +        top.pc += READ_INT32(top.pc);
 14.1370 +        continue;
 14.1371 +    }
 14.1372 +    break;
 14.1373 +}
 14.1374 +
 14.1375 +case OP_JF:
 14.1376 +{
 14.1377 +    int value = POP_I32(top);
 14.1378 +    if (!value) {
 14.1379 +        top.pc += READ_INT32(top.pc);
 14.1380 +        continue;
 14.1381 +    }
 14.1382 +    break;
 14.1383 +}
 14.1384 +
 14.1385 +case OP_JUMP:
 14.1386 +{
 14.1387 +    top.pc += READ_INT32(top.pc);
 14.1388 +    continue;
 14.1389 +}
 14.1390 +
 14.1391 +case OP_BREAK:
 14.1392 +case OP_CONTINUE:
 14.1393 +{
 14.1394 +    top.fp->leaveLoop(zone);
 14.1395 +    top.pc += READ_INT32(top.pc);
 14.1396 +    continue;
 14.1397 +}
 14.1398 +
 14.1399 +case OP_GETLOCAL:
 14.1400 +{
 14.1401 +    unsigned slot = READ_UINT32(top.pc);
 14.1402 +    assert(slot < top.fp->code()->nlocals());
 14.1403 +    *top.sp++ = locals[slot];
 14.1404 +    break;
 14.1405 +}
 14.1406 +
 14.1407 +case OP_SETLOCAL:
 14.1408 +{
 14.1409 +    unsigned slot = READ_UINT32(top.pc);
 14.1410 +    assert(slot < top.fp->code()->nlocals());
 14.1411 +    locals[slot] = top.sp[-1];
 14.1412 +    break;
 14.1413 +}
 14.1414 +
 14.1415 +case OP_ADD:
 14.1416 +{
 14.1417 +    top.sp[-2].i32 = top.sp[-2].i32 + top.sp[-1].i32;
 14.1418 +    top.sp--;
 14.1419 +    break;
 14.1420 +}
 14.1421 +
 14.1422 +case OP_SUB:
 14.1423 +{
 14.1424 +    top.sp[-2].i32 = top.sp[-2].i32 - top.sp[-1].i32;
 14.1425 +    top.sp--;
 14.1426 +    break;
 14.1427 +}
 14.1428 +
 14.1429 +case OP_MUL:
 14.1430 +{
 14.1431 +    top.sp[-2].i32 = top.sp[-2].i32 * top.sp[-1].i32;
 14.1432 +    top.sp--;
 14.1433 +    break;
 14.1434 +}
 14.1435 +
 14.1436 +case OP_DIV:
 14.1437 +{
 14.1438 +    if (top.sp[-1].i32 == 0) {
 14.1439 +        zone->reportError(Message_IntegerDivideByZero);
 14.1440 +        goto error;
 14.1441 +    }
 14.1442 +    top.sp[-2].i32 = top.sp[-2].i32 / top.sp[-1].i32;
 14.1443 +    top.sp--;
 14.1444 +    break;
 14.1445 +}
 14.1446 +
 14.1447 +case OP_MOD:
 14.1448 +{
 14.1449 +    if (top.sp[-1].i32 == 0) {
 14.1450 +        zone->reportError(Message_IntegerDivideByZero);
 14.1451 +        goto error;
 14.1452 +    }
 14.1453 +    top.sp[-2].i32 = top.sp[-2].i32 % top.sp[-1].i32;
 14.1454 +    top.sp--;
 14.1455 +    break;
 14.1456 +}
 14.1457 +
 14.1458 +case OP_LT:
 14.1459 +{
 14.1460 +    top.sp[-2].i32 = top.sp[-2].i32 < top.sp[-1].i32;
 14.1461 +    top.sp--;
 14.1462 +    break;
 14.1463 +}
 14.1464 +
 14.1465 +case OP_LE:
 14.1466 +{
 14.1467 +    top.sp[-2].i32 = top.sp[-2].i32 <= top.sp[-1].i32;
 14.1468 +    top.sp--;
 14.1469 +    break;
 14.1470 +}
 14.1471 +
 14.1472 +case OP_GT:
 14.1473 +{
 14.1474 +    top.sp[-2].i32 = top.sp[-2].i32 > top.sp[-1].i32;
 14.1475 +    top.sp--;
 14.1476 +    break;
 14.1477 +}
 14.1478 +
 14.1479 +case OP_GE:
 14.1480 +{
 14.1481 +    top.sp[-2].i32 = top.sp[-2].i32 >= top.sp[-1].i32;
 14.1482 +    top.sp--;
 14.1483 +    break;
 14.1484 +}
 14.1485 +
 14.1486 +case OP_EQ:
 14.1487 +{
 14.1488 +    top.sp[-2].i32 = (top.sp[-2].i32 == top.sp[-1].i32);
 14.1489 +    top.sp--;
 14.1490 +    break;
 14.1491 +}
 14.1492 +
 14.1493 +case OP_NE:
 14.1494 +{
 14.1495 +    top.sp[-2].i32 = (top.sp[-2].i32 != top.sp[-1].i32);
 14.1496 +    top.sp--;
 14.1497 +    break;
 14.1498 +}
 14.1499 +
 14.1500 +case OP_ADD_F:
 14.1501 +{
 14.1502 +    top.sp[-2].f = top.sp[-2].f + top.sp[-1].f;
 14.1503 +    top.sp--;
 14.1504 +    break;
 14.1505 +}
 14.1506 +
 14.1507 +case OP_SUB_F:
 14.1508 +{
 14.1509 +    top.sp[-2].f = top.sp[-2].f - top.sp[-1].f;
 14.1510 +    top.sp--;
 14.1511 +    break;
 14.1512 +}
 14.1513 +
 14.1514 +case OP_MUL_F:
 14.1515 +{
 14.1516 +    top.sp[-2].f = top.sp[-2].f * top.sp[-1].f;
 14.1517 +    top.sp--;
 14.1518 +    break;
 14.1519 +}
 14.1520 +
 14.1521 +case OP_DIV_F:
 14.1522 +{
 14.1523 +    top.sp[-2].f = top.sp[-2].f / top.sp[-1].f;
 14.1524 +    top.sp--;
 14.1525 +    break;
 14.1526 +}
 14.1527 +
 14.1528 +case OP_LT_F:
 14.1529 +{
 14.1530 +    top.sp[-2].f = top.sp[-2].f < top.sp[-1].f;
 14.1531 +    top.sp--;
 14.1532 +    break;
 14.1533 +}
 14.1534 +
 14.1535 +case OP_LE_F:
 14.1536 +{
 14.1537 +    top.sp[-2].f = top.sp[-2].f <= top.sp[-1].f;
 14.1538 +    top.sp--;
 14.1539 +    break;
 14.1540 +}
 14.1541 +
 14.1542 +case OP_GT_F:
 14.1543 +{
 14.1544 +    top.sp[-2].f = top.sp[-2].f > top.sp[-1].f;
 14.1545 +    top.sp--;
 14.1546 +    break;
 14.1547 +}
 14.1548 +
 14.1549 +case OP_GE_F:
 14.1550 +{
 14.1551 +    top.sp[-2].f = top.sp[-2].f >= top.sp[-1].f;
 14.1552 +    top.sp--;
 14.1553 +    break;
 14.1554 +}
 14.1555 +
 14.1556 +case OP_EQ_F:
 14.1557 +{
 14.1558 +    top.sp[-2].i32 = (top.sp[-2].f == top.sp[-1].f);
 14.1559 +    top.sp--;
 14.1560 +    break;
 14.1561 +}
 14.1562 +
 14.1563 +case OP_NE_F:
 14.1564 +{
 14.1565 +    top.sp[-2].i32 = (top.sp[-2].f != top.sp[-1].f);
 14.1566 +    top.sp--;
 14.1567 +    break;
 14.1568 +}
 14.1569 +
 14.1570 +case OP_SHL:
 14.1571 +{
 14.1572 +    top.sp[-2].i32 = top.sp[-2].i32 << top.sp[-1].i32;
 14.1573 +    top.sp--;
 14.1574 +    break;
 14.1575 +}
 14.1576 +
 14.1577 +case OP_SHR:
 14.1578 +{
 14.1579 +    top.sp[-2].i32 = top.sp[-2].i32 >> top.sp[-1].i32;
 14.1580 +    top.sp--;
 14.1581 +    break;
 14.1582 +}
 14.1583 +
 14.1584 +case OP_USHR:
 14.1585 +{
 14.1586 +    top.sp[-2].i32 = unsigned(top.sp[-2].i32) >> unsigned(top.sp[-1].i32);
 14.1587 +    top.sp--;
 14.1588 +    break;
 14.1589 +}
 14.1590 +
 14.1591 +case OP_BITAND:
 14.1592 +{
 14.1593 +    top.sp[-2].i32 = top.sp[-2].i32 & top.sp[-1].i32;
 14.1594 +    top.sp--;
 14.1595 +    break;
 14.1596 +}
 14.1597 +
 14.1598 +case OP_BITOR:
 14.1599 +{
 14.1600 +    top.sp[-2].i32 = top.sp[-2].i32 | top.sp[-1].i32;
 14.1601 +    top.sp--;
 14.1602 +    break;
 14.1603 +}
 14.1604 +
 14.1605 +case OP_BITXOR:
 14.1606 +{
 14.1607 +    top.sp[-2].i32 = top.sp[-2].i32 ^ top.sp[-1].i32;
 14.1608 +    top.sp--;
 14.1609 +    break;
 14.1610 +}
 14.1611 +
 14.1612 +case OP_BITNOT:
 14.1613 +{
 14.1614 +    top.sp[-1].i32 = ~top.sp[-1].i32;
 14.1615 +    break;
 14.1616 +}
 14.1617 +
 14.1618 +case OP_NOT:
 14.1619 +{
 14.1620 +    top.sp[-1].i32 = top.sp[-1].i32 ? 0 : 1;
 14.1621 +    break;
 14.1622 +}
 14.1623 +
 14.1624 +case OP_NOT_F:
 14.1625 +{
 14.1626 +    top.sp[-1].i32 = top.sp[-1].f ? 0 : 1;
 14.1627 +    break;
 14.1628 +}
 14.1629 +
 14.1630 +case OP_NEG:
 14.1631 +{
 14.1632 +    top.sp[-1].i32 = -top.sp[-1].i32;
 14.1633 +    break;
 14.1634 +}
 14.1635 +
 14.1636 +case OP_NEG_F:
 14.1637 +{
 14.1638 +    top.sp[-1].f = -top.sp[-1].f;
 14.1639 +    break;
 14.1640 +}
 14.1641 +
 14.1642 +case OP_CALL:
 14.1643 +{
 14.1644 +    Local<Function> newFun(zone, Function::cast(top.sp[-1].obj));
 14.1645 +    top.sp--;
 14.1646 +
 14.1647 +    if (!zone->stack().pushInlineFrame(newFun))
 14.1648 +        goto error;
 14.1649 +
 14.1650 +    locals = top.fp->locals();
 14.1651 +    continue;
 14.1652 +}
 14.1653 +
 14.1654 +case OP_GETARG:
 14.1655 +{
 14.1656 +    unsigned slot = READ_UINT32(top.pc);
 14.1657 +    *top.sp++ = top.fp->arg(slot);
 14.1658 +    break;
 14.1659 +}
 14.1660 +
 14.1661 +case OP_SETARG:
 14.1662 +{
 14.1663 +    unsigned slot = READ_UINT32(top.pc);
 14.1664 +    top.fp->arg(slot) = top.sp[-1];
 14.1665 +    break;
 14.1666 +}
 14.1667 +
 14.1668 +case OP_GETELEM:
 14.1669 +{
 14.1670 +    Array *array = Array::cast(top.sp[-2].obj);
 14.1671 +    int index = top.sp[-1].i32;
 14.1672 +
 14.1673 +    if (index < 0 || unsigned(index) >= array->length()) {
 14.1674 +        zone->reportError(Message_ArrayIndexOutOfBounds, index, array->length());
 14.1675 +        goto error;
 14.1676 +    }
 14.1677 +
 14.1678 +    GetElement(array, index, &top.sp[-2]);
 14.1679 +    top.sp--;
 14.1680 +    break;
 14.1681 +}
 14.1682 +
 14.1683 +case OP_SETELEM:
 14.1684 +{
 14.1685 +    Array *array = Array::cast(top.sp[-3].obj);
 14.1686 +    int index = top.sp[-2].i32;
 14.1687 +
 14.1688 +    if (index < 0 || unsigned(index) >= array->length()) {
 14.1689 +        zone->reportError(Message_ArrayIndexOutOfBounds, index, array->length());
 14.1690 +        goto error;
 14.1691 +    }
 14.1692 +
 14.1693 +    SetElement(zone, array, index, top.sp[-1]);
 14.1694 +    top.sp[-3] = top.sp[-1];
 14.1695 +    top.sp -= 2;
 14.1696 +    break;
 14.1697 +}
 14.1698 +
 14.1699 +case OP_CVT_I2F:
 14.1700 +{
 14.1701 +    int ival = POP_I32(top);
 14.1702 +    float fval = (float)ival;
 14.1703 +    PUSH_F(top, fval);
 14.1704 +    break;
 14.1705 +}
 14.1706 +
 14.1707 +case OP_CVT_I2B:
 14.1708 +{
 14.1709 +    top.sp[-1].i32 = !!top.sp[-1].i32;
 14.1710 +    break;
 14.1711 +}
 14.1712 +
 14.1713 +case OP_DUPARRAY:
 14.1714 +{
 14.1715 +    Local<Array> src(zone, Array::cast(top.sp[-1].obj));
 14.1716 +    top.sp[-1].obj = Array::DeepCopy(zone, src, Heap::Tenure_Default);
 14.1717 +    if (!top.sp[-1].obj)
 14.1718 +        goto error;
 14.1719 +    break;
 14.1720 +}
 14.1721 +
 14.1722 +case OP_NEWFIXED:
 14.1723 +{
 14.1724 +    Heap::Tenure tenure = (Heap::Tenure)top.pc[1];
 14.1725 +    Local<ArrayMap> map(zone, ArrayMap::cast(top.fp->code()->map(READ_UINT32(top.pc + 1))));
 14.1726 +    Array *array = Array::NewFixed(zone, map, tenure);
 14.1727 +    if (!array)
 14.1728 +        goto error;
 14.1729 +    top.sp->obj = array;
 14.1730 +    top.sp++;
 14.1731 +    break;
 14.1732 +}
 14.1733 +
 14.1734 +case OP_NEWEMPTY:
 14.1735 +{
 14.1736 +    Heap::Tenure tenure = (Heap::Tenure)top.pc[1];
 14.1737 +    Local<ArrayMap> map(zone, ArrayMap::cast(top.fp->code()->map(READ_UINT32(top.pc + 1))));
 14.1738 +    Array *array = Array::NewEmpty(zone, map, tenure);
 14.1739 +    if (!array)
 14.1740 +        goto error;
 14.1741 +    top.sp->obj = array;
 14.1742 +    top.sp++;
 14.1743 +    break;
 14.1744 +}
 14.1745 +
 14.1746 +case OP_NEWSIZED:
 14.1747 +{
 14.1748 +    Heap::Tenure tenure = (Heap::Tenure)top.pc[1];
 14.1749 +    Local<ArrayMap> map(zone, ArrayMap::cast(top.fp->code()->map(READ_UINT32(top.pc + 1))));
 14.1750 +    assert(map->type()->levels() < MAX_ARRAY_DEPTH);
 14.1751 +
 14.1752 +    int dims[MAX_ARRAY_DEPTH];
 14.1753 +    for (unsigned i = map->type()->levels() - 1; i < map->type()->levels(); i--)
 14.1754 +        dims[i] = POP_I32(top);
 14.1755 +
 14.1756 +    Array *array = Array::NewSized(zone, map, dims, tenure);
 14.1757 +    if (!array)
 14.1758 +        goto error;
 14.1759 +    top.sp->obj = array;
 14.1760 +    top.sp++;
 14.1761 +    break;
 14.1762 +}
 14.1763 +
 14.1764 +case OP_NEWSTRUCT:
 14.1765 +{
 14.1766 +    Heap::Tenure tenure = (Heap::Tenure)top.pc[1];
 14.1767 +    Local<StructMap> map(zone, StructMap::cast(top.fp->code()->map(READ_UINT32(top.pc + 1))));
 14.1768 +    top.sp->obj = Struct::New(zone, map, tenure);
 14.1769 +    if (!top.sp->obj)
 14.1770 +        goto error;
 14.1771 +    top.sp++;
 14.1772 +    break;
 14.1773 +}
 14.1774 +
 14.1775 +case OP_SAVELIFO:
 14.1776 +{
 14.1777 +    unsigned slot = READ_UINT32(top.pc);
 14.1778 +    locals[slot].address = zone->heap().lifoPosition();
 14.1779 +    break;
 14.1780 +}
 14.1781 +
 14.1782 +case OP_UNWINDLIFO:
 14.1783 +{
 14.1784 +    unsigned slot = READ_UINT32(top.pc);
 14.1785 +    zone->heap().unwindLifo(locals[slot].address);
 14.1786 +    break;
 14.1787 +}
 14.1788 +
 14.1789 +case OP_VARREF_LIFO:
 14.1790 +{
 14.1791 +    unsigned slot = READ_UINT32(top.pc);
 14.1792 +    if (!PushNewRef(zone, top, &locals[slot], Heap::Tenure_Stack))
 14.1793 +        goto error;
 14.1794 +    break;
 14.1795 +}
 14.1796 +
 14.1797 +case OP_ARGREF_LIFO:
 14.1798 +{
 14.1799 +    unsigned slot = READ_UINT32(top.pc);
 14.1800 +    if (!PushNewRef(zone, top, &top.fp->arg(slot), Heap::Tenure_Stack))
 14.1801 +        goto error;
 14.1802 +    break;
 14.1803 +}
 14.1804 +
 14.1805 +case OP_SLOTREF_LIFO:
 14.1806 +{
 14.1807 +    Reference *ref = Reference::NewStack(zone, top.sp[-1], Heap::Tenure_Stack);
 14.1808 +    if (!ref)
 14.1809 +        goto error;
 14.1810 +    top.sp[-1].ref = ref;
 14.1811 +    break;
 14.1812 +}
 14.1813 +
 14.1814 +case OP_GETREF_I:
 14.1815 +{
 14.1816 +    top.sp[-1].i32 = top.sp[-1].ref->getInt();
 14.1817 +    break;
 14.1818 +}
 14.1819 +
 14.1820 +case OP_SETREF_I:
 14.1821 +{
 14.1822 +    top.sp[-2].ref->setInt(top.sp[-1].i32);
 14.1823 +    top.sp[-2].i32 = top.sp[-1].i32;
 14.1824 +    top.sp--;
 14.1825 +    break;
 14.1826 +}
 14.1827 +
 14.1828 +case OP_GETREF_F:
 14.1829 +{
 14.1830 +    top.sp[-1].f = top.sp[-1].ref->getFloat();
 14.1831 +    break;
 14.1832 +}
 14.1833 +
 14.1834 +case OP_SETREF_F:
 14.1835 +{
 14.1836 +    top.sp[-2].ref->setFloat(top.sp[-1].f);
 14.1837 +    top.sp[-2].f = top.sp[-1].f;
 14.1838 +    break;
 14.1839 +}
 14.1840 +
 14.1841 +case OP_OBJECT:
 14.1842 +{
 14.1843 +    top.sp->obj = top.fp->code()->object(READ_UINT32(top.pc));
 14.1844 +    top.sp++;
 14.1845 +    break;
 14.1846 +}
 14.1847 +
 14.1848 +case OP_COPYARRAY:
 14.1849 +{
 14.1850 +    // Note for this assignment opcode, we return the left-hand side, not the
 14.1851 +    // right, since in this case the result of the expression could be different.
 14.1852 +    Local<Array> left(zone, Array::cast(top.sp[-2].array));
 14.1853 +    Local<Array> right(zone, Array::cast(top.sp[-1].array));
 14.1854 +    if (!Array::ShallowCopy(zone, left, right))
 14.1855 +        goto error;
 14.1856 +    top.sp--;
 14.1857 +    break;
 14.1858 +}
 14.1859 +
 14.1860 +case OP_DUP:
 14.1861 +{
 14.1862 +    top.sp++;
 14.1863 +    top.sp[-1] = top.sp[-2];
 14.1864 +    break;
 14.1865 +}
 14.1866 +
 14.1867 +case OP_DUP2:
 14.1868 +{
 14.1869 +    top.sp += 2;
 14.1870 +    top.sp[-2] = top.sp[-4];
 14.1871 +    top.sp[-1] = top.sp[-3];
 14.1872 +    break;
 14.1873 +}
 14.1874 +
 14.1875 +case OP_SWAP:
 14.1876 +{
 14.1877 +    LocalSlot slot = top.sp[-2];
 14.1878 +    top.sp[-2] = top.sp[-1];
 14.1879 +    top.sp[-1] = slot;
 14.1880 +    break;
 14.1881 +}
 14.1882 +
 14.1883 +case OP_ROLL3:
 14.1884 +{
 14.1885 +    LocalSlot slot = top.sp[-3];
 14.1886 +    top.sp[-3] = top.sp[-2];
 14.1887 +    top.sp[-2] = top.sp[-1];
 14.1888 +    top.sp[-1] = slot;
 14.1889 +    break;
 14.1890 +}
 14.1891 +
 14.1892 +case OP_PICK2:
 14.1893 +{
 14.1894 +    top.sp++;
 14.1895 +    top.sp[-1] = top.sp[-3];
 14.1896 +    break;
 14.1897 +}
 14.1898 +
 14.1899 +case OP_PICK3:
 14.1900 +{
 14.1901 +    top.sp++;
 14.1902 +    top.sp[-1] = top.sp[-4];
 14.1903 +    break;
 14.1904 +}
 14.1905 +
 14.1906 +case OP_CALLNATIVE:
 14.1907 +{
 14.1908 +    unsigned argc = READ_UINT32(top.pc);
 14.1909 +
 14.1910 +    Local<Native> native(zone, Native::cast(top.sp[-1].obj));
 14.1911 +    top.sp--;
 14.1912 +
 14.1913 +    int result;
 14.1914 +    void *nativeIdentity = top.fp->code()->module()->parent()->getNativeIdentity();
 14.1915 +    if (!InvokeNative(zone, native, nativeIdentity, top.sp, argc, &result))
 14.1916 +        goto error;
 14.1917 +
 14.1918 +    top.sp -= argc;
 14.1919 +    PUSH_I32(top, result);
 14.1920 +    break;
 14.1921 +}
 14.1922 +
 14.1923 +case OP_BITCAST:
 14.1924 +{
 14.1925 +    // Because the stack is a union, this is a no-op.
 14.1926 +    break;
 14.1927 +}
 14.1928 +
 14.1929 +case OP_TRUE:
 14.1930 +{
 14.1931 +    top.sp++;
 14.1932 +    top.sp[-1].i32 = 1;
 14.1933 +    break;
 14.1934 +}
 14.1935 +
 14.1936 +case OP_FALSE:
 14.1937 +{
 14.1938 +    top.sp++;
 14.1939 +    top.sp[-1].i32 = 0;
 14.1940 +    break;
 14.1941 +}
 14.1942 +
 14.1943 +case OP_GETFIELD:
 14.1944 +{
 14.1945 +    Struct *obj;
 14.1946 +    if (top.sp[-1].obj->is(MapKind_Module))
 14.1947 +        obj = Module::cast(top.sp[-1].obj)->globals();
 14.1948 +    else
 14.1949 +        obj = Struct::cast(top.sp[-1].obj);
 14.1950 +    GetField(obj, READ_UINT32(top.pc), &top.sp[-1]);
 14.1951 +    break;
 14.1952 +}
 14.1953 +
 14.1954 +case OP_SETFIELD:
 14.1955 +{
 14.1956 +    Struct *obj = Struct::cast(top.sp[-2].obj);
 14.1957 +    SetField(zone, obj, READ_UINT32(top.pc), top.sp[-1]);
 14.1958 +    top.sp[-2] = top.sp[-1];
 14.1959 +    top.sp--;
 14.1960 +    break;
 14.1961 +}
 14.1962 +
 14.1963 +case OP_COPYSTRUCT:
 14.1964 +{
 14.1965 +    Local<Struct> left(zone, Struct::cast(top.sp[-2].obj));
 14.1966 +    Local<Struct> right(zone, Struct::cast(top.sp[-1].obj));
 14.1967 +    if (!Struct::Copy(zone, left, right))
 14.1968 +        goto error;
 14.1969 +    top.sp[-2].obj = top.sp[-1].obj;
 14.1970 +    top.sp--;
 14.1971 +    break;
 14.1972 +}
 14.1973 +
 14.1974 +case OP_TABLESWITCH:
 14.1975 +{
 14.1976 +    int value = top.sp[-1].i32;
 14.1977 +    int low = READ_TABLESWITCH_LOW(top.pc);
 14.1978 +    int high = READ_TABLESWITCH_HIGH(top.pc);
 14.1979 +
 14.1980 +    top.sp--;
 14.1981 +
 14.1982 +    unsigned index = unsigned(value - low);
 14.1983 +    unsigned tablesize = TableSwitchEntries(low, high);
 14.1984 +    if (index < tablesize) {
 14.1985 +        top.pc += OP_TABLESWITCH_LENGTH + OP_JUMP_LENGTH;
 14.1986 +        top.pc += index * OP_JUMP_LENGTH;
 14.1987 +        continue;
 14.1988 +    }
 14.1989 +    break;
 14.1990 +}
 14.1991 +
 14.1992 +case OP_SIZEOF:
 14.1993 +{
 14.1994 +    Array *array = Array::cast(top.sp[-1].obj);
 14.1995 +    top.sp[-1].i32 = array->length();
 14.1996 +    break;
 14.1997 +}
 14.1998 +
 14.1999 +case OP_PUBLIC:
 14.2000 +{
 14.2001 +    Local<Function> fun(zone, Function::cast(top.sp[-1].obj));
 14.2002 +    zone->registerPublic(fun);
 14.2003 +    top.sp--;
 14.2004 +    break;
 14.2005 +}
 14.2006 +
 14.2007 +case OP_SETGLOBAL:
 14.2008 +{
 14.2009 +    Local<Code> code(zone, top.fp->code());
 14.2010 +    Local<Struct> obj(zone, code->module()->globals());
 14.2011 +    Local<String> name(zone, String::cast(code->strings()->at(READ_UINT32(top.pc))));
 14.2012 +    SetGlobal(zone, obj, name, top.sp[-1]);
 14.2013 +    break;
 14.2014 +}
 14.2015 +
 14.2016 +case OP_GETGLOBAL:
 14.2017 +{
 14.2018 +    Local<Code> code(zone, top.fp->code());
 14.2019 +    Local<Struct> obj(zone, code->module()->globals());
 14.2020 +    Local<String> name(zone, String::cast(code->strings()->at(READ_UINT32(top.pc))));
 14.2021 +    GetGlobal(zone, obj, name, top.sp);
 14.2022 +    top.sp++;
 14.2023 +    break;
 14.2024 +}
 14.2025 +
 14.2026 +case OP_ENTERLOOP:
 14.2027 +{
 14.2028 +    top.fp->enterLoop(zone);
 14.2029 +    break;
 14.2030 +}
 14.2031 +
 14.2032 +case OP_LEAVELOOP:
 14.2033 +{
 14.2034 +    top.fp->leaveLoop(zone);
 14.2035 +    break;
 14.2036 +}
 14.2037 +
 14.2038 +case OP_DEPARRAY:
 14.2039 +{
 14.2040 +    Local<ArrayMap> map(zone, ArrayMap::cast(top.fp->code()->object(READ_UINT32(top.pc))));
 14.2041 +    Local<Array> array(zone, Array::cast(top.sp[-2].obj));
 14.2042 +    int index = top.sp[-1].i32;
 14.2043 +
 14.2044 +    // We allow taking 0-length dependent arrays.
 14.2045 +    if (index < 0 || unsigned(index) > array->length()) {
 14.2046 +        zone->reportError(Message_ArrayIndexOutOfBounds, index, array->length());
 14.2047 +        goto error;
 14.2048 +    }
 14.2049 +
 14.2050 +    top.sp[-2].obj = DependentArray::New(zone, array, map, index);
 14.2051 +    if (!top.sp[-2].obj)
 14.2052 +        goto error;
 14.2053 +
 14.2054 +    top.sp--;
 14.2055 +    break;
 14.2056 +}
 14.2057 +
 14.2058 +case OP_IMPORT:
 14.2059 +{
 14.2060 +    unsigned index = READ_UINT32(top.pc);
 14.2061 +
 14.2062 +    top.sp++;
 14.2063 +    top.sp[-1].obj = top.fp->code()->module()->getImportAt(index);
 14.2064 +    break;
 14.2065 +}
 14.2066 +
 14.2067 +default:
 14.2068 +    assert(false);
 14.2069 +    return false;
 14.2070 +
 14.2071 +        }
 14.2072 +
 14.2073 +        top.pc += OpcodeInfo[op].length;
 14.2074 +        assert(top.sp >= top.fp->stackBase());
 14.2075 +    }
 14.2076 +
 14.2077 +done:
 14.2078 +    return true;
 14.2079 +
 14.2080 +error:
 14.2081 +    // Unwind frames until we can continue.
 14.2082 +    while (top.fp != entryFrame)
 14.2083 +        zone->stack().popInlineFrame();
 14.2084 +    return false;
 14.2085 +}
    15.1 --- a/src/Interpreter.h	Mon Jun 10 00:46:29 2013 +0100
    15.2 +++ b/src/Interpreter.h	Mon Jun 10 01:04:43 2013 +0100
    15.3 @@ -1,29 +1,29 @@
    15.4 -/*
    15.5 - * Copyright (C) 2012 David Anderson
    15.6 - *
    15.7 - * This file is part of JITCraft.
    15.8 - *
    15.9 - * JITCraft is free software: you can redistribute it and/or modify it under
   15.10 - * the terms of the GNU General Public License as published by the Free
   15.11 - * Software Foundation, either version 3 of the License, or (at your option)
   15.12 - * any later version.
   15.13 - * 
   15.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
   15.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   15.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   15.17 - *
   15.18 - * You should have received a copy of the GNU General Public License along with
   15.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
   15.20 - */
   15.21 -#ifndef _include_jc_interpreter_h_
   15.22 -#define _include_jc_interpreter_h_
   15.23 -
   15.24 -#include "Stack.h"
   15.25 -
   15.26 -namespace ke {
   15.27 -
   15.28 -bool Interpret(Zone *zone, Frame *frame, LocalSlot *result);
   15.29 -
   15.30 -}
   15.31 -
   15.32 -#endif // _include_jc_interpreter_h_
   15.33 +/*
   15.34 + * Copyright (C) 2012 David Anderson
   15.35 + *
   15.36 + * This file is part of JITCraft.
   15.37 + *
   15.38 + * JITCraft is free software: you can redistribute it and/or modify it under
   15.39 + * the terms of the GNU General Public License as published by the Free
   15.40 + * Software Foundation, either version 3 of the License, or (at your option)
   15.41 + * any later version.
   15.42 + * 
   15.43 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
   15.44 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   15.45 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   15.46 + *
   15.47 + * You should have received a copy of the GNU General Public License along with
   15.48 + * JITCraft. If not, see http://www.gnu.org/licenses/.
   15.49 + */
   15.50 +#ifndef _include_jc_interpreter_h_
   15.51 +#define _include_jc_interpreter_h_
   15.52 +
   15.53 +#include "Stack.h"
   15.54 +
   15.55 +namespace ke {
   15.56 +
   15.57 +bool Interpret(Zone *zone, Frame *frame, LocalSlot *result);
   15.58 +
   15.59 +}
   15.60 +
   15.61 +#endif // _include_jc_interpreter_h_
    16.1 --- a/src/Messages.h	Mon Jun 10 00:46:29 2013 +0100
    16.2 +++ b/src/Messages.h	Mon Jun 10 01:04:43 2013 +0100
    16.3 @@ -1,48 +1,48 @@
    16.4 -/*
    16.5 - * Copyright (C) 2012 David Anderson
    16.6 - *
    16.7 - * This file is part of JITCraft.
    16.8 - *
    16.9 - * JITCraft is free software: you can redistribute it and/or modify it under
   16.10 - * the terms of the GNU General Public License as published by the Free
   16.11 - * Software Foundation, either version 3 of the License, or (at your option)
   16.12 - * any later version.
   16.13 - * 
   16.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
   16.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   16.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   16.17 - *
   16.18 - * You should have received a copy of the GNU General Public License along with
   16.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
   16.20 - */
   16.21 -#ifndef _include_jitcraft_messages_h_
   16.22 -#define _include_jitcraft_messages_h_
   16.23 -
   16.24 -namespace ke {
   16.25 -
   16.26 -enum MessageType
   16.27 -{
   16.28 -    MessageType_SyntaxError,
   16.29 -    MessageType_TypeError,
   16.30 -    MessageType_SystemError
   16.31 -};
   16.32 -
   16.33 -enum Message
   16.34 -{
   16.35 -#define MSG(Name, Type, String)     Message_##Name,
   16.36 -# include "Messages.tbl"
   16.37 -#undef MSG
   16.38 -    MessageType_Total
   16.39 -};
   16.40 -
   16.41 -struct MessageInfo
   16.42 -{
   16.43 -    MessageType type;
   16.44 -    const char *format;
   16.45 -};
   16.46 -
   16.47 -extern const MessageInfo Messages[];
   16.48 -
   16.49 -}
   16.50 -
   16.51 -#endif // _include_jitcraft_messages_h_
   16.52 +/*
   16.53 + * Copyright (C) 2012 David Anderson
   16.54 + *
   16.55 + * This file is part of JITCraft.
   16.56 + *
   16.57 + * JITCraft is free software: you can redistribute it and/or modify it under
   16.58 + * the terms of the GNU General Public License as published by the Free
   16.59 + * Software Foundation, either version 3 of the License, or (at your option)
   16.60 + * any later version.
   16.61 + * 
   16.62 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
   16.63 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   16.64 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   16.65 + *
   16.66 + * You should have received a copy of the GNU General Public License along with
   16.67 + * JITCraft. If not, see http://www.gnu.org/licenses/.
   16.68 + */
   16.69 +#ifndef _include_jitcraft_messages_h_
   16.70 +#define _include_jitcraft_messages_h_
   16.71 +
   16.72 +namespace ke {
   16.73 +
   16.74 +enum MessageType
   16.75 +{
   16.76 +    MessageType_SyntaxError,
   16.77 +    MessageType_TypeError,
   16.78 +    MessageType_SystemError
   16.79 +};
   16.80 +
   16.81 +enum Message
   16.82 +{
   16.83 +#define MSG(Name, Type, String)     Message_##Name,
   16.84 +# include "Messages.tbl"
   16.85 +#undef MSG
   16.86 +    MessageType_Total
   16.87 +};
   16.88 +
   16.89 +struct MessageInfo
   16.90 +{
   16.91 +    MessageType type;
   16.92 +    const char *format;
   16.93 +};
   16.94 +
   16.95 +extern const MessageInfo Messages[];
   16.96 +
   16.97 +}
   16.98 +
   16.99 +#endif // _include_jitcraft_messages_h_
    17.1 --- a/src/Modules.cpp	Mon Jun 10 00:46:29 2013 +0100
    17.2 +++ b/src/Modules.cpp	Mon Jun 10 01:04:43 2013 +0100
    17.3 @@ -1,40 +1,40 @@
    17.4 -/*
    17.5 - * Copyright (C) 2012 David Anderson
    17.6 - *
    17.7 - * This file is part of JITCraft.
    17.8 - *
    17.9 - * JITCraft is free software: you can redistribute it and/or modify it under
   17.10 - * the terms of the GNU General Public License as published by the Free
   17.11 - * Software Foundation, either version 3 of the License, or (at your option)
   17.12 - * any later version.
   17.13 - * 
   17.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
   17.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   17.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   17.17 - *
   17.18 - * You should have received a copy of the GNU General Public License along with
   17.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
   17.20 - */
   17.21 -#include "Modules.h"
   17.22 -#include "Zone.h"
   17.23 -#include "Heap.h"
   17.24 -#include "Heap-inl.h"
   17.25 -
   17.26 -using namespace ke;
   17.27 -
   17.28 -Module *
   17.29 -Module::New(Zone *zone, Handle<Package> package, Handle<String> path, Handle<String> name)
   17.30 -{
   17.31 -    Local<Module> module(zone, Module::cast(zone->allocate(MapKind_Module, sizeof(Module), Heap::Tenure_Old)));
   17.32 -    if (!module)
   17.33 -        return NULL;
   17.34 -
   17.35 -    module->parent_ = package;
   17.36 -    module->path_ = path;
   17.37 -    module->name_ = name;
   17.38 -    module->globals_ = NULL;
   17.39 -    module->nativeIdentity_ = NULL;
   17.40 -    module->globals_ = NULL;
   17.41 -    module->unit_ = NULL;
   17.42 -    return module;
   17.43 -}
   17.44 +/*
   17.45 + * Copyright (C) 2012 David Anderson
   17.46 + *
   17.47 + * This file is part of JITCraft.
   17.48 + *
   17.49 + * JITCraft is free software: you can redistribute it and/or modify it under
   17.50 + * the terms of the GNU General Public License as published by the Free
   17.51 + * Software Foundation, either version 3 of the License, or (at your option)
   17.52 + * any later version.
   17.53 + * 
   17.54 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
   17.55 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   17.56 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   17.57 + *
   17.58 + * You should have received a copy of the GNU General Public License along with
   17.59 + * JITCraft. If not, see http://www.gnu.org/licenses/.
   17.60 + */
   17.61 +#include "Modules.h"
   17.62 +#include "Zone.h"
   17.63 +#include "Heap.h"
   17.64 +#include "Heap-inl.h"
   17.65 +
   17.66 +using namespace ke;
   17.67 +
   17.68 +Module *
   17.69 +Module::New(Zone *zone, Handle<Package> package, Handle<String> path, Handle<String> name)
   17.70 +{
   17.71 +    Local<Module> module(zone, Module::cast(zone->allocate(MapKind_Module, sizeof(Module), Heap::Tenure_Old)));
   17.72 +    if (!module)
   17.73 +        return NULL;
   17.74 +
   17.75 +    module->parent_ = package;
   17.76 +    module->path_ = path;
   17.77 +    module->name_ = name;
   17.78 +    module->globals_ = NULL;
   17.79 +    module->nativeIdentity_ = NULL;
   17.80 +    module->globals_ = NULL;
   17.81 +    module->unit_ = NULL;
   17.82 +    return module;
   17.83 +}
    18.1 --- a/src/Modules.h	Mon Jun 10 00:46:29 2013 +0100
    18.2 +++ b/src/Modules.h	Mon Jun 10 01:04:43 2013 +0100
    18.3 @@ -1,107 +1,107 @@
    18.4 -/*
    18.5 - * Copyright (C) 2012 David Anderson
    18.6 - *
    18.7 - * This file is part of SourcePawn.
    18.8 - *
    18.9 - * SourcePawn is free software: you can redistribute it and/or modify it under
   18.10 - * the terms of the GNU General Public License as published by the Free
   18.11 - * Software Foundation, either version 3 of the License, or (at your option)
   18.12 - * any later version.
   18.13 - * 
   18.14 - * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
   18.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   18.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   18.17 - *
   18.18 - * You should have received a copy of the GNU General Public License along with
   18.19 - * SourcePawn. If not, see http://www.gnu.org/licenses/.
   18.20 - */
   18.21 -#ifndef _include_jc_module_h_
   18.22 -#define _include_jc_module_h_
   18.23 -
   18.24 -#include "Heap.h"
   18.25 -#include "Code.h"
   18.26 -#include "Functions.h"
   18.27 -#include "FixedArray.h"
   18.28 -#include "Packages.h"
   18.29 -
   18.30 -namespace ke {
   18.31 -
   18.32 -class Environment;
   18.33 -class Struct;
   18.34 -class Package;
   18.35 -struct TranslationUnit;
   18.36 -
   18.37 -class Module : public Importable
   18.38 -{
   18.39 -    Barriered<Code> code_;
   18.40 -    Barriered<Struct> globals_;
   18.41 -    void *nativeIdentity_;
   18.42 -    TranslationUnit *unit_;
   18.43 -    Barriered<FixedArray> imports_;
   18.44 -
   18.45 -  public:
   18.46 -    static Module *New(Zone *zone, Handle<Package> package, Handle<String> path, Handle<String> name);
   18.47 -    
   18.48 -    Code *code() {
   18.49 -        return code_;
   18.50 -    }
   18.51 -    Struct *globals() {
   18.52 -        return globals_;
   18.53 -    }
   18.54 -
   18.55 -    bool compiled() {
   18.56 -        return !!code_;
   18.57 -    }
   18.58 -
   18.59 -    // Modules are pre-created, and may have their intermediate compilation
   18.60 -    // data attached while they are being compiled.
   18.61 -    bool compiling() {
   18.62 -        return !!unit_;
   18.63 -    }
   18.64 -    TranslationUnit *translationUnit() {
   18.65 -        return unit_;
   18.66 -    }
   18.67 -    void setTranslationUnit(TranslationUnit *unit) {
   18.68 -        unit_ = unit;
   18.69 -    }
   18.70 -
   18.71 -    unsigned imports() {
   18.72 -        return imports_ ? imports_->length() / 2 : 0;
   18.73 -    }
   18.74 -    Importable *getImportAt(unsigned index) {
   18.75 -        return Importable::cast(imports_->at(index * 2));
   18.76 -    }
   18.77 -    FixedArray *importPathAt(unsigned index) {
   18.78 -        return FixedArray::cast(imports_->at(index * 2 + 1));
   18.79 -    }
   18.80 -    void setImports(Handle<FixedArray> imports) {
   18.81 -        imports_ = imports;
   18.82 -    }
   18.83 -    void setCode(Handle<Code> code) {
   18.84 -        code_ = code;
   18.85 -    }
   18.86 -    void setGlobals(Handle<Struct> globals) {
   18.87 -        globals_ = globals;
   18.88 -    }
   18.89 -
   18.90 -    // Begin GC Descriptor.
   18.91 -    static inline size_t offsetOfCode() {
   18.92 -        return OFFSETOF(Module, code_);
   18.93 -    }
   18.94 -    static inline size_t offsetOfGlobals() {
   18.95 -        return OFFSETOF(Module, globals_);
   18.96 -    }
   18.97 -    static inline size_t offsetOfImports() {
   18.98 -        return OFFSETOF(Module, imports_);
   18.99 -    }
  18.100 -    // End GC Descriptor.
  18.101 -
  18.102 -    static inline Module *cast(Object *obj) {
  18.103 -        assert(!obj || obj->is(MapKind_Module));
  18.104 -        return reinterpret_cast<Module *>(obj);
  18.105 -    }
  18.106 -};
  18.107 -
  18.108 -}
  18.109 -
  18.110 -#endif // _include_jc_module_h_
  18.111 +/*
  18.112 + * Copyright (C) 2012 David Anderson
  18.113 + *
  18.114 + * This file is part of SourcePawn.
  18.115 + *
  18.116 + * SourcePawn is free software: you can redistribute it and/or modify it under
  18.117 + * the terms of the GNU General Public License as published by the Free
  18.118 + * Software Foundation, either version 3 of the License, or (at your option)
  18.119 + * any later version.
  18.120 + * 
  18.121 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
  18.122 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  18.123 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  18.124 + *
  18.125 + * You should have received a copy of the GNU General Public License along with
  18.126 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
  18.127 + */
  18.128 +#ifndef _include_jc_module_h_
  18.129 +#define _include_jc_module_h_
  18.130 +
  18.131 +#include "Heap.h"
  18.132 +#include "Code.h"
  18.133 +#include "Functions.h"
  18.134 +#include "FixedArray.h"
  18.135 +#include "Packages.h"
  18.136 +
  18.137 +namespace ke {
  18.138 +
  18.139 +class Environment;
  18.140 +class Struct;
  18.141 +class Package;
  18.142 +struct TranslationUnit;
  18.143 +
  18.144 +class Module : public Importable
  18.145 +{
  18.146 +    Barriered<Code> code_;
  18.147 +    Barriered<Struct> globals_;
  18.148 +    void *nativeIdentity_;
  18.149 +    TranslationUnit *unit_;
  18.150 +    Barriered<FixedArray> imports_;
  18.151 +
  18.152 +  public:
  18.153 +    static Module *New(Zone *zone, Handle<Package> package, Handle<String> path, Handle<String> name);
  18.154 +    
  18.155 +    Code *code() {
  18.156 +        return code_;
  18.157 +    }
  18.158 +    Struct *globals() {
  18.159 +        return globals_;
  18.160 +    }
  18.161 +
  18.162 +    bool compiled() {
  18.163 +        return !!code_;
  18.164 +    }
  18.165 +
  18.166 +    // Modules are pre-created, and may have their intermediate compilation
  18.167 +    // data attached while they are being compiled.
  18.168 +    bool compiling() {
  18.169 +        return !!unit_;
  18.170 +    }
  18.171 +    TranslationUnit *translationUnit() {
  18.172 +        return unit_;
  18.173 +    }
  18.174 +    void setTranslationUnit(TranslationUnit *unit) {
  18.175 +        unit_ = unit;
  18.176 +    }
  18.177 +
  18.178 +    unsigned imports() {
  18.179 +        return imports_ ? imports_->length() / 2 : 0;
  18.180 +    }
  18.181 +    Importable *getImportAt(unsigned index) {
  18.182 +        return Importable::cast(imports_->at(index * 2));
  18.183 +    }
  18.184 +    FixedArray *importPathAt(unsigned index) {
  18.185 +        return FixedArray::cast(imports_->at(index * 2 + 1));
  18.186 +    }
  18.187 +    void setImports(Handle<FixedArray> imports) {
  18.188 +        imports_ = imports;
  18.189 +    }
  18.190 +    void setCode(Handle<Code> code) {
  18.191 +        code_ = code;
  18.192 +    }
  18.193 +    void setGlobals(Handle<Struct> globals) {
  18.194 +        globals_ = globals;
  18.195 +    }
  18.196 +
  18.197 +    // Begin GC Descriptor.
  18.198 +    static inline size_t offsetOfCode() {
  18.199 +        return OFFSETOF(Module, code_);
  18.200 +    }
  18.201 +    static inline size_t offsetOfGlobals() {
  18.202 +        return OFFSETOF(Module, globals_);
  18.203 +    }
  18.204 +    static inline size_t offsetOfImports() {
  18.205 +        return OFFSETOF(Module, imports_);
  18.206 +    }
  18.207 +    // End GC Descriptor.
  18.208 +
  18.209 +    static inline Module *cast(Object *obj) {
  18.210 +        assert(!obj || obj->is(MapKind_Module));
  18.211 +        return reinterpret_cast<Module *>(obj);
  18.212 +    }
  18.213 +};
  18.214 +
  18.215 +}
  18.216 +
  18.217 +#endif // _include_jc_module_h_
    19.1 --- a/src/NativeTable.cpp	Mon Jun 10 00:46:29 2013 +0100
    19.2 +++ b/src/NativeTable.cpp	Mon Jun 10 01:04:43 2013 +0100
    19.3 @@ -1,97 +1,97 @@
    19.4 -/* vim: set ts=4 sw=4 tw=99 et:
    19.5 - *
    19.6 - * Copyright (C) 2012 David Anderson
    19.7 - *
    19.8 - * This file is part of SourcePawn.
    19.9 - *
   19.10 - * SourcePawn is free software: you can redistribute it and/or modify it under
   19.11 - * the terms of the GNU General Public License as published by the Free
   19.12 - * Software Foundation, either version 3 of the License, or (at your option)
   19.13 - * any later version.
   19.14 - * 
   19.15 - * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
   19.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   19.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   19.18 - *
   19.19 - * You should have received a copy of the GNU General Public License along with
   19.20 - * SourcePawn. If not, see http://www.gnu.org/licenses/.
   19.21 - */
   19.22 -#include "Zone.h"
   19.23 -#include "NativeTable.h"
   19.24 -#include "StringPool.h"
   19.25 -#include "Heap-inl.h"
   19.26 -
   19.27 -using namespace ke;
   19.28 -
   19.29 -NativeTable::NativeTable(Zone *zone)
   19.30 -  : zone_(zone),
   19.31 -    nativeMap_(ZoneAllocatorPolicy())
   19.32 -{
   19.33 -}
   19.34 -
   19.35 -NativeTable::~NativeTable()
   19.36 -{
   19.37 -    for (size_t i = 0; i < natives_.length(); i++)
   19.38 -        delete natives_[i];
   19.39 -}
   19.40 -
   19.41 -bool
   19.42 -NativeTable::initialize()
   19.43 -{
   19.44 -    return nativeMap_.init(16);
   19.45 -}
   19.46 -
   19.47 -bool
   19.48 -NativeTable::add(Handle<String> name, size_t *indexp)
   19.49 -{
   19.50 -    // :TODO: assert no GC
   19.51 -    CharsAndLength key(name->chars(), name->length());
   19.52 -    NativeMap::Insert p = nativeMap_.findForAdd(key);
   19.53 -    if (p.found()) {
   19.54 -        *indexp = (*p)->index;
   19.55 -        return true;
   19.56 -    }
   19.57 -
   19.58 -    NativeInfo *info = new NativeInfo(name, NULL, natives_.length());
   19.59 -    if (!info || !natives_.append(info))
   19.60 -        return false;
   19.61 -
   19.62 -    if (!nativeMap_.add(p, info))
   19.63 -        return false;
   19.64 -
   19.65 -    *indexp = info->index;
   19.66 -
   19.67 -    return true;
   19.68 -}
   19.69 -
   19.70 -bool
   19.71 -NativeTable::bind(const char *name, void *address)
   19.72 -{
   19.73 -    CharsAndLength key(name, strlen(name));
   19.74 -    NativeMap::Insert p = nativeMap_.findForAdd(key);
   19.75 -    if (p.found()) {
   19.76 -        (*p)->address = address;
   19.77 -        return true;
   19.78 -    }
   19.79 -
   19.80 -    Local<String> str(zone_, zone_->symbols()->add(key.str(), key.length()));
   19.81 -    if (!str)
   19.82 -        return false;
   19.83 -
   19.84 -    // :TODO: assert no GC
   19.85 -    NativeInfo *info = new NativeInfo(str, address, natives_.length());
   19.86 -    if (!info || !natives_.append(info))
   19.87 -        return false;
   19.88 -
   19.89 -    if (!nativeMap_.add(p, info))
   19.90 -        return false;
   19.91 -
   19.92 -    return true;
   19.93 -}
   19.94 -
   19.95 -void
   19.96 -NativeTable::accept(VirtualObjectVisitor *visitor)
   19.97 -{
   19.98 -    for (size_t i = 0; i < natives_.length(); i++)
   19.99 -        visitor->visit(natives_[i]->name.address());
  19.100 -}
  19.101 +/* vim: set ts=4 sw=4 tw=99 et:
  19.102 + *
  19.103 + * Copyright (C) 2012 David Anderson
  19.104 + *
  19.105 + * This file is part of SourcePawn.
  19.106 + *
  19.107 + * SourcePawn is free software: you can redistribute it and/or modify it under
  19.108 + * the terms of the GNU General Public License as published by the Free
  19.109 + * Software Foundation, either version 3 of the License, or (at your option)
  19.110 + * any later version.
  19.111 + * 
  19.112 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
  19.113 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  19.114 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  19.115 + *
  19.116 + * You should have received a copy of the GNU General Public License along with
  19.117 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
  19.118 + */
  19.119 +#include "Zone.h"
  19.120 +#include "NativeTable.h"
  19.121 +#include "StringPool.h"
  19.122 +#include "Heap-inl.h"
  19.123 +
  19.124 +using namespace ke;
  19.125 +
  19.126 +NativeTable::NativeTable(Zone *zone)
  19.127 +  : zone_(zone),
  19.128 +    nativeMap_(ZoneAllocatorPolicy())
  19.129 +{
  19.130 +}
  19.131 +
  19.132 +NativeTable::~NativeTable()
  19.133 +{
  19.134 +    for (size_t i = 0; i < natives_.length(); i++)
  19.135 +        delete natives_[i];
  19.136 +}
  19.137 +
  19.138 +bool
  19.139 +NativeTable::initialize()
  19.140 +{
  19.141 +    return nativeMap_.init(16);
  19.142 +}
  19.143 +
  19.144 +bool
  19.145 +NativeTable::add(Handle<String> name, size_t *indexp)
  19.146 +{
  19.147 +    // :TODO: assert no GC
  19.148 +    CharsAndLength key(name->chars(), name->length());
  19.149 +    NativeMap::Insert p = nativeMap_.findForAdd(key);
  19.150 +    if (p.found()) {
  19.151 +        *indexp = (*p)->index;
  19.152 +        return true;
  19.153 +    }
  19.154 +
  19.155 +    NativeInfo *info = new NativeInfo(name, NULL, natives_.length());
  19.156 +    if (!info || !natives_.append(info))
  19.157 +        return false;
  19.158 +
  19.159 +    if (!nativeMap_.add(p, info))
  19.160 +        return false;
  19.161 +
  19.162 +    *indexp = info->index;
  19.163 +
  19.164 +    return true;
  19.165 +}
  19.166 +
  19.167 +bool
  19.168 +NativeTable::bind(const char *name, void *address)
  19.169 +{
  19.170 +    CharsAndLength key(name, strlen(name));
  19.171 +    NativeMap::Insert p = nativeMap_.findForAdd(key);
  19.172 +    if (p.found()) {
  19.173 +        (*p)->address = address;
  19.174 +        return true;
  19.175 +    }
  19.176 +
  19.177 +    Local<String> str(zone_, zone_->symbols()->add(key.str(), key.length()));
  19.178 +    if (!str)
  19.179 +        return false;
  19.180 +
  19.181 +    // :TODO: assert no GC
  19.182 +    NativeInfo *info = new NativeInfo(str, address, natives_.length());
  19.183 +    if (!info || !natives_.append(info))
  19.184 +        return false;
  19.185 +
  19.186 +    if (!nativeMap_.add(p, info))
  19.187 +        return false;
  19.188 +
  19.189 +    return true;
  19.190 +}
  19.191 +
  19.192 +void
  19.193 +NativeTable::accept(VirtualObjectVisitor *visitor)
  19.194 +{
  19.195 +    for (size_t i = 0; i < natives_.length(); i++)
  19.196 +        visitor->visit(natives_[i]->name.address());
  19.197 +}
    20.1 --- a/src/NativeTable.h	Mon Jun 10 00:46:29 2013 +0100
    20.2 +++ b/src/NativeTable.h	Mon Jun 10 01:04:43 2013 +0100
    20.3 @@ -1,90 +1,90 @@
    20.4 -/* vim: set ts=4 sw=4 tw=99 et:
    20.5 - *
    20.6 - * Copyright (C) 2012 David Anderson
    20.7 - *
    20.8 - * This file is part of SourcePawn.
    20.9 - *
   20.10 - * SourcePawn is free software: you can redistribute it and/or modify it under
   20.11 - * the terms of the GNU General Public License as published by the Free
   20.12 - * Software Foundation, either version 3 of the License, or (at your option)
   20.13 - * any later version.
   20.14 - * 
   20.15 - * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
   20.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   20.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   20.18 - *
   20.19 - * You should have received a copy of the GNU General Public License along with
   20.20 - * SourcePawn. If not, see http://www.gnu.org/licenses/.
   20.21 - */
   20.22 -#ifndef _include_sp2_native_table_h_
   20.23 -#define _include_sp2_native_table_h_
   20.24 -
   20.25 -#include <string.h>
   20.26 -#include "AllocatorPolicies.h"
   20.27 -#include "Strings.h"
   20.28 -#include "HashTable.h"
   20.29 -#include "Vector.h"
   20.30 -#include "VirtualObjectVisitor.h"
   20.31 -
   20.32 -namespace ke {
   20.33 -
   20.34 -class NativeTable
   20.35 -{
   20.36 -  public:
   20.37 -    NativeTable(Zone *zone);
   20.38 -    ~NativeTable();
   20.39 -
   20.40 -  private:
   20.41 -    struct NativeInfo {
   20.42 -        Unbarriered<String> name;
   20.43 -        void *address;
   20.44 -        size_t index;
   20.45 -
   20.46 -        NativeInfo(String *name, void *address, size_t index)
   20.47 -          : address(address),
   20.48 -            index(index)
   20.49 -        {
   20.50 -            this->name = name;
   20.51 -        }
   20.52 -    };
   20.53 -
   20.54 -    struct Policy
   20.55 -    {
   20.56 -        typedef NativeInfo * Payload;
   20.57 -
   20.58 -        static uint32 hash(const CharsAndLength &key) {
   20.59 -            return HashCharSequence(key.str(), key.length());
   20.60 -        }
   20.61 -        
   20.62 -        static bool matches(const CharsAndLength &key, NativeInfo *info) {
   20.63 -            if (info->name->length() != key.length())
   20.64 -                return false;
   20.65 -            return memcmp(info->name->chars(), key.str(), key.length() * sizeof(char)) == 0;
   20.66 -        }
   20.67 -    };
   20.68 -
   20.69 -    typedef HashTable<Policy, ZoneAllocatorPolicy> NativeMap;
   20.70 -
   20.71 -  public:
   20.72 -    bool initialize();
   20.73 -
   20.74 -    bool bind(const char *name, void *address);
   20.75 -    bool add(Handle<String> name, size_t *indexp);
   20.76 -    String *name(size_t index) const {
   20.77 -        return natives_[index]->name;
   20.78 -    }
   20.79 -    void *address(size_t index) const {
   20.80 -        return natives_[index]->address;
   20.81 -    }
   20.82 -
   20.83 -    void accept(VirtualObjectVisitor *visitor);
   20.84 -
   20.85 -  private:
   20.86 -    Zone *zone_;
   20.87 -    NativeMap nativeMap_;
   20.88 -    Vector<NativeInfo *> natives_;
   20.89 -};
   20.90 -
   20.91 -}
   20.92 -
   20.93 -#endif // _include_sp2_native_table_h_
   20.94 +/* vim: set ts=4 sw=4 tw=99 et:
   20.95 + *
   20.96 + * Copyright (C) 2012 David Anderson
   20.97 + *
   20.98 + * This file is part of SourcePawn.
   20.99 + *
  20.100 + * SourcePawn is free software: you can redistribute it and/or modify it under
  20.101 + * the terms of the GNU General Public License as published by the Free
  20.102 + * Software Foundation, either version 3 of the License, or (at your option)
  20.103 + * any later version.
  20.104 + * 
  20.105 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
  20.106 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  20.107 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  20.108 + *
  20.109 + * You should have received a copy of the GNU General Public License along with
  20.110 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
  20.111 + */
  20.112 +#ifndef _include_sp2_native_table_h_
  20.113 +#define _include_sp2_native_table_h_
  20.114 +
  20.115 +#include <string.h>
  20.116 +#include "AllocatorPolicies.h"
  20.117 +#include "Strings.h"
  20.118 +#include "HashTable.h"
  20.119 +#include "Vector.h"
  20.120 +#include "VirtualObjectVisitor.h"
  20.121 +
  20.122 +namespace ke {
  20.123 +
  20.124 +class NativeTable
  20.125 +{
  20.126 +  public:
  20.127 +    NativeTable(Zone *zone);
  20.128 +    ~NativeTable();
  20.129 +
  20.130 +  private:
  20.131 +    struct NativeInfo {
  20.132 +        Unbarriered<String> name;
  20.133 +        void *address;
  20.134 +        size_t index;
  20.135 +
  20.136 +        NativeInfo(String *name, void *address, size_t index)
  20.137 +          : address(address),
  20.138 +            index(index)
  20.139 +        {
  20.140 +            this->name = name;
  20.141 +        }
  20.142 +    };
  20.143 +
  20.144 +    struct Policy
  20.145 +    {
  20.146 +        typedef NativeInfo * Payload;
  20.147 +
  20.148 +        static uint32 hash(const CharsAndLength &key) {
  20.149 +            return HashCharSequence(key.str(), key.length());
  20.150 +        }
  20.151 +        
  20.152 +        static bool matches(const CharsAndLength &key, NativeInfo *info) {
  20.153 +            if (info->name->length() != key.length())
  20.154 +                return false;
  20.155 +            return memcmp(info->name->chars(), key.str(), key.length() * sizeof(char)) == 0;
  20.156 +        }
  20.157 +    };
  20.158 +
  20.159 +    typedef HashTable<Policy, ZoneAllocatorPolicy> NativeMap;
  20.160 +
  20.161 +  public:
  20.162 +    bool initialize();
  20.163 +
  20.164 +    bool bind(const char *name, void *address);
  20.165 +    bool add(Handle<String> name, size_t *indexp);
  20.166 +    String *name(size_t index) const {
  20.167 +        return natives_[index]->name;
  20.168 +    }
  20.169 +    void *address(size_t index) const {
  20.170 +        return natives_[index]->address;
  20.171 +    }
  20.172 +
  20.173 +    void accept(VirtualObjectVisitor *visitor);
  20.174 +
  20.175 +  private:
  20.176 +    Zone *zone_;
  20.177 +    NativeMap nativeMap_;
  20.178 +    Vector<NativeInfo *> natives_;
  20.179 +};
  20.180 +
  20.181 +}
  20.182 +
  20.183 +#endif // _include_sp2_native_table_h_
    21.1 --- a/src/OldByCo.cpp	Mon Jun 10 00:46:29 2013 +0100
    21.2 +++ b/src/OldByCo.cpp	Mon Jun 10 01:04:43 2013 +0100
    21.3 @@ -1,1585 +1,1585 @@
    21.4 -/* vim: set ts=4 sw=4 tw=99 et:
    21.5 - *
    21.6 - * Copyright (C) 2012 David Anderson
    21.7 - *
    21.8 - * This file is part of JITCraft.
    21.9 - *
   21.10 - * JITCraft is free software: you can redistribute it and/or modify it under
   21.11 - * the terms of the GNU General Public License as published by the Free
   21.12 - * Software Foundation, either version 3 of the License, or (at your option)
   21.13 - * any later version.
   21.14 - * 
   21.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
   21.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   21.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   21.18 - *
   21.19 - * You should have received a copy of the GNU General Public License along with
   21.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
   21.21 - */
   21.22 -#include <string.h>
   21.23 -#include "../Modules.h"
   21.24 -#include "../Types.h"
   21.25 -#include "../Array.h"
   21.26 -#include "../Strings.h"
   21.27 -#include "../Zone.h"
   21.28 -#include "../Environments.h"
   21.29 -#include "../Box.h"
   21.30 -#include "../Heap-inl.h"
   21.31 -#include "BytecodeCompiler.h"
   21.32 -#include "Scopes.h"
   21.33 -
   21.34 -using namespace ke;
   21.35 -
   21.36 -typedef BytecodeEmitter::Label Label;
   21.37 -
   21.38 -#define __ emitter_.
   21.39 -
   21.40 -BytecodeCompiler::BytecodeCompiler(Zone *zone, ParseTree *tree, ModuleData *module)
   21.41 -  : zone_(zone),
   21.42 -    tree_(tree),
   21.43 -    emitter_(zone->pool()),
   21.44 -    locals_(NULL),
   21.45 -    scope_(NULL),
   21.46 -    moduleData_(module),
   21.47 -    loop_(NULL)
   21.48 -{
   21.49 -}
   21.50 -
   21.51 -static inline TokenKind
   21.52 -ToCompare(Expression *expr)
   21.53 -{
   21.54 -    if (expr->isBinaryExpression()) {
   21.55 -        BinaryExpression *b = expr->toBinaryExpression();
   21.56 -        if (b->token() >= TOK_EQUALS && b->token() <= TOK_OR)
   21.57 -            return b->token();
   21.58 -    } else if (expr->isUnaryExpression()) {
   21.59 -        UnaryExpression *u = expr->toUnaryExpression();
   21.60 -        if (u->token() == TOK_NOT)
   21.61 -            return TOK_NOT;
   21.62 -    }
   21.63 -    return TOK_EOF;
   21.64 -}
   21.65 -
   21.66 -static inline Opcode
   21.67 -CompareTokenToJump(TokenKind kind)
   21.68 -{
   21.69 -    switch (kind) {
   21.70 -      case TOK_EQUALS:
   21.71 -        return OP_JEQ;
   21.72 -      case TOK_NOTEQUALS:
   21.73 -        return OP_JNE;
   21.74 -      case TOK_GT:
   21.75 -        return OP_JG;
   21.76 -      case TOK_GE:
   21.77 -        return OP_JGE;
   21.78 -      case TOK_LT:
   21.79 -        return OP_JL;
   21.80 -      default:
   21.81 -        assert(kind == TOK_LE);
   21.82 -        return OP_JLE;
   21.83 -    }
   21.84 -}
   21.85 -
   21.86 -static inline Opcode
   21.87 -TokenToOpcode(TokenKind kind)
   21.88 -{
   21.89 -    switch (kind) {
   21.90 -      case TOK_PLUS:
   21.91 -        return OP_ADD;
   21.92 -      case TOK_MINUS:
   21.93 -        return OP_SUB;
   21.94 -      case TOK_STAR:
   21.95 -        return OP_MUL;
   21.96 -      case TOK_SLASH:
   21.97 -        return OP_DIV;
   21.98 -      case TOK_PERCENT:
   21.99 -        return OP_MOD;
  21.100 -      case TOK_SHR:
  21.101 -        return OP_SHR;
  21.102 -      case TOK_USHR:
  21.103 -        return OP_USHR;
  21.104 -      case TOK_SHL:
  21.105 -        return OP_SHL;
  21.106 -      case TOK_BITAND:
  21.107 -        return OP_BITAND;
  21.108 -      case TOK_BITOR:
  21.109 -        return OP_BITOR;
  21.110 -      case TOK_GT:
  21.111 -          return OP_GT;
  21.112 -      case TOK_GE:
  21.113 -          return OP_GE;
  21.114 -      case TOK_LT:
  21.115 -          return OP_LT;
  21.116 -      case TOK_LE:
  21.117 -          return OP_LE;
  21.118 -      case TOK_EQUALS:
  21.119 -          return OP_EQ;
  21.120 -      case TOK_NOTEQUALS:
  21.121 -          return OP_NE;
  21.122 -      default:
  21.123 -        assert(kind == TOK_BITXOR);
  21.124 -        return OP_BITXOR;
  21.125 -    }
  21.126 -}
  21.127 -
  21.128 -void
  21.129 -BytecodeCompiler::recordLifoSlot(Scope *scope)
  21.130 -{
  21.131 -    if (!scope)
  21.132 -        return;
  21.133 -
  21.134 -    if (Variable *var = scope->lifoSlot()) {
  21.135 -        locals_->set(zone_, var->slot(), var->type());
  21.136 -        __ savelifo(var->slot());
  21.137 -    }
  21.138 -}
  21.139 -
  21.140 -void
  21.141 -BytecodeCompiler::unwindTo(Scope *scope)
  21.142 -{
  21.143 -    // Note: we only need to unwind to the outermost scope's LIFO slot.
  21.144 -    Variable *var = NULL;
  21.145 -    for (Scope *current = scope_; current != scope; current = current->enclosing()) {
  21.146 -        if (Variable *slot = current->lifoSlot())
  21.147 -            var = slot;
  21.148 -    }
  21.149 -
  21.150 -    if (var)
  21.151 -        __ unwindlifo(var->slot());
  21.152 -}
  21.153 -
  21.154 -void
  21.155 -BytecodeCompiler::visit(NameProxy *name)
  21.156 -{
  21.157 -    switch (name->binding()->kind()) {
  21.158 -      case BoundName::VARIABLE:
  21.159 -      {
  21.160 -        Variable *var = name->binding()->toVariable();
  21.161 -
  21.162 -        if (var->location() == Variable::STACK) {
  21.163 -            __ getlocal(var);
  21.164 -            assert(!name->type()->isReference());
  21.165 -        } else if (var->location() == Variable::ENVIRONMENT) {
  21.166 -            getEnvSlot(var);
  21.167 -        } else {
  21.168 -            assert(var->location() == Variable::PARAMETER);
  21.169 -            __ getarg(var);
  21.170 -
  21.171 -            // If this argument is actually a reference, dereference it now.
  21.172 -            if (var->type()->isReference())
  21.173 -                __ getref(var->type()->contained());
  21.174 -        }
  21.175 -        break;
  21.176 -      }
  21.177 -
  21.178 -      case BoundName::FUNCTION:
  21.179 -      {
  21.180 -        NamedFunction *fun = name->binding()->toNamedFunction();
  21.181 -        __ module();
  21.182 -        __ getmodule_fn(fun->slot());
  21.183 -        break;
  21.184 -      }
  21.185 -
  21.186 -      default:
  21.187 -      {
  21.188 -        NamedConstant *constant = name->binding()->toNamedConstant();
  21.189 -        __ int_(constant->value().toInt());
  21.190 -        break;
  21.191 -      }
  21.192 -    }
  21.193 -}
  21.194 -
  21.195 -void
  21.196 -BytecodeCompiler::visit(ExpressionStatement *node)
  21.197 -{
  21.198 -    // Expressions leave their value on the top of the stack, so we make sure
  21.199 -    // to balance the stack if they're used as a statement.
  21.200 -    node->expression()->accept(this);
  21.201 -    if (!node->expression()->type()->isVoid())
  21.202 -        __ pop();
  21.203 -}
  21.204 -
  21.205 -static inline bool
  21.206 -IsCompositeValueType(Type *type)
  21.207 -{
  21.208 -    return type->isStruct() ||
  21.209 -           (type->isArray() && type->isFixedLength());
  21.210 -}
  21.211 -
  21.212 -static inline Array *
  21.213 -StringLiteralToArray(Zone *zone, StringLiteral *node)
  21.214 -{
  21.215 -    Local<Type> type(zone, node->type());
  21.216 -    Local<ArrayMap> map(zone, ArrayMap::Attach(zone, type));
  21.217 -    if (!map)
  21.218 -        return NULL;
  21.219 -
  21.220 -    return Array::NewString(zone,
  21.221 -                            map,
  21.222 -                            node->string()->raw(),
  21.223 -                            node->string()->length(),
  21.224 -                            Heap::Tenure_Old);
  21.225 -}
  21.226 -
  21.227 -void
  21.228 -BytecodeCompiler::visit(Assignment *node)
  21.229 -{
  21.230 -    Local<Type> left(zone_, node->type());
  21.231 -    Local<Type> right(zone_, node->expression()->type());
  21.232 -
  21.233 -    // The first step is three sub-steps:
  21.234 -    //
  21.235 -    //   (1) Bind the left-hand side.
  21.236 -    //   -- If a cumulative operation (+=, etc):
  21.237 -    //   (2) Save a copy of the binding on the stack.
  21.238 -    //   (3) Dereference the binding to get a value.
  21.239 -    //
  21.240 -    if (node->lvalue()->isNameProxy()) {
  21.241 -        NameProxy *proxy = node->lvalue()->toNameProxy();
  21.242 -        Variable *var = proxy->binding()->toVariable();
  21.243 -
  21.244 -        // We need to fetch the variable under the following circumstances:
  21.245 -        //  (1) The variable is a reference, since we'll store into the ref.
  21.246 -        //  (2) The variable is a fixed array, since we need to copy into it.
  21.247 -        //  (3) The variable is a struct, since we need to copy into it.
  21.248 -        if (var->type()->isReference() || IsCompositeValueType(var->type()))
  21.249 -            __ get(var);
  21.250 -
  21.251 -        // Get the value if needed.
  21.252 -        if (node->token() != TOK_ASSIGN) {
  21.253 -            // += etc is not allowed on arrays.
  21.254 -            assert(!var->type()->isArray());
  21.255 -
  21.256 -            if (var->location() == Variable::ENVIRONMENT)
  21.257 -                getEnvSlot(var);
  21.258 -
  21.259 -            if (var->type()->isReference()) {
  21.260 -                __ dup();
  21.261 -                __ getref(var->type()->contained());
  21.262 -            } else if (var->location() != Variable::ENVIRONMENT) {
  21.263 -                __ get(var);
  21.264 -            }
  21.265 -        }
  21.266 -    } else if (node->lvalue()->isFieldExpression()) {
  21.267 -        FieldExpression *expr = node->lvalue()->toFieldExpression();
  21.268 -        __ note_position(expr->pos());
  21.269 -
  21.270 -        expr->left()->accept(this);
  21.271 -
  21.272 -        if (node->token() != TOK_ASSIGN)
  21.273 -            __ dup();
  21.274 -
  21.275 -        if (node->token() != TOK_ASSIGN || IsCompositeValueType(left))
  21.276 -            __ getfield(expr->fieldIndex(), left);
  21.277 -    } else {
  21.278 -        IndexExpression *index = node->lvalue()->toIndexExpression();
  21.279 -        __ note_position(index->pos());
  21.280 -
  21.281 -        index->left()->accept(this);
  21.282 -        index->right()->accept(this);
  21.283 -
  21.284 -        if (node->token() != TOK_ASSIGN)
  21.285 -            __ dup2();
  21.286 -
  21.287 -        if (node->token() != TOK_ASSIGN || IsCompositeValueType(left))
  21.288 -            __ getelem(left);
  21.289 -    }
  21.290 -
  21.291 -    if (node->token() == TOK_ASSIGN) {
  21.292 -        // Special case: if the left-hand side is a string literal, we must
  21.293 -        // spawn a new copy (:TODO: something about const?)
  21.294 -        if (node->expression()->isStringLiteral() && !left->isFixedLength()) {
  21.295 -            Local<Array> string(zone_,
  21.296 -                    StringLiteralToArray(zone_, node->expression()->toStringLiteral()));
  21.297 -            if (!string)
  21.298 -                return;
  21.299 -
  21.300 -            Local<ArrayMap> arrayMap(zone_, ArrayMap::cast(string->map()));
  21.301 -            __ note_position(node->expression()->pos());
  21.302 -            __ int_(string->length());
  21.303 -            __ newarray(OP_NEWSIZED, arrayMap, Heap::Tenure_Default);
  21.304 -            __ object(string);
  21.305 -            __ copyarray();
  21.306 -        } else {
  21.307 -            node->expression()->accept(this);
  21.308 -        }
  21.309 -    } else {
  21.310 -        visitForALU(left, node->expression());
  21.311 -
  21.312 -        TokenKind alu = TokenKind(int(node->token()) - (TOK_ASSIGN_ADD - TOK_PLUS));
  21.313 -        __ note_position(node->pos());
  21.314 -        __ binary(TokenToOpcode(alu));
  21.315 -    }
  21.316 -
  21.317 -    // Emit the store.
  21.318 -    if (left->isArray() && left->isFixedLength()) {
  21.319 -        // (x = y) returns the left-hand side; if |x| is a fixed-length array,
  21.320 -        // then |y| is as well, and we perform a deep copy.
  21.321 -        assert(right->isFixedLength());
  21.322 -        __ note_position(node->pos());
  21.323 -        __ copyarray();
  21.324 -    } else if (left->isStruct()) {
  21.325 -        // Structs have value semantics, so emit a full copy. We don't break
  21.326 -        // this down into u-ops, to avoid unnecessary bytecode explosion.
  21.327 -        assert(right->isStruct());
  21.328 -        __ note_position(node->pos());
  21.329 -        __ copystruct();
  21.330 -    } else if (node->lvalue()->isNameProxy()) {
  21.331 -        NameProxy *proxy = node->lvalue()->toNameProxy();
  21.332 -        Variable *var = proxy->binding()->toVariable();
  21.333 -
  21.334 -        if (var->type()->isReference())
  21.335 -            __ setref(var->type()->contained());
  21.336 -        else if (var->location() == Variable::ENVIRONMENT)
  21.337 -            setEnvSlot(var);
  21.338 -        else
  21.339 -            __ set(var);
  21.340 -    } else if (node->lvalue()->isFieldExpression()) {
  21.341 -        FieldExpression *expr = node->lvalue()->toFieldExpression();
  21.342 -        __ setfield(expr->fieldIndex(), left);
  21.343 -    } else {
  21.344 -        __ setelem(left);
  21.345 -    }
  21.346 -}
  21.347 -
  21.348 -void
  21.349 -BytecodeCompiler::visit(IncDecExpression *node)
  21.350 -{
  21.351 -    // In the postfix case, the logic looks like:
  21.352 -    //      (1) Bind       -> REF
  21.353 -    //      (2) Dup        -> REF REF
  21.354 -    //      (3) Fetch      -> REF VAL
  21.355 -    //      (4) Swap       -> VAL REF
  21.356 -    //      (5) Pick       -> VAL REF VAL
  21.357 -    //      (6) Add        -> VAL REF VAL+1
  21.358 -    //      (7) Store      -> VAL VAL+1
  21.359 -    //      (8) Drop       -> VAL
  21.360 -    //
  21.361 -    // In the prefix case, the logic looks like:
  21.362 -    //      (1) Bind       -> REF
  21.363 -    //      (2) Dup        -> REF REF
  21.364 -    //      (3) Fetch      -> REF VAL
  21.365 -    //      --
  21.366 -    //      --
  21.367 -    //      (6) Add        -> REF VAL+1
  21.368 -    //      (7) Store      -> VAL+1
  21.369 -    //      --
  21.370 -    //
  21.371 -    // This is squirrely enough such that we don't bother sharing too much
  21.372 -    // with the above.
  21.373 -    // 
  21.374 -    // Note: We simulate a "Pick" operation with a dup2+pop.
  21.375 -
  21.376 -    // This is steps (1) to (5).
  21.377 -    Expression *expr = node->expression();
  21.378 -    if (expr->isNameProxy()) {
  21.379 -        NameProxy *proxy = expr->toNameProxy();
  21.380 -        Variable *var = proxy->binding()->toVariable();
  21.381 -
  21.382 -        // Bind.
  21.383 -        if (var->location() == Variable::ENVIRONMENT)
  21.384 -            getEnvSlot(var);
  21.385 -        else if (var->type()->isReference() || var->type()->isArray())
  21.386 -            __ get(var);
  21.387 -
  21.388 -        // Dup and fetch.
  21.389 -        if (var->type()->isReference()) {
  21.390 -            __ dup();
  21.391 -            __ getref(node->type());
  21.392 -            if (node->postfix()) {
  21.393 -                __ swap();
  21.394 -                __ pick2();
  21.395 -            }
  21.396 -        } else {
  21.397 -            assert(!var->type()->isArray());
  21.398 -            if (var->location() != Variable::ENVIRONMENT)
  21.399 -                __ get(var);
  21.400 -            if (node->postfix())
  21.401 -                __ dup();
  21.402 -        }
  21.403 -    } else if (expr->isFieldExpression()) {
  21.404 -        FieldExpression *field = expr->toFieldExpression();
  21.405 -
  21.406 -        field->left()->accept(this);
  21.407 -        __ dup();
  21.408 -        __ getfield(field->fieldIndex(), field->type());
  21.409 -
  21.410 -        if (node->postfix()) {
  21.411 -            // The stack looks like this now:
  21.412 -            // OBJECT VALUE
  21.413 -            __ swap();          // VALUE OBJECT
  21.414 -            __ pick2();         // VALUE OBJECT VALUE
  21.415 -        }
  21.416 -    } else {
  21.417 -        IndexExpression *index = expr->toIndexExpression();
  21.418 -        __ note_position(index->pos());
  21.419 -
  21.420 -        index->left()->accept(this);
  21.421 -        index->right()->accept(this);
  21.422 -
  21.423 -        assert(!node->type()->isArray());
  21.424 -        __ dup2();
  21.425 -        __ getelem(node->type());
  21.426 -
  21.427 -        if (node->postfix()) {
  21.428 -            // The stack looks like this now:
  21.429 -            // ARRAY INDEX VALUE
  21.430 -            //
  21.431 -            // So we must use a PICK operation to rotate the stack into position.
  21.432 -            __ roll3();         // INDEX VALUE ARRAY
  21.433 -            __ roll3();         // VALUE ARRAY INDEX
  21.434 -            __ pick3();         // VALUE ARRAY INDEX VALUE
  21.435 -        }
  21.436 -    }
  21.437 -
  21.438 -    // Perform step (6).
  21.439 -    if (node->type()->isFloat()) {
  21.440 -        __ float_(1.0);
  21.441 -    } else {
  21.442 -        assert(node->type()->isInt32());
  21.443 -        __ int_(1);
  21.444 -    }
  21.445 -
  21.446 -    __ note_position(node->pos());
  21.447 -    if (node->token() == TOK_INCREMENT)
  21.448 -        __ binary(OP_ADD);
  21.449 -    else
  21.450 -        __ binary(OP_SUB);
  21.451 -
  21.452 -    // Perform step (7).
  21.453 -    if (expr->isNameProxy()) {
  21.454 -        NameProxy *proxy = expr->toNameProxy();
  21.455 -        Variable *var = proxy->binding()->toVariable();
  21.456 -
  21.457 -        if (var->type()->isReference())
  21.458 -            __ setref(node->type());
  21.459 -        else if (var->location() == Variable::ENVIRONMENT)
  21.460 -            setEnvSlot(var);
  21.461 -        else
  21.462 -            __ set(var);
  21.463 -    } else if (expr->isFieldExpression()) {
  21.464 -        FieldExpression *field = expr->toFieldExpression();
  21.465 -        __ setfield(field->fieldIndex(), field->type());
  21.466 -    } else {
  21.467 -        assert(expr->isIndexExpression());
  21.468 -        __ setelem(node->type());
  21.469 -    }
  21.470 -
  21.471 -    // Perform step (8).
  21.472 -    if (node->postfix())
  21.473 -        __ pop();
  21.474 -}
  21.475 -
  21.476 -void
  21.477 -BytecodeCompiler::visitForALU(Type *needed, Expression *node)
  21.478 -{
  21.479 -    node->accept(this);
  21.480 -    if (needed->isFloat() && !node->type()->isFloat())
  21.481 -        __ cvt_i2f();
  21.482 -    else
  21.483 -        assert(needed->primitive() == node->type()->primitive());
  21.484 -}
  21.485 -
  21.486 -static inline Type *
  21.487 -GetCoercionType(TokenKind tok, Type *left, Type *right)
  21.488 -{
  21.489 -    if (left->isFloat())
  21.490 -        return left;
  21.491 -    return right;
  21.492 -}
  21.493 -
  21.494 -void
  21.495 -BytecodeCompiler::visit(UnaryExpression *node)
  21.496 -{
  21.497 -    Local<Type> out(zone_, ((Expression *)node)->type());
  21.498 -
  21.499 -    switch (node->token()) {
  21.500 -      case TOK_MINUS:
  21.501 -      {
  21.502 -        Local<Type> type(zone_, node->expression()->type());
  21.503 -        node->expression()->accept(this);
  21.504 -        
  21.505 -        if (out->isFloat())
  21.506 -            __ neg_f();
  21.507 -        else
  21.508 -            __ neg();
  21.509 -        break;
  21.510 -      }
  21.511 -
  21.512 -      case TOK_NOT:
  21.513 -      {
  21.514 -        Local<Type> type(zone_, node->expression()->type());
  21.515 -        node->expression()->accept(this);
  21.516 -        
  21.517 -        if (out->isFloat())
  21.518 -            __ not_f();
  21.519 -        else
  21.520 -            __ not_();
  21.521 -        break;
  21.522 -      }
  21.523 -
  21.524 -      case TOK_LABEL:
  21.525 -      {
  21.526 -        Local<Type> from(zone_, node->expression()->type());
  21.527 -
  21.528 -        node->expression()->accept(this);
  21.529 -        if (!from->isFloat() && out->isFloat())
  21.530 -            __ bits_f2i();
  21.531 -        else if (from->isFloat() && !out->isFloat())
  21.532 -            __ bits_i2f();
  21.533 -        break;
  21.534 -      }
  21.535 -
  21.536 -      case TOK_SIZEOF:
  21.537 -      {
  21.538 -        Local<Type> type(zone_, node->expression()->type());
  21.539 -        if (type->isFixedLength()) {
  21.540 -            __ int_(type->fixedLength());
  21.541 -        } else {
  21.542 -            node->expression()->accept(this);
  21.543 -            __ sizeof_();
  21.544 -        }
  21.545 -        break;
  21.546 -      }
  21.547 -
  21.548 -      default:
  21.549 -        assert(node->token() == TOK_TILDE);
  21.550 -        node->expression()->accept(this);
  21.551 -        __ bitnot();
  21.552 -        break;
  21.553 -    }
  21.554 -}
  21.555 -
  21.556 -void
  21.557 -BytecodeCompiler::visit(BinaryExpression *node)
  21.558 -{
  21.559 -    if (node->token() == TOK_AND || node->token() == TOK_OR) {
  21.560 -        Label success, failure, done;
  21.561 -        visitForTest(node, &success, &failure, &success);
  21.562 -        __ bind(&success);
  21.563 -        __ int_(1);
  21.564 -        __ drop(1);         // Otherwise, the stack depth will be +1 too much.
  21.565 -        __ jump(&done);
  21.566 -        __ bind(&failure);
  21.567 -        __ int_(0);
  21.568 -        __ bind(&done);
  21.569 -        return;
  21.570 -    }
  21.571 -
  21.572 -    Local<Type> leftType(zone_, node->left()->type());
  21.573 -    Local<Type> rightType(zone_, node->right()->type());
  21.574 -    Local<Type> coerce(zone_, GetCoercionType(node->token(), leftType, rightType));
  21.575 -
  21.576 -    visitForALU(coerce, node->left());
  21.577 -    visitForALU(coerce, node->right());
  21.578 -
  21.579 -    Opcode op = TokenToOpcode(node->token());
  21.580 -    if (node->type()->isFloat())
  21.581 -        op = (Opcode)(int(op) + (OP_ADD_F - OP_ADD));
  21.582 -
  21.583 -    __ note_position(node->pos());
  21.584 -    __ binary(op);
  21.585 -}
  21.586 -
  21.587 -void
  21.588 -BytecodeCompiler::visit(IndexExpression *node)
  21.589 -{
  21.590 -    node->left()->accept(this);
  21.591 -    node->right()->accept(this);
  21.592 -    __ note_position(node->pos());
  21.593 -    __ getelem(node->type());
  21.594 -}
  21.595 -
  21.596 -void
  21.597 -BytecodeCompiler::visit(FieldExpression *node)
  21.598 -{
  21.599 -    node->left()->accept(this);
  21.600 -    __ getfield(node->fieldIndex(), node->type());
  21.601 -}
  21.602 -
  21.603 -void
  21.604 -BytecodeCompiler::visit(ReturnStatement *node)
  21.605 -{
  21.606 -    if (node->expression()) {
  21.607 -        node->expression()->accept(this);
  21.608 -        __ return_();
  21.609 -    } else {
  21.610 -        __ returnvoid();
  21.611 -    }
  21.612 -}
  21.613 -
  21.614 -void
  21.615 -BytecodeCompiler::visitForTest(Expression *expression,
  21.616 -                               Label *trueBranch,
  21.617 -                               Label *falseBranch,
  21.618 -                               Label *fallthrough)
  21.619 -{
  21.620 -    TokenKind token = ToCompare(expression);
  21.621 -    if (token == TOK_EOF || token == TOK_NOT) {
  21.622 -        if (token == TOK_EOF)
  21.623 -            expression->accept(this);
  21.624 -        else
  21.625 -            expression->toUnaryExpression()->expression()->accept(this);
  21.626 -        
  21.627 -        bool jumpOnTrue = (fallthrough == falseBranch) ^ (token == TOK_NOT);
  21.628 -
  21.629 -        Opcode op = jumpOnTrue ? OP_JT : OP_JF;
  21.630 -        if (expression->type()->isFloat())
  21.631 -            op = (Opcode)(int(op) + (OP_JL_F - OP_JL));
  21.632 -
  21.633 -        if (fallthrough == falseBranch)
  21.634 -            __ j(op, trueBranch);
  21.635 -        else
  21.636 -            __ j(op, falseBranch); 
  21.637 -        return;
  21.638 -    }
  21.639 -
  21.640 -    BinaryExpression *binary = expression->toBinaryExpression();
  21.641 -
  21.642 -    if (token == TOK_AND || token == TOK_OR) {
  21.643 -        Label next;
  21.644 -        if (token == TOK_AND)
  21.645 -            visitForTest(binary->left(), &next, falseBranch, &next);
  21.646 -        else
  21.647 -            visitForTest(binary->left(), trueBranch, &next, &next);
  21.648 -        __ bind(&next);
  21.649 -        visitForTest(binary->right(), trueBranch, falseBranch, fallthrough);
  21.650 -        return;
  21.651 -    }
  21.652 -
  21.653 -    Opcode op = CompareTokenToJump(token);
  21.654 -    if (fallthrough == trueBranch)
  21.655 -        op = Invert(op);
  21.656 -
  21.657 -    Local<Type> leftType(zone_, binary->left()->type());
  21.658 -    Local<Type> rightType(zone_, binary->right()->type());
  21.659 -    Local<Type> coerce(zone_, GetCoercionType(binary->token(), leftType, rightType));
  21.660 -
  21.661 -    visitForALU(coerce, binary->left());
  21.662 -    visitForALU(coerce, binary->right());
  21.663 -    if (coerce->isFloat())
  21.664 -        op = (Opcode)(int(op) + (OP_JL_F - OP_JL));
  21.665 -
  21.666 -    if (fallthrough == trueBranch)
  21.667 -        __ j(op, falseBranch);
  21.668 -    else
  21.669 -        __ j(op, trueBranch);
  21.670 -}
  21.671 -
  21.672 -void
  21.673 -BytecodeCompiler::visit(ForStatement *node)
  21.674 -{
  21.675 -    AutoEnterScope forScope(this, node->scope());
  21.676 -
  21.677 -    recordLifoSlot(node->scope());
  21.678 -
  21.679 -    Label join, update;
  21.680 -    LoopScope loop(scope_, &join, &update, &loop_);
  21.681 -
  21.682 -    if (node->initialization())
  21.683 -        node->initialization()->accept(this);
  21.684 -
  21.685 -    Label header, test;
  21.686 -    if (node->condition())
  21.687 -        __ jump(&test);
  21.688 -
  21.689 -    __ bind(&header);
  21.690 -    node->body()->accept(this);
  21.691 -
  21.692 -    __ bind(&update);
  21.693 -    if (node->update())
  21.694 -        node->update()->accept(this);
  21.695 -
  21.696 -    if (node->condition()) {
  21.697 -        __ bind(&test);
  21.698 -        visitForTest(node->condition(), &header, &join, &join);
  21.699 -    } else {
  21.700 -        __ jump(&header);
  21.701 -    }
  21.702 -
  21.703 -    __ bind(&join);
  21.704 -
  21.705 -    if (node->scope())
  21.706 -        unwindTo(node->scope()->enclosing());
  21.707 -    assert(__ stackDepth() == 0);
  21.708 -}
  21.709 -
  21.710 -void
  21.711 -BytecodeCompiler::visit(WhileStatement *node)
  21.712 -{
  21.713 -    Label header, join;
  21.714 -
  21.715 -    __ bind(&header);
  21.716 -
  21.717 -    LoopScope loop(scope_, &join, &header, &loop_);
  21.718 -
  21.719 -    if (node->token() == TOK_WHILE) {
  21.720 -        Label body;
  21.721 -
  21.722 -        visitForTest(node->condition(), &body, &join, &body);
  21.723 -        __ bind(&body);
  21.724 -        node->body()->accept(this);
  21.725 -        __ jump(&header);
  21.726 -    } else {
  21.727 -        node->body()->accept(this);
  21.728 -        visitForTest(node->condition(), &header, &join, &join);
  21.729 -    }
  21.730 -
  21.731 -    __ bind(&join);
  21.732 -}
  21.733 -
  21.734 -void
  21.735 -BytecodeCompiler::visit(BreakStatement *node)
  21.736 -{
  21.737 -    unwindTo(loop_->scope());
  21.738 -    __ jump(loop_->break_());
  21.739 -}
  21.740 -
  21.741 -void
  21.742 -BytecodeCompiler::visit(ContinueStatement *node)
  21.743 -{
  21.744 -    unwindTo(loop_->scope());
  21.745 -    __ jump(loop_->continue_());
  21.746 -}
  21.747 -
  21.748 -void
  21.749 -BytecodeCompiler::visit(BlockStatement *node)
  21.750 -{
  21.751 -    AutoEnterScope blockScope(this, node->scope());
  21.752 -
  21.753 -    recordLifoSlot(node->scope());
  21.754 -
  21.755 -    for (size_t i = 0; i < node->statements()->length(); i++) {
  21.756 -        Statement *statement = node->statements()->at(i);
  21.757 -        statement->accept(this);
  21.758 -        assert(__ stackDepth() == 0);
  21.759 -    }
  21.760 -
  21.761 -    // We don't bother emitting an "unwind" instruction for function scopes,
  21.762 -    // since this is taken care of by the calling convention.
  21.763 -    if (node->scope() && node->scope()->enclosing()->kind() != Scope::FUNCTION)
  21.764 -        unwindTo(node->scope()->enclosing());
  21.765 -}
  21.766 -
  21.767 -void
  21.768 -BytecodeCompiler::visit(IntegerLiteral *node)
  21.769 -{
  21.770 -    __ int_(node->value());
  21.771 -}
  21.772 -
  21.773 -void
  21.774 -BytecodeCompiler::visit(BooleanLiteral *node)
  21.775 -{
  21.776 -    if (node->token() == TOK_TRUE)
  21.777 -        __ true_();
  21.778 -    else
  21.779 -        __ false_();
  21.780 -}
  21.781 -
  21.782 -void
  21.783 -BytecodeCompiler::visit(FloatLiteral *node)
  21.784 -{
  21.785 -    __ float_((float)node->value());
  21.786 -}
  21.787 -
  21.788 -void
  21.789 -BytecodeCompiler::visit(StringLiteral *node)
  21.790 -{
  21.791 -    Local<Array> array(zone_, StringLiteralToArray(zone_, node));
  21.792 -    if (!array)
  21.793 -        return;
  21.794 -
  21.795 -    __ note_position(node->pos());
  21.796 -    __ object(array);
  21.797 -}
  21.798 -
  21.799 -void
  21.800 -BytecodeCompiler::getEnvSlot(Variable *var)
  21.801 -{
  21.802 -    assert(var->scope()->kind() == Scope::GLOBAL);
  21.803 -    __ getglobal(var);
  21.804 -}
  21.805 -
  21.806 -void
  21.807 -BytecodeCompiler::setEnvSlot(Variable *var)
  21.808 -{
  21.809 -    assert(var->scope()->kind() == Scope::GLOBAL);
  21.810 -    __ setglobal(var);
  21.811 -}
  21.812 -
  21.813 -static bool
  21.814 -FillArrayLiteral_String(Zone *zone, Handle<Array> array, ArrayLiteral *literal, unsigned *maxsize)
  21.815 -{
  21.816 -    Local<Array> string(zone);
  21.817 -    for (size_t i = 0; i < literal->expressions()->length(); i++) {
  21.818 -        Expression *expr = literal->expressions()->at(i);
  21.819 -        StringLiteral *lit = expr->toStringLiteral();
  21.820 -        if ((string = StringLiteralToArray(zone, lit)) == NULL)
  21.821 -            return false;
  21.822 -
  21.823 -        array->writeObject(zone, i, string);
  21.824 -
  21.825 -        if (string->length() > *maxsize)
  21.826 -            *maxsize = string->length();
  21.827 -
  21.828 -        assert(!array->type()->contained()->isFixedLength() ||
  21.829 -                array->type()->contained()->fixedLength() >= string->length());
  21.830 -    }
  21.831 -
  21.832 -    return true;
  21.833 -}
  21.834 -
  21.835 -static bool
  21.836 -FillArrayLiteral_Primitive(Zone *zone, Handle<Array> array, ArrayLiteral *literal)
  21.837 -{
  21.838 -    assert(array->type()->fixedLength() == literal->expressions()->length());
  21.839 -
  21.840 -    for (size_t i = 0; i < literal->expressions()->length(); i++) {
  21.841 -        Expression *expr = literal->expressions()->at(i);
  21.842 -        if (IntegerLiteral *lit = expr->asIntegerLiteral()) {
  21.843 -            array->writeInt32(i, lit->value());
  21.844 -            continue;
  21.845 -        }
  21.846 -        if (BooleanLiteral *lit = expr->asBooleanLiteral()) {
  21.847 -            if (lit->token() == TOK_TRUE)
  21.848 -                array->writeInt32(i, 1);
  21.849 -            else
  21.850 -                array->writeInt32(i, 0);
  21.851 -            continue;
  21.852 -        }
  21.853 -        if (FloatLiteral *lit = expr->asFloatLiteral()) {
  21.854 -            array->writeFloat(i, (float)lit->value());
  21.855 -            continue;
  21.856 -        }
  21.857 -
  21.858 -        // Unrecognized literal type.
  21.859 -        assert(false);
  21.860 -    }
  21.861 -
  21.862 -    return true;
  21.863 -}
  21.864 -
  21.865 -static bool
  21.866 -TraverseArrayLiteral(Zone *zone, ArrayLiteral *literal, Handle<Array> array, Handle<Type> type,
  21.867 -                     unsigned *maxsize)
  21.868 -{
  21.869 -    assert(type->fixedLength() == literal->expressions()->length());
  21.870 -
  21.871 -    Local<Type> contained(zone, type->contained());
  21.872 -    if (contained->isCharArray())
  21.873 -        return FillArrayLiteral_String(zone, array, literal, maxsize);
  21.874 -
  21.875 -    if (!contained->isArray())
  21.876 -        return FillArrayLiteral_Primitive(zone, array, literal);
  21.877 -
  21.878 -    Local<Array> subarray(zone);
  21.879 -    for (size_t i = 0; i < literal->expressions()->length(); i++) {
  21.880 -        Expression *expr = literal->expressions()->at(i);
  21.881 -        subarray = Array::cast(array->readObject(i));
  21.882 -        if (!TraverseArrayLiteral(zone, expr->toArrayLiteral(), subarray, contained, maxsize))
  21.883 -            return false;
  21.884 -    }
  21.885 -
  21.886 -    return true;
  21.887 -}
  21.888 -
  21.889 -static Array *
  21.890 -BuildArrayLiteral(Zone *zone, ArrayLiteral *literal, Handle<ArrayMap> map, unsigned *maxsize)
  21.891 -{
  21.892 -    Local<Array> root(zone, Array::NewFixed(zone, map, Heap::Tenure_Old));
  21.893 -    if (!root)
  21.894 -        return NULL;
  21.895 -
  21.896 -    // This should have allocated everything in the array, so all we need to
  21.897 -    // do is traverse down to the lowest levels and copy things.
  21.898 -    Local<Type> type(zone, map->type());
  21.899 -    if (!TraverseArrayLiteral(zone, literal, root, type, maxsize))
  21.900 -        return NULL;
  21.901 -
  21.902 -    return root;
  21.903 -}
  21.904 -
  21.905 -static inline bool
  21.906 -ArrayContainsCharBuffers(Type *type)
  21.907 -{
  21.908 -    if (type->contained()->isArray())
  21.909 -        return ArrayContainsCharBuffers(type->contained());
  21.910 -    return type->isCharArray();
  21.911 -}
  21.912 -
  21.913 -void
  21.914 -BytecodeCompiler::visit(VariableDeclaration *node)
  21.915 -{
  21.916 -    Variable *var = node->variable();
  21.917 -    
  21.918 -    Local<Type> type(zone_, var->type());
  21.919 -    if (type->isArray()) {
  21.920 -        Local<ArrayMap> map(zone_, ArrayMap::Attach(zone_, type));
  21.921 -        __ note_position(node->pos());
  21.922 -
  21.923 -        Local<Type> right(zone_);
  21.924 -        if (node->initialization())
  21.925 -            right = node->initialization()->type();
  21.926 -
  21.927 -        // There are a few methods for allocating, here:
  21.928 -        // (1) If the array is fixed,
  21.929 -        //    (a) Initializer not present,
  21.930 -        //              NEWFIXED
  21.931 -        //    (b) Left is const non-string:
  21.932 -        //              <nothing>
  21.933 -        //    (b) Otherwise:
  21.934 -        //              NEWFIXED
  21.935 -        //              COPYARRAY
  21.936 -        // (2) If the array is not fixed,
  21.937 -        //    (a) Initializer is not present,
  21.938 -        //              NEWEMPTY
  21.939 -        //    (b) Initializer is not a string literal,
  21.940 -        //        or left is const:
  21.941 -        //              <nothing>
  21.942 -        //    (c) Initializer is a string literal,
  21.943 -        //              NEWSIZED
  21.944 -        //              COPYARRAY
  21.945 -        //
  21.946 -
  21.947 -        Heap::Tenure tenure = var->scope()->kind() == Scope::GLOBAL
  21.948 -                              ? Heap::Tenure_Old
  21.949 -                              : Heap::Tenure_Default;
  21.950 -
  21.951 -        if (Expression *init = node->initialization()) {
  21.952 -            if (init->isArrayLiteral()) {
  21.953 -                unsigned maxsize = 0;
  21.954 -                Local<Array> array(zone_, BuildArrayLiteral(zone_, init->toArrayLiteral(), map, &maxsize));
  21.955 -                if (!array)
  21.956 -                    return;
  21.957 -
  21.958 -                assert(type->isFixedLength());
  21.959 -
  21.960 -                if (type->isConst()) {
  21.961 -                    __ object(array);
  21.962 -                } else if (ArrayContainsCharBuffers(type)) {
  21.963 -                    // This array contains mutable char buffers, so
  21.964 -                    // unfortunately this gets a little more complicated. We
  21.965 -                    // compute the maximum size needed for the innermost
  21.966 -                    // string, which is similar to SP1. This means we can use
  21.967 -                    // CopyArray rather than individually emit opcodes to clone
  21.968 -                    // every string.
  21.969 -                    Local<Type> child(zone_, type);
  21.970 -                    for (size_t i = 0; i < type->levels() - 1; i++) {
  21.971 -                        __ int_(child->fixedLength());
  21.972 -                        child = child->contained();
  21.973 -                    }
  21.974 -                    __ int_(maxsize);
  21.975 -                    __ newarray(OP_NEWSIZED, map, tenure);
  21.976 -                    __ object(array);
  21.977 -                    __ copyarray();
  21.978 -                } else {
  21.979 -                    __ newarray(OP_NEWFIXED, map, tenure);
  21.980 -                    __ object(array);
  21.981 -                    __ copyarray();
  21.982 -                }
  21.983 -            } else if (type->isFixedLength()) {
  21.984 -                // Note in the case of:
  21.985 -                // const String:buffer[50] = "hello";
  21.986 -                //
  21.987 -                // We want to preserve sizeof(buffer) == 50.
  21.988 -                if (type->isConst() && !type->isCharArray()) {
  21.989 -                    init->accept(this);
  21.990 -                } else {
  21.991 -                    __ newarray(OP_NEWFIXED, map, tenure);
  21.992 -                    init->accept(this);
  21.993 -                    __ copyarray();
  21.994 -                }
  21.995 -            } else if (!type->isConst() && init->isStringLiteral()) {
  21.996 -                // This is a degenerate case of ArrayLiteral.
  21.997 -                __ int_(right->fixedLength());
  21.998 -                __ newarray(OP_NEWSIZED, map, tenure);
  21.999 -                init->accept(this);
 21.1000 -                __ copyarray();
 21.1001 -            } else if (type->isConst()) {
 21.1002 -                init->accept(this);
 21.1003 -            }
 21.1004 -        } else if (type->isFixedLength()) {
 21.1005 -            __ newarray(OP_NEWFIXED, map, tenure);
 21.1006 -        } else {
 21.1007 -#if 0
 21.1008 -            if (node->postDimensions()) {
 21.1009 -                for (size_t i = 0; i < node->postDimensions()->length(); i++) {
 21.1010 -                    Expression *expr = node->postDimensions()->at(i);
 21.1011 -                    if (expr)
 21.1012 -                        expr->accept(this);
 21.1013 -                    else
 21.1014 -                        __ int_(0);
 21.1015 -                }
 21.1016 -                __ newarray(OP_NEWSIZED, map, tenure);
 21.1017 -            } else {
 21.1018 -                __ newarray(OP_NEWEMPTY, map, tenure);
 21.1019 -            }
 21.1020 -#endif
 21.1021 -        }
 21.1022 -    } else if (type->isStruct()) {
 21.1023 -        Local<StructMap> map(zone_, StructMap::cast(type->newMap()));
 21.1024 -
 21.1025 -        // Because structs can contain arrays, any sort of composition
 21.1026 -        // triggers non-LIFO allocation. This is just for correctness.
 21.1027 -        // We could do better by:
 21.1028 -        //  (1) Limiting to structs that just (recursively) contain arrays,
 21.1029 -        //  (2) Swap Stack for Default tenure in Struct::New
 21.1030 -        //  (3) JIT analysis
 21.1031 -        if (var->scope()->kind() == Scope::GLOBAL)
 21.1032 -            __ newstruct(map, Heap::Tenure_Old);
 21.1033 -        else if (var->needsHeapAllocation() || map->composed())
 21.1034 -            __ newstruct(map, Heap::Tenure_Default);
 21.1035 -        else
 21.1036 -            __ newstruct(map, Heap::Tenure_Stack);
 21.1037 -    } else {
 21.1038 -        if (node->initialization()) {
 21.1039 -            node->initialization()->accept(this);
 21.1040 -        } else {
 21.1041 -            if (type->isInt32OrEnum() || type->isBool()) {
 21.1042 -                __ int_(0);
 21.1043 -            } else {
 21.1044 -                assert(type->isFloat());
 21.1045 -                __ float_(0);
 21.1046 -            }
 21.1047 -        }
 21.1048 -    }
 21.1049 -
 21.1050 -    if (var->location() == Variable::STACK) {
 21.1051 -        __ setlocal(var);
 21.1052 -        locals_->set(zone_, var->slot(), var->type());
 21.1053 -    } else {
 21.1054 -        assert(var->location() == Variable::ENVIRONMENT);
 21.1055 -        setEnvSlot(var);
 21.1056 -    }
 21.1057 -
 21.1058 -    __ pop();
 21.1059 -}
 21.1060 -
 21.1061 -void
 21.1062 -BytecodeCompiler::visit(CallExpression *node)
 21.1063 -{
 21.1064 -#if 0
 21.1065 -    Local<Type> funType(zone_, node->callee()->type());
 21.1066 -
 21.1067 -    // Sniff out natives, which have a specific opcode and are guaranteed to
 21.1068 -    // be called via name proxy.
 21.1069 -    NamedFunction *native = NULL;
 21.1070 -    if (funType->isNative())
 21.1071 -        native = node->callee()->toNameProxy()->binding()->toNamedFunction();
 21.1072 -
 21.1073 -    Local<Type> given(zone_);
 21.1074 -    for (size_t i = node->arguments()->length() - 1; i < node->arguments()->length(); i--) {
 21.1075 -        Expression *arg = node->arguments()->at(i);
 21.1076 -
 21.1077 -        given = arg->type();
 21.1078 -
 21.1079 -        // We need to compute a reference if the parameter was in the form:
 21.1080 -        //  f(&a)
 21.1081 -        // Note this form does not allow: f({})
 21.1082 -        // 
 21.1083 -        // We also need to compute references for all variadic native
 21.1084 -        // arguments, but arrays and references are already in the
 21.1085 -        // appropriate form.
 21.1086 -        bool mustPushReference = false;
 21.1087 -        if (i >= funType->parameters()->length()) {
 21.1088 -            assert(funType->isNative() && funType->isNativeVariadic());
 21.1089 -            mustPushReference = !given->isArray() && !given->isReference();
 21.1090 -        } else if (funType->parameterAt(i)->isReference()) {
 21.1091 -            mustPushReference = !given->isReference();
 21.1092 -        }
 21.1093 -
 21.1094 -        // If a native is passed to a native, it must only be one level deep.
 21.1095 -        assert(!funType->isNative() || !given->isArray() || given->levels() == 1);
 21.1096 -
 21.1097 -        if (mustPushReference) {
 21.1098 -            if (arg->isNameProxy()) {
 21.1099 -                // :TODO: test with functions and globals
 21.1100 -                // Compute a reference to the name.
 21.1101 -                Variable *var = arg->toNameProxy()->binding()->toVariable();
 21.1102 -                __ note_position(node->pos());
 21.1103 -                __ newref(var);
 21.1104 -            } else if (arg->isFieldExpression()) {
 21.1105 -                FieldExpression *expr = arg->toFieldExpression();
 21.1106 -                expr->left()->accept(this);
 21.1107 -                __ note_position(expr->pos());
 21.1108 -                __ fieldref_lifo(expr->fieldIndex());
 21.1109 -            } else {
 21.1110 -                // We don't know how to, or can't, build a direct reference to
 21.1111 -                // this type. Make an indirect one, by taking the top of the
 21.1112 -                // stack and boxing it up.
 21.1113 -                arg->accept(this);
 21.1114 -                __ note_position(node->pos());
 21.1115 -                __ slotref_lifo();
 21.1116 -            }
 21.1117 -        } else {
 21.1118 -            arg->accept(this);
 21.1119 -        }
 21.1120 -    }
 21.1121 -
 21.1122 -    unsigned argc = node->arguments()->length();
 21.1123 -
 21.1124 -    // If there are missing arguments, then we're not done and have to push
 21.1125 -    // default parameters.
 21.1126 -    Local<Box> box(zone_);
 21.1127 -    Local<Array> array(zone_);
 21.1128 -    Local<ArrayMap> map(zone_);
 21.1129 -    for (size_t i = node->arguments()->length(); i < funType->parameters()->length(); i++) {
 21.1130 -        box = Box::cast(funType->defaults()->at(i));
 21.1131 -
 21.1132 -        if (box->type()->isPod()) {
 21.1133 -            if (box->type()->pod() == PrimitiveType_Int32)
 21.1134 -                __ int_(box->toInt32());
 21.1135 -            else if (box->type()->pod() == PrimitiveType_Float)
 21.1136 -                __ float_(box->toFloat());
 21.1137 -            else
 21.1138 -                assert(false);
 21.1139 -
 21.1140 -            if (funType->parameterAt(i)->isReference()) {
 21.1141 -                __ note_position(node->pos());
 21.1142 -                __ slotref_lifo();
 21.1143 -            }
 21.1144 -        } else {
 21.1145 -            assert(box->type()->isArray());
 21.1146 -
 21.1147 -            array = Array::cast(box->toObject());
 21.1148 -            if (funType->parameterAt(i)->isConst()) {
 21.1149 -                __ object(array);
 21.1150 -            } else {
 21.1151 -                // We need to copy the array since it's mutable. Note that
 21.1152 -                // although COPYARRAY returns its left-hand side, this may
 21.1153 -                // change in the future, we do the same thing and dupe the
 21.1154 -                // newly allocated array.
 21.1155 -                map = ArrayMap::cast(array->map());
 21.1156 -                
 21.1157 -                // Natives cannot escape array references, so we can allocate
 21.1158 -                // them on the LIFO stack.
 21.1159 -                if (funType->isNative())
 21.1160 -                    __ newarray(OP_NEWFIXED, map, Heap::Tenure_Stack);
 21.1161 -                else
 21.1162 -                    __ newarray(OP_NEWFIXED, map, Heap::Tenure_Default);
 21.1163 -                __ dup();
 21.1164 -                __ object(array);
 21.1165 -                __ copyarray();
 21.1166 -                __ pop();
 21.1167 -            }
 21.1168 -        }
 21.1169 -
 21.1170 -        argc++;
 21.1171 -    }
 21.1172 -
 21.1173 -    __ note_position(node->pos());
 21.1174 -    if (native) {
 21.1175 -        __ callnative(native->slot(), argc);
 21.1176 -        __ drop(argc);
 21.1177 -    } else {
 21.1178 -        node->callee()->accept(this);
 21.1179 -        __ call(funType);
 21.1180 -        __ drop(argc + 1);
 21.1181 -    }
 21.1182 -#endif
 21.1183 -}
 21.1184 -
 21.1185 -void
 21.1186 -BytecodeCompiler::visit(TernaryExpression *node)
 21.1187 -{
 21.1188 -    Label success, failure, join;
 21.1189 -
 21.1190 -    visitForTest(node->condition(), &success, &failure, &success);
 21.1191 -    __ bind(&success);
 21.1192 -    node->left()->accept(this);
 21.1193 -    __ drop(1);
 21.1194 -    __ jump(&join);
 21.1195 -    __ bind(&failure);
 21.1196 -    node->right()->accept(this);
 21.1197 -    __ bind(&join);
 21.1198 -}
 21.1199 -
 21.1200 -void
 21.1201 -BytecodeCompiler::visit(IfStatement *node)
 21.1202 -{
 21.1203 -    Label join;
 21.1204 -    if (!node->ifFalse()) {
 21.1205 -        Label success;
 21.1206 -
 21.1207 -        visitForTest(node->condition(), &success, &join, &success);
 21.1208 -        __ bind(&success);
 21.1209 -        node->ifTrue()->accept(this);
 21.1210 -    } else {
 21.1211 -        Label success, next;
 21.1212 -
 21.1213 -        visitForTest(node->condition(), &success, &next, &success);
 21.1214 -        __ bind(&success);
 21.1215 -        node->ifTrue()->accept(this);
 21.1216 -        __ jump(&join);
 21.1217 -        __ bind(&next);
 21.1218 -        node->ifFalse()->accept(this);
 21.1219 -    }
 21.1220 -
 21.1221 -    __ bind(&join);
 21.1222 -}
 21.1223 -
 21.1224 -bool
 21.1225 -BytecodeCompiler::tableswitch(SwitchStatement *node)
 21.1226 -{
 21.1227 -    CaseValueList *values = node->caseValueList();
 21.1228 -
 21.1229 -    if (values->length() < 3)
 21.1230 -        return false;
 21.1231 -
 21.1232 -    // Find the delta between the largest and smallest value.
 21.1233 -    int hi = values->at(values->length() - 1).box.toInt();
 21.1234 -    int lo = values->at(0).box.toInt();
 21.1235 -    assert(hi > lo);
 21.1236 -
 21.1237 -    unsigned tablesize = TableSwitchEntries(lo, hi);
 21.1238 -    if (tablesize > MAX_TABLESWITCH_ENTRIES)
 21.1239 -        return false;
 21.1240 -
 21.1241 -    Label def, join;
 21.1242 -
 21.1243 -    // Create the list of labels that each statement will bind to.
 21.1244 -    Label *labels = new Label[node->cases()->length()];
 21.1245 -
 21.1246 -    // Create the table of labels we'll use for each case.
 21.1247 -    Label **table = new Label *[tablesize];
 21.1248 -
 21.1249 -    // Link all cases, by default, to the default label.
 21.1250 -    for (size_t i = 0; i < tablesize; i++)
 21.1251 -        table[i] = &def;
 21.1252 -
 21.1253 -    // Now patch actual cases to their correct labels.
 21.1254 -    for (size_t i = 0; i < values->length(); i++) {
 21.1255 -        CaseValue &v = values->at(i);
 21.1256 -        assert(v.statement < node->cases()->length());
 21.1257 -
 21.1258 -        unsigned index = unsigned(v.box.toInt() - lo);
 21.1259 -        assert(index < tablesize);
 21.1260 -
 21.1261 -        table[index] = &labels[v.statement];
 21.1262 -    }
 21.1263 -
 21.1264 -    // Emit the tableswitch opcode and the jump table.
 21.1265 -    __ tableswitch(lo, hi, &def, table);
 21.1266 -
 21.1267 -    // We're done with the jump table now.
 21.1268 -    delete [] table;
 21.1269 -
 21.1270 -    // Emit each statement.
 21.1271 -    for (size_t i = 0; i < node->cases()->length(); i++) {
 21.1272 -        Statement *stmt = node->cases()->at(i)->statement();
 21.1273 -
 21.1274 -        __ bind(&labels[i]);
 21.1275 -        stmt->accept(this);
 21.1276 -        __ jump(&join);
 21.1277 -    }
 21.1278 -
 21.1279 -    // We're done with the statement labels.
 21.1280 -    delete [] labels;
 21.1281 -
 21.1282 -    // Emit the default case.
 21.1283 -    __ bind(&def);
 21.1284 -    if (node->defaultCase())
 21.1285 -        node->defaultCase()->accept(this);
 21.1286 -
 21.1287 -    __ bind(&join);
 21.1288 -
 21.1289 -    return true;
 21.1290 -}
 21.1291 -
 21.1292 -void
 21.1293 -BytecodeCompiler::visit(SwitchStatement *node)
 21.1294 -{
 21.1295 -    node->expression()->accept(this);
 21.1296 -
 21.1297 -    if (tableswitch(node))
 21.1298 -        return;
 21.1299 -
 21.1300 -    Label join;
 21.1301 -
 21.1302 -    for (size_t i = 0; i < node->cases()->length(); i++) {
 21.1303 -        Case *c = node->cases()->at(i);
 21.1304 -
 21.1305 -        Label success, fail;
 21.1306 -        if (c->others()) {
 21.1307 -            for (size_t j = 0; j < c->others()->length(); j++) {
 21.1308 -                Expression *expr = c->others()->at(j);
 21.1309 -
 21.1310 -                __ dup();
 21.1311 -                expr->accept(this);
 21.1312 -                __ j(OP_JEQ, &success);
 21.1313 -            }
 21.1314 -        }
 21.1315 -
 21.1316 -        // The final test.
 21.1317 -        __ dup();
 21.1318 -        c->expression()->accept(this);
 21.1319 -        __ j(OP_JNE, &fail);
 21.1320 -        __ bind(&success);
 21.1321 -        c->statement()->accept(this);
 21.1322 -        __ jump(&join);
 21.1323 -        __ bind(&fail);
 21.1324 -    }
 21.1325 -
 21.1326 -    if (node->defaultCase())
 21.1327 -        node->defaultCase()->accept(this);
 21.1328 -
 21.1329 -    __ pop();
 21.1330 -    __ bind(&join);
 21.1331 -}
 21.1332 -
 21.1333 -void
 21.1334 -BytecodeCompiler::visit(FunctionStatement *node)
 21.1335 -{
 21.1336 -    if (!node->fun()->used())
 21.1337 -        return;
 21.1338 -
 21.1339 -    if (node->fun()->isNative()) {
 21.1340 -        assert(!moduleData_->natives->at(node->fun()->slot()));
 21.1341 -
 21.1342 -        Local<FunctionType> type(zone_, FunctionType::cast(node->fun()->type()));
 21.1343 -        Local<String> name(zone_, node->fun()->name());
 21.1344 -        Local<Native> native(zone_, Native::New(zone_, type, name));
 21.1345 -        if (!native)
 21.1346 -            return;
 21.1347 -
 21.1348 -        moduleData_->natives->set(zone_, node->fun()->slot(), native);
 21.1349 -        return;
 21.1350 -    }
 21.1351 -
 21.1352 -    // If the function has no body, then it's just a declaration.
 21.1353 -    if (!node->body()) {
 21.1354 -        assert(node->fun()->isForward() || node->fun()->isPublic());
 21.1355 -        return;
 21.1356 -    }
 21.1357 -
 21.1358 -    BytecodeCompiler child(zone_, tree_, moduleData_);
 21.1359 -    Local<Function> fun(zone_, child.compileFunction(moduleData_, node));
 21.1360 -    if (!fun)
 21.1361 -        return;
 21.1362 -    
 21.1363 -    assert(!moduleData_->module->getFunction(node->fun()->slot()));
 21.1364 -    moduleData_->module->setFunction(zone_, node->fun()->slot(), fun);
 21.1365 -}
 21.1366 -
 21.1367 -void
 21.1368 -BytecodeCompiler::visit(FunctionTypeStatement *node)
 21.1369 -{
 21.1370 -}
 21.1371 -
 21.1372 -void
 21.1373 -BytecodeCompiler::visit(EnumStatement *node)
 21.1374 -{
 21.1375 -}
 21.1376 -
 21.1377 -void
 21.1378 -BytecodeCompiler::visit(StructureStatement *node)
 21.1379 -{
 21.1380 -}
 21.1381 -
 21.1382 -void
 21.1383 -BytecodeCompiler::visit(ArrayLiteral *node)
 21.1384 -{
 21.1385 -    // We shouldn't reach these; they're handled manually when initializing
 21.1386 -    // declared arrays.
 21.1387 -    assert(false);
 21.1388 -}
 21.1389 -
 21.1390 -void
 21.1391 -BytecodeCompiler::visit(ImportStatement *node)
 21.1392 -{
 21.1393 -}
 21.1394 -
 21.1395 -Code *
 21.1396 -BytecodeCompiler::compileCode(Scope *scope, unsigned lineno)
 21.1397 -{
 21.1398 -    // STOP doubles as RETURNVOID.
 21.1399 -    __ stop();
 21.1400 -
 21.1401 -    if (__ oom() || zone_->hasPendingException())
 21.1402 -        return NULL;
 21.1403 -
 21.1404 -    Local<ByteArray> bytes(zone_, ByteArray::New(zone_, __ length() * sizeof(bytecode), Heap::Tenure_Old));
 21.1405 -    if (!bytes)
 21.1406 -        return NULL;
 21.1407 -    memcpy(bytes->raw(), __ buffer(), __ length());
 21.1408 -
 21.1409 -    for (size_t i = 0; i < scope->maxContainedLocals(); i++)
 21.1410 -        assert(locals_->at(i));
 21.1411 -
 21.1412 -    Local<FixedArray> objects(zone_, FixedArray::New(zone_, __ objects()->length(), Heap::Tenure_Old));
 21.1413 -    if (!objects)
 21.1414 -        return NULL;
 21.1415 -
 21.1416 -    for (size_t i = 0; i < __ objects()->length(); i++)
 21.1417 -        objects->set(zone_, i, *(__ objects()->at(i)));
 21.1418 -
 21.1419 -    Local<ByteArray> safepoints(zone_);
 21.1420 -
 21.1421 -    // If any stack slots hold gc pointers at potential failure points in the
 21.1422 -    // bytecode, record them now. We do this by building a list of tuples;
 21.1423 -    // each tuple contains the pc offset, and a bitset containing which stack
 21.1424 -    // slots must be scanned by the gc.
 21.1425 -    if (__ oopRecords()->length()) {
 21.1426 -        size_t bytesPerSafepoint = Code::BytesPerSafepoint(__ maxStackDepth());
 21.1427 -        size_t gcmapSize = bytesPerSafepoint * __ oopRecords()->length();
 21.1428 -        safepoints = ByteArray::New(zone_, gcmapSize, Heap::Tenure_Old);
 21.1429 -        if (!safepoints)
 21.1430 -            return NULL;
 21.1431 -
 21.1432 -        Address cursor = safepoints->raw();
 21.1433 -        for (size_t i = 0; i < __ oopRecords()->length(); i++) {
 21.1434 -            OopRecord *record = __ oopRecords()->at(i);
 21.1435 -            assert(record->depth <= __ maxStackDepth());
 21.1436 -
 21.1437 -            *reinterpret_cast<unsigned *>(cursor) = record->offset;
 21.1438 -
 21.1439 -            unsigned char *bits = reinterpret_cast<unsigned char *>(cursor + sizeof(unsigned));
 21.1440 -            for (unsigned i = 0; i < record->depth; i++)
 21.1441 -                bits[i / 8] |= (1 << (i % 8));
 21.1442 -
 21.1443 -            cursor += bytesPerSafepoint;
 21.1444 -        }
 21.1445 -
 21.1446 -        assert(cursor == safepoints->raw() + gcmapSize);
 21.1447 -    }
 21.1448 -
 21.1449 -    Local<ByteArray> sourcemap(zone_);
 21.1450 -    if (__ sourcemapLength()) {
 21.1451 -        sourcemap = ByteArray::New(zone_, __ sourcemapLength(), Heap::Tenure_Old);
 21.1452 -        if (!sourcemap)
 21.1453 -            return NULL;
 21.1454 -
 21.1455 -        memcpy(sourcemap->raw(), __ sourcemap(), __ sourcemapLength());
 21.1456 -    }
 21.1457 -
 21.1458 -    Local<Code> code(zone_);
 21.1459 -
 21.1460 -    code = Code::New(zone_,
 21.1461 -                     bytes,
 21.1462 -                     locals_,
 21.1463 -                     objects,
 21.1464 -                     __ maxStackDepth(),
 21.1465 -                     moduleData_->module,
 21.1466 -                     safepoints,
 21.1467 -                     sourcemap,
 21.1468 -                     lineno);
 21.1469 -    return code;
 21.1470 -}
 21.1471 -
 21.1472 -Function *
 21.1473 -BytecodeCompiler::compileFunction(ModuleData *module, FunctionStatement *node)
 21.1474 -{
 21.1475 -    // Note: No need to record a life slot here, since it's part of the Frame.
 21.1476 -    AutoEnterScope functionScope(this, node->scope());
 21.1477 -
 21.1478 -    // Set the initial line, because line mappings are deltas.
 21.1479 -    __ setFirstLine(node->pos().line);
 21.1480 -    locals_ = FixedArray::New(zone_, node->scope()->maxContainedLocals(), Heap::Tenure_Old);
 21.1481 -
 21.1482 -    node->body()->accept(this);
 21.1483 -
 21.1484 -    unsigned nargs = node->scope()->numArguments();
 21.1485 -    Local<FixedArray> args(zone_, FixedArray::New(zone_, nargs, Heap::Tenure_Old));
 21.1486 -    if (!args)
 21.1487 -        return NULL;
 21.1488 -
 21.1489 -    for (size_t i = 0; i < node->scope()->numArguments(); i++)
 21.1490 -        args->set(zone_, i, node->scope()->getArgument(i)->type());
 21.1491 -
 21.1492 -
 21.1493 -    Local<Code> code(zone_, compileCode(node->scope(), node->pos().line));
 21.1494 -    if (!code)
 21.1495 -        return NULL;
 21.1496 -
 21.1497 -    Local<FunctionType> type(zone_, FunctionType::cast(node->fun()->type()));
 21.1498 -    Local<String> name(zone_, node->fun()->name());
 21.1499 -    Local<Function> fun(zone_, Function::New(zone_, code, type, name, node->pos()));
 21.1500 -    if (!fun)
 21.1501 -        return NULL;
 21.1502 -
 21.1503 -    // If this function had a forward, export it as a named public.
 21.1504 -    if (node->fun()->isPublic()) {
 21.1505 -        assert(node->fun()->isPublic());
 21.1506 -        ScopedRoot<Function> root(fun);
 21.1507 -        if (!root)
 21.1508 -            return NULL;
 21.1509 -        if (!moduleData_->publics.append(root))
 21.1510 -            return NULL;
 21.1511 -    }
 21.1512 -
 21.1513 -#ifndef NDEBUG
 21.1514 -    Disassemble(code, stdout);
 21.1515 -#endif
 21.1516 -    
 21.1517 -    return fun;
 21.1518 -}
 21.1519 -
 21.1520 -Module *
 21.1521 -BytecodeCompiler::compile()
 21.1522 -{
 21.1523 -    AutoEnterScope scope(this, tree_->globalScope());
 21.1524 -
 21.1525 -    ModuleData moduleData;
 21.1526 -
 21.1527 -    moduleData_ = &moduleData;
 21.1528 -    moduleData_->module = Module::New(zone_, tree_->globalScope()->numFunctions());
 21.1529 -
 21.1530 -    if (!moduleData_)
 21.1531 -        return NULL;
 21.1532 -    
 21.1533 -    moduleData_->natives = FixedArray::New(zone_, tree_->globalScope()->numNatives(), Heap::Tenure_Old);
 21.1534 -    if (!moduleData_->natives)
 21.1535 -        return NULL;
 21.1536 -
 21.1537 -    for (size_t i = 0; i < tree_->statements()->length(); i++) {
 21.1538 -        Statement *statement = tree_->statements()->at(i);
 21.1539 -        statement->accept(this);
 21.1540 -    }
 21.1541 -
 21.1542 -    if (zone_->hasPendingException())
 21.1543 -        return NULL;
 21.1544 -
 21.1545 -#ifndef NDEBUG
 21.1546 -    for (size_t i = 0; i < tree_->globalScope()->numFunctions(); i++)
 21.1547 -        assert(moduleData_->module->getFunction(i));
 21.1548 -    for (size_t i = 0; i < tree_->globalScope()->numNatives(); i++)
 21.1549 -        assert(moduleData_->natives->at(i));
 21.1550 -#endif
 21.1551 -
 21.1552 -    if (moduleData_->publics.length()) {
 21.1553 -        Local<Function> fun(zone_);
 21.1554 -        Local<FixedArray> list(zone_, FixedArray::New(zone_, moduleData_->publics.length(),
 21.1555 -                               Heap::Tenure_Old));
 21.1556 -        if (!list)
 21.1557 -            return NULL;
 21.1558 -
 21.1559 -        for (size_t i = 0; i < moduleData_->publics.length(); i++)
 21.1560 -            list->set(zone_, i, moduleData_->publics[i]);
 21.1561 -
 21.1562 -        moduleData_->module->setPublics(list);
 21.1563 -    }
 21.1564 -
 21.1565 -    moduleData_->module->setNatives(moduleData_->natives);
 21.1566 -
 21.1567 -    if (scope_->numEnvironmentVars()) {
 21.1568 -        Local<EnvironmentMap> globalMap(zone_, scope_->createEnvironmentMap(zone_));
 21.1569 -        if (!globalMap)
 21.1570 -            return NULL;
 21.1571 -
 21.1572 -        Local<Environment> environment(zone_, Environment::New(zone_, globalMap));
 21.1573 -        if (!environment)
 21.1574 -            return NULL;
 21.1575 -
 21.1576 -        moduleData_->module->setEnvironment(environment);
 21.1577 -    }
 21.1578 -
 21.1579 -    Local<Code> code(zone_, compileCode(tree_->globalScope(), 1));
 21.1580 -    if (!code)
 21.1581 -        return NULL;
 21.1582 -
 21.1583 -    Disassemble(code, stdout);
 21.1584 -
 21.1585 -    moduleData_->module->setCode(code);
 21.1586 -
 21.1587 -    return moduleData_->module;
 21.1588 -}
 21.1589 +/* vim: set ts=4 sw=4 tw=99 et:
 21.1590 + *
 21.1591 + * Copyright (C) 2012 David Anderson
 21.1592 + *
 21.1593 + * This file is part of JITCraft.
 21.1594 + *
 21.1595 + * JITCraft is free software: you can redistribute it and/or modify it under
 21.1596 + * the terms of the GNU General Public License as published by the Free
 21.1597 + * Software Foundation, either version 3 of the License, or (at your option)
 21.1598 + * any later version.
 21.1599 + * 
 21.1600 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
 21.1601 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 21.1602 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 21.1603 + *
 21.1604 + * You should have received a copy of the GNU General Public License along with
 21.1605 + * JITCraft. If not, see http://www.gnu.org/licenses/.
 21.1606 + */
 21.1607 +#include <string.h>
 21.1608 +#include "../Modules.h"
 21.1609 +#include "../Types.h"
 21.1610 +#include "../Array.h"
 21.1611 +#include "../Strings.h"
 21.1612 +#include "../Zone.h"
 21.1613 +#include "../Environments.h"
 21.1614 +#include "../Box.h"
 21.1615 +#include "../Heap-inl.h"
 21.1616 +#include "BytecodeCompiler.h"
 21.1617 +#include "Scopes.h"
 21.1618 +
 21.1619 +using namespace ke;
 21.1620 +