Added global variable support.
authorDavid Anderson <dvander@alliedmods.net>
Mon Jul 23 01:19:44 2012 -0700 (2012-07-23)
changeset 8506a0015b6a5c
parent 84 eaa43f765cbd
child 86 32ad0523b309
Added global variable support.
jitcraft/API.cpp
jitcraft/Barriers.h
jitcraft/BytecodeCompiler.cpp
jitcraft/BytecodeCompiler.h
jitcraft/BytecodeEmitter.h
jitcraft/Code.h
jitcraft/Environments.cpp
jitcraft/Environments.h
jitcraft/FixedArray.cpp
jitcraft/FixedArray.h
jitcraft/Handles.h
jitcraft/Interpreter.cpp
jitcraft/Modules.cpp
jitcraft/Modules.h
jitcraft/NameBinding.cpp
jitcraft/NameBinding.h
jitcraft/ObjectVisitor.h
jitcraft/Objects.h
jitcraft/Opcodes.cpp
jitcraft/Opcodes.tbl
jitcraft/Parser.cpp
jitcraft/Scopes.cpp
jitcraft/Scopes.h
jitcraft/SemanticAnalysis.cpp
jitcraft/Stack.cpp
jitcraft/Stack.h
jitcraft/Structures.cpp
jitcraft/Structures.h
jitcraft/Vector.h
jitcraft/Zone.cpp
jitcraft/jitcraft.vcxproj
jitcraft/main.cpp
     1.1 --- a/jitcraft/API.cpp	Fri Jul 20 00:03:10 2012 -0700
     1.2 +++ b/jitcraft/API.cpp	Mon Jul 23 01:19:44 2012 -0700
     1.3 @@ -110,7 +110,17 @@
     1.4      Scope::Allocate(tree);
     1.5  
     1.6      BytecodeCompiler compiler(ZONE(), tree, NULL);
     1.7 -    return compiler.compile();
     1.8 +    ke::Local<Module> module(ke::ZONE(), compiler.compile());
     1.9 +    if (!module)
    1.10 +        return NULL;
    1.11 +
    1.12 +    ke::InvokeArgs args;
    1.13 +    if (!ke::ZONE()->stack().pushModuleFrame(module, args))
    1.14 +        return NULL;
    1.15 +    if (!ke::Interpret(ke::ZONE(), NULL, NULL))
    1.16 +        return NULL;
    1.17 +
    1.18 +    return module;
    1.19  }
    1.20  
    1.21  Ke::Local<Ke::Module>
     2.1 --- a/jitcraft/Barriers.h	Fri Jul 20 00:03:10 2012 -0700
     2.2 +++ b/jitcraft/Barriers.h	Mon Jul 23 01:19:44 2012 -0700
     2.3 @@ -78,7 +78,7 @@
     2.4          return *this;
     2.5      }
     2.6      Object **addr() {
     2.7 -        return &obj_;
     2.8 +        return reinterpret_cast<Object **>(&obj_);
     2.9      }
    2.10      operator bool () const {
    2.11          return !!obj_;
     3.1 --- a/jitcraft/BytecodeCompiler.cpp	Fri Jul 20 00:03:10 2012 -0700
     3.2 +++ b/jitcraft/BytecodeCompiler.cpp	Mon Jul 23 01:19:44 2012 -0700
     3.3 @@ -23,6 +23,7 @@
     3.4  #include "Array.h"
     3.5  #include "Strings.h"
     3.6  #include "Zone.h"
     3.7 +#include "Environments.h"
     3.8  #include "Heap-inl.h"
     3.9  
    3.10  using namespace ke;
    3.11 @@ -156,6 +157,8 @@
    3.12          if (var->location() == Variable::STACK) {
    3.13              __ getlocal(var);
    3.14              assert(!name->type()->isReference());
    3.15 +        } else if (var->location() == Variable::ENVIRONMENT) {
    3.16 +            getEnvSlot(var);
    3.17          } else {
    3.18              assert(var->location() == Variable::PARAMETER);
    3.19              __ getarg(var);
    3.20 @@ -697,16 +700,34 @@
    3.21  }
    3.22  
    3.23  void
    3.24 +BytecodeCompiler::getEnvSlot(Variable *var)
    3.25 +{
    3.26 +    assert(var->scope()->kind() == Scope::GLOBAL);
    3.27 +    __ getglobal(var);
    3.28 +}
    3.29 +
    3.30 +void
    3.31 +BytecodeCompiler::setEnvSlot(Variable *var)
    3.32 +{
    3.33 +    assert(var->scope()->kind() == Scope::GLOBAL);
    3.34 +    __ setglobal(var);
    3.35 +}
    3.36 +
    3.37 +void
    3.38  BytecodeCompiler::visit(VariableDeclaration *node)
    3.39  {
    3.40      Variable *var = node->variable();
    3.41 -    assert(var->location() == Variable::STACK);
    3.42      
    3.43      Local<Type> type(zone_, var->type());
    3.44      if (type->isArray()) {
    3.45          Local<ArrayMap> map(zone_, BuildArrayMap(zone_, type));
    3.46          __ note_position(node->pos());
    3.47 -        __ newarray_lifo(map);
    3.48 +        if (var->scope()->kind() == Scope::GLOBAL)
    3.49 +            __ newarray(map, Heap::Tenure_Old);
    3.50 +        else if (var->needsHeapAllocation())
    3.51 +            __ newarray(map, Heap::Tenure_Default);
    3.52 +        else
    3.53 +            __ newarray(map, Heap::Tenure_Stack);
    3.54  
    3.55          if (node->initialization()) {
    3.56              node->initialization()->accept(this);
    3.57 @@ -721,10 +742,16 @@
    3.58                  __ int_(0);
    3.59          }
    3.60      }
    3.61 -    __ setlocal(var);
    3.62 +
    3.63 +    if (var->location() == Variable::STACK) {
    3.64 +        __ setlocal(var);
    3.65 +        locals_->set(zone_, var->slot(), var->type());
    3.66 +    } else {
    3.67 +        assert(var->location() == Variable::ENVIRONMENT);
    3.68 +        setEnvSlot(var);
    3.69 +    }
    3.70 +
    3.71      __ pop();
    3.72 -
    3.73 -    locals_->set(zone_, var->slot(), var->type());
    3.74  }
    3.75  
    3.76  void
    3.77 @@ -875,18 +902,9 @@
    3.78      // :TODO: eventually, we'll export these.
    3.79  }
    3.80  
    3.81 -Function *
    3.82 -BytecodeCompiler::compileFunction(ModuleData *module, FunctionStatement *node)
    3.83 +Code *
    3.84 +BytecodeCompiler::compileCode(Scope *scope, unsigned lineno)
    3.85  {
    3.86 -    // Note: No need to record a life slot here, since it's part of the Frame.
    3.87 -    AutoEnterScope functionScope(this, node->scope());
    3.88 -
    3.89 -    // Set the initial line, because line mappings are deltas.
    3.90 -    __ setFirstLine(node->pos().line);
    3.91 -    locals_ = FixedArray::New(zone_, node->scope()->maxContainedLocals(), Heap::Tenure_Old);
    3.92 -
    3.93 -    node->body()->accept(this);
    3.94 -
    3.95      // STOP doubles as RETURNVOID.
    3.96      __ stop();
    3.97  
    3.98 @@ -898,15 +916,7 @@
    3.99          return NULL;
   3.100      memcpy(bytes->raw(), __ buffer(), __ length());
   3.101  
   3.102 -    unsigned nargs = node->scope()->numArguments();
   3.103 -    Local<FixedArray> args(zone_, FixedArray::New(zone_, nargs, Heap::Tenure_Old));
   3.104 -    if (!args)
   3.105 -        return NULL;
   3.106 -
   3.107 -    for (size_t i = 0; i < node->scope()->numArguments(); i++)
   3.108 -        args->set(zone_, i, node->scope()->getArgument(i)->type());
   3.109 -
   3.110 -    for (size_t i = 0; i < node->scope()->maxContainedLocals(); i++)
   3.111 +    for (size_t i = 0; i < scope->maxContainedLocals(); i++)
   3.112          assert(locals_->at(i));
   3.113  
   3.114      Local<FixedArray> objects(zone_, FixedArray::New(zone_, __ objects()->length(), Heap::Tenure_Old));
   3.115 @@ -965,7 +975,32 @@
   3.116                       moduleData_->module,
   3.117                       safepoints,
   3.118                       sourcemap,
   3.119 -                     node->pos().line);
   3.120 +                     lineno);
   3.121 +    return code;
   3.122 +}
   3.123 +
   3.124 +Function *
   3.125 +BytecodeCompiler::compileFunction(ModuleData *module, FunctionStatement *node)
   3.126 +{
   3.127 +    // Note: No need to record a life slot here, since it's part of the Frame.
   3.128 +    AutoEnterScope functionScope(this, node->scope());
   3.129 +
   3.130 +    // Set the initial line, because line mappings are deltas.
   3.131 +    __ setFirstLine(node->pos().line);
   3.132 +    locals_ = FixedArray::New(zone_, node->scope()->maxContainedLocals(), Heap::Tenure_Old);
   3.133 +
   3.134 +    node->body()->accept(this);
   3.135 +
   3.136 +    unsigned nargs = node->scope()->numArguments();
   3.137 +    Local<FixedArray> args(zone_, FixedArray::New(zone_, nargs, Heap::Tenure_Old));
   3.138 +    if (!args)
   3.139 +        return NULL;
   3.140 +
   3.141 +    for (size_t i = 0; i < node->scope()->numArguments(); i++)
   3.142 +        args->set(zone_, i, node->scope()->getArgument(i)->type());
   3.143 +
   3.144 +
   3.145 +    Local<Code> code(zone_, compileCode(node->scope(), node->pos().line));
   3.146      if (!code)
   3.147          return NULL;
   3.148  
   3.149 @@ -993,6 +1028,8 @@
   3.150  Module *
   3.151  BytecodeCompiler::compile()
   3.152  {
   3.153 +    AutoEnterScope scope(this, tree_->scope());
   3.154 +
   3.155      ModuleData moduleData;
   3.156  
   3.157      moduleData_ = &moduleData;
   3.158 @@ -1035,5 +1072,25 @@
   3.159  
   3.160      moduleData_->module->setNatives(moduleData_->natives);
   3.161  
   3.162 +    if (scope_->numEnvironmentVars()) {
   3.163 +        Local<EnvironmentMap> globalMap(zone_, scope_->createEnvironmentMap(zone_));
   3.164 +        if (!globalMap)
   3.165 +            return NULL;
   3.166 +
   3.167 +        Local<Environment> environment(zone_, Environment::New(zone_, globalMap));
   3.168 +        if (!environment)
   3.169 +            return NULL;
   3.170 +
   3.171 +        moduleData_->module->setEnvironment(environment);
   3.172 +    }
   3.173 +
   3.174 +    Local<Code> code(zone_, compileCode(tree_->scope(), 1));
   3.175 +    if (!code)
   3.176 +        return NULL;
   3.177 +
   3.178 +    Disassemble(code, stdout);
   3.179 +
   3.180 +    moduleData_->module->setCode(code);
   3.181 +
   3.182      return moduleData_->module;
   3.183  }
     4.1 --- a/jitcraft/BytecodeCompiler.h	Fri Jul 20 00:03:10 2012 -0700
     4.2 +++ b/jitcraft/BytecodeCompiler.h	Mon Jul 23 01:19:44 2012 -0700
     4.3 @@ -107,9 +107,13 @@
     4.4                        BytecodeEmitter::Label *trueBranch,
     4.5                        BytecodeEmitter::Label *falseBranch,
     4.6                        BytecodeEmitter::Label *fallthrough);
     4.7 +    Code *compileCode(Scope *scope, unsigned lineno);
     4.8      Function *compileFunction(ModuleData *module, FunctionStatement *fun);
     4.9      void visitForALU(Type *needed, Expression *node);
    4.10  
    4.11 +    void getEnvSlot(Variable *var);
    4.12 +    void setEnvSlot(Variable *var);
    4.13 +
    4.14    public:
    4.15      BytecodeCompiler(Zone *zone, ParseTree *tree, ModuleData *module);
    4.16  
     5.1 --- a/jitcraft/BytecodeEmitter.h	Fri Jul 20 00:03:10 2012 -0700
     5.2 +++ b/jitcraft/BytecodeEmitter.h	Mon Jul 23 01:19:44 2012 -0700
     5.3 @@ -364,6 +364,7 @@
     5.4          writeUint32(index);
     5.5          writeUint32(argc);
     5.6      }
     5.7 +
     5.8      void getarray(PrimitiveType type) {
     5.9          switch (type) {
    5.10            case PrimitiveType_Float:
    5.11 @@ -392,6 +393,43 @@
    5.12              break;
    5.13          }
    5.14      }
    5.15 +
    5.16 +    void getglobal(Variable *var) {
    5.17 +        ensure(OP_GETGLOBAL_F_LENGTH);
    5.18 +        if (var->type()->isPrimitive()) {
    5.19 +            switch (var->type()->primitive()) {
    5.20 +              case PrimitiveType_Float:
    5.21 +                writeOp(OP_GETGLOBAL_F);
    5.22 +                break;
    5.23 +              default:
    5.24 +                assert(var->type()->primitive() == PrimitiveType_Int32);
    5.25 +                writeOp(OP_GETGLOBAL_I);
    5.26 +                break;
    5.27 +            }
    5.28 +        } else {
    5.29 +            writeOp(OP_GETGLOBAL_O);
    5.30 +            markOop(1);
    5.31 +        }
    5.32 +        writeUint32(var->slot());
    5.33 +    }
    5.34 +    void setglobal(Variable *var) {
    5.35 +        ensure(OP_SETGLOBAL_F_LENGTH);
    5.36 +        if (var->type()->isPrimitive()) {
    5.37 +            switch (var->type()->primitive()) {
    5.38 +              case PrimitiveType_Float:
    5.39 +                writeOp(OP_SETGLOBAL_F);
    5.40 +                break;
    5.41 +              default:
    5.42 +                assert(var->type()->primitive() == PrimitiveType_Int32);
    5.43 +                writeOp(OP_SETGLOBAL_I);
    5.44 +                break;
    5.45 +            }
    5.46 +        } else {
    5.47 +            writeOp(OP_SETGLOBAL_O);
    5.48 +        }
    5.49 +        writeUint32(var->slot());
    5.50 +    }
    5.51 +
    5.52      void getarray_o() {
    5.53          singleByteOp(OP_GETARRAY_O);
    5.54          markOop(1);
    5.55 @@ -408,10 +446,11 @@
    5.56      void cvt_i2f() {
    5.57          singleByteOp(OP_CVT_I2F);
    5.58      }
    5.59 -    void newarray_lifo(Handle<Map> map) {
    5.60 +    void newarray(Handle<Map> map, Heap::Tenure tenure) {
    5.61          recordOops();
    5.62 -        ensure(OP_NEWARRAY_LIFO_LENGTH);
    5.63 -        writeOp(OP_NEWARRAY_LIFO);
    5.64 +        ensure(OP_NEWARRAY_LENGTH);
    5.65 +        writeOp(OP_NEWARRAY);
    5.66 +        writeUint8(tenure);
    5.67          writeObject(map);
    5.68          markOop(1);
    5.69      }
     6.1 --- a/jitcraft/Code.h	Fri Jul 20 00:03:10 2012 -0700
     6.2 +++ b/jitcraft/Code.h	Mon Jul 23 01:19:44 2012 -0700
     6.3 @@ -69,7 +69,7 @@
     6.4          return Type::cast(locals_->at(index));
     6.5      }
     6.6      unsigned nlocals() {
     6.7 -        return locals_->length();
     6.8 +        return locals_ ? locals_->length() : 0;
     6.9      }
    6.10      unsigned maxStackDepth() {
    6.11          return maxStackDepth_;
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/jitcraft/Environments.cpp	Mon Jul 23 01:19:44 2012 -0700
     7.3 @@ -0,0 +1,97 @@
     7.4 +/*
     7.5 + * Copyright (C) 2012 David Anderson
     7.6 + *
     7.7 + * This file is part of JITCraft.
     7.8 + *
     7.9 + * JITCraft 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 + * Foobar 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 + * JITCraft. If not, see http://www.gnu.org/licenses/.
    7.20 + */
    7.21 +#include "Utility.h"
    7.22 +#include "Environments.h"
    7.23 +#include "Structures.h"
    7.24 +#include "FixedArray.h"
    7.25 +#include "Zone.h"
    7.26 +#include "NameBinding.h"
    7.27 +
    7.28 +using namespace ke;
    7.29 +
    7.30 +EnvironmentSlotDescriptorArray *
    7.31 +EnvironmentSlotDescriptorArray::New(Zone *zone, unsigned nslots)
    7.32 +{
    7.33 +    size_t bytesNeeded = sizeof(EnvironmentSlotDescriptorArray) +
    7.34 +                         sizeof(EnvironmentSlotDescriptor) * nslots;
    7.35 +
    7.36 +    Local<EnvironmentSlotDescriptorArray> array(zone);
    7.37 +    Local<Map> map(zone, zone->getMap(MapKind_EnvironmentSlotDescriptorArray));
    7.38 +
    7.39 +    array = EnvironmentSlotDescriptorArray::cast(zone->allocate(map, bytesNeeded, Heap::Tenure_Old));
    7.40 +    if (!array)
    7.41 +        return NULL;
    7.42 +
    7.43 +    // We zero the array for safety, since we could GC or fail before initialization.
    7.44 +    array->length_ = nslots;
    7.45 +    memset(array->slots(), 0, sizeof(EnvironmentSlotDescriptor) * nslots);
    7.46 +    return array;
    7.47 +}
    7.48 +
    7.49 +Environment *
    7.50 +Environment::New(Zone *zone, Handle<EnvironmentMap> map, Heap::Tenure tenure)
    7.51 +{
    7.52 +    size_t bytesNeeded = sizeof(Environment) + map->structureSize();
    7.53 +    Local<Environment> env(zone, Environment::cast(zone->allocate(map, bytesNeeded, tenure)));
    7.54 +    if (!env)
    7.55 +        return NULL;
    7.56 +
    7.57 +    // Initialize when called from C++, to make sure object slots are NULL.
    7.58 +    memset((Object *)env + 1, 0, map->structureSize());
    7.59 +    return env;
    7.60 +}
    7.61 +
    7.62 +EnvironmentMap *
    7.63 +EnvironmentMap::New(Zone *zone, unsigned nvars, Variable **vars)
    7.64 +{
    7.65 +    StructureBufferBuilder structure;
    7.66 +
    7.67 +    Local<EnvironmentSlotDescriptorArray> slots(zone);
    7.68 +    slots = EnvironmentSlotDescriptorArray::New(zone, nvars);
    7.69 +    if (!slots)
    7.70 +        return NULL;
    7.71 +
    7.72 +    // Build the descriptor table, mapping each slot to an offset and type.
    7.73 +    Local<Type> type(zone);
    7.74 +    for (unsigned i = 0; i < nvars; i++) {
    7.75 +        assert(vars[i]->slot() == i);
    7.76 +        type = vars[i]->type();
    7.77 +
    7.78 +        EnvironmentSlotDescriptor &desc = slots->slots()[i];
    7.79 +        if (!structure.add(type, &desc.offset))
    7.80 +            return NULL;
    7.81 +
    7.82 +        desc.type = type;
    7.83 +    }
    7.84 +
    7.85 +    // Allocate the actual map now.
    7.86 +    size_t bytesNeeded = sizeof(EnvironmentMap) + structure.traceableOffsetCount() * sizeof(unsigned);
    7.87 +    Local<EnvironmentMap> map(zone);
    7.88 +    
    7.89 +    map = EnvironmentMap::cast(zone->allocateMap(MapKind_Environment, bytesNeeded, MapKind_MetaEnvironment));
    7.90 +    if (!map)
    7.91 +        return NULL;
    7.92 +    
    7.93 +    // Fill in the map fields, and copy the traceable offsets structure.
    7.94 +    map->structureSize_ = structure.structureSize();
    7.95 +    map->traceOffsetCount_ = structure.traceableOffsetCount();
    7.96 +    map->slots_ = slots;
    7.97 +    memcpy(const_cast<unsigned *>(map->traceOffsets()), structure.offsets(), sizeof(unsigned) * structure.traceableOffsetCount());
    7.98 +
    7.99 +    return map;
   7.100 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/jitcraft/Environments.h	Mon Jul 23 01:19:44 2012 -0700
     8.3 @@ -0,0 +1,168 @@
     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 size();
    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 size() {
   8.106 +        return Align(sizeof(*this) + length() * sizeof(EnvironmentSlotDescriptorArray),
   8.107 +                     kObjectAlignment);
   8.108 +    }
   8.109 +
   8.110 +    static inline EnvironmentSlotDescriptorArray *cast(Object *obj) {
   8.111 +        assert(!obj || obj->is(MapKind_EnvironmentSlotDescriptorArray));
   8.112 +        return reinterpret_cast<EnvironmentSlotDescriptorArray *>(obj);
   8.113 +    }
   8.114 +};
   8.115 +
   8.116 +class EnvironmentMap : public Map
   8.117 +{
   8.118 +    unsigned structureSize_;
   8.119 +    unsigned traceOffsetCount_;
   8.120 +    Barriered<EnvironmentSlotDescriptorArray> slots_;
   8.121 +
   8.122 +  public:
   8.123 +    static EnvironmentMap *New(Zone *zone, unsigned nvars, Variable **vars);
   8.124 +
   8.125 +    unsigned structureSize() {
   8.126 +        return structureSize_;
   8.127 +    }
   8.128 +    unsigned traceOffsetCount() {
   8.129 +        return traceOffsetCount_;
   8.130 +    }
   8.131 +    const unsigned *traceOffsets() {
   8.132 +        return reinterpret_cast<unsigned *>(this + 1);
   8.133 +    }
   8.134 +    size_t size() {
   8.135 +        return Align(sizeof(EnvironmentMap) + sizeof(unsigned) * traceOffsetCount(), kObjectAlignment);
   8.136 +    }
   8.137 +    EnvironmentSlotDescriptor &slotDescriptor(unsigned slot) {
   8.138 +        return slots_->at(slot);
   8.139 +    }
   8.140 +
   8.141 +    static inline size_t offsetOfSlots() {
   8.142 +        return offsetof(EnvironmentMap, slots_);
   8.143 +    }
   8.144 +
   8.145 +    static inline EnvironmentMap *cast(Object *obj) {
   8.146 +        assert(!obj || obj->is(MapKind_MetaEnvironment));
   8.147 +        return reinterpret_cast<EnvironmentMap *>(obj);
   8.148 +    }
   8.149 +};
   8.150 +
   8.151 +size_t
   8.152 +Environment::size()
   8.153 +{
   8.154 +    return Align(sizeof(Environment) + map()->structureSize(), kObjectAlignment);
   8.155 +}
   8.156 +
   8.157 +EnvironmentMap *
   8.158 +Environment::map()
   8.159 +{
   8.160 +    return EnvironmentMap::cast(Object::map());
   8.161 +}
   8.162 +
   8.163 +template <typename T> T *
   8.164 +Environment::pointerToSlot(unsigned slot)
   8.165 +{
   8.166 +    return reinterpret_cast<T *>(reinterpret_cast<char *>(this + 1) + map()->slotDescriptor(slot).offset);
   8.167 +}
   8.168 +
   8.169 +}
   8.170 +
   8.171 +#endif // _include_ke_environment_h_
     9.1 --- a/jitcraft/FixedArray.cpp	Fri Jul 20 00:03:10 2012 -0700
     9.2 +++ b/jitcraft/FixedArray.cpp	Mon Jul 23 01:19:44 2012 -0700
     9.3 @@ -44,7 +44,6 @@
     9.4  ByteArray *
     9.5  ByteArray::New(Zone *zone, unsigned length, Heap::Tenure tenure)
     9.6  {
     9.7 -    // :TODO: error...
     9.8      if (length >= kMaxFixedArrayLength) {
     9.9          zone->reportError(Message_ArrayTooBig);
    9.10          return NULL;
    9.11 @@ -59,3 +58,19 @@
    9.12      return array;
    9.13  }
    9.14  
    9.15 +ByteArray *
    9.16 +ByteArray::New(Zone *zone, Handle<Map> map, unsigned length, Heap::Tenure tenure)
    9.17 +{
    9.18 +    if (length >= kMaxFixedArrayLength) {
    9.19 +        zone->reportError(Message_ArrayTooBig);
    9.20 +        return NULL;
    9.21 +    }
    9.22 +
    9.23 +    Local<ByteArray> array(zone, ByteArray::cast(zone->allocate(map, SizeFor(length), tenure)));
    9.24 +    if (!array)
    9.25 +        return NULL;
    9.26 +
    9.27 +    array->length_ = length;
    9.28 +    memset(array->raw(), 0, length);
    9.29 +    return array;
    9.30 +}
    10.1 --- a/jitcraft/FixedArray.h	Fri Jul 20 00:03:10 2012 -0700
    10.2 +++ b/jitcraft/FixedArray.h	Mon Jul 23 01:19:44 2012 -0700
    10.3 @@ -65,6 +65,7 @@
    10.4  
    10.5    public:
    10.6      static ByteArray *New(Zone *zone, unsigned length, Heap::Tenure tenure = Heap::Tenure_Default);
    10.7 +    static ByteArray *New(Zone *zone, Handle<Map> map, unsigned length, Heap::Tenure tenure = Heap::Tenure_Default);
    10.8  
    10.9      unsigned length() {
   10.10          return length_;
    11.1 --- a/jitcraft/Handles.h	Fri Jul 20 00:03:10 2012 -0700
    11.2 +++ b/jitcraft/Handles.h	Mon Jul 23 01:19:44 2012 -0700
    11.3 @@ -19,6 +19,8 @@
    11.4  #ifndef _include_jitcraft_rooting_h_
    11.5  #define _include_jitcraft_rooting_h_
    11.6  
    11.7 +#include <stdlib.h>
    11.8 +
    11.9  namespace ke {
   11.10  
   11.11  class Zone;
   11.12 @@ -67,7 +69,7 @@
   11.13    private:
   11.14      template <typename S>
   11.15      void typeCheck() {
   11.16 -#ifdef DEBUG
   11.17 +#ifndef NDEBUG
   11.18          T *v1 = NULL;
   11.19          S *v2 = NULL;
   11.20          v1 = v2;
    12.1 --- a/jitcraft/Interpreter.cpp	Fri Jul 20 00:03:10 2012 -0700
    12.2 +++ b/jitcraft/Interpreter.cpp	Mon Jul 23 01:19:44 2012 -0700
    12.3 @@ -23,6 +23,7 @@
    12.4  #include "Array.h"
    12.5  #include "Reference.h"
    12.6  #include "Strings.h"
    12.7 +#include "Environments.h"
    12.8  #include "Heap-inl.h"
    12.9  
   12.10  using namespace ke;
   12.11 @@ -80,11 +81,11 @@
   12.12  
   12.13  // Generate an array with completely static sizes.
   12.14  static Array *
   12.15 -GenerateArray(Zone *zone, Handle<ArrayMap> map)
   12.16 +GenerateArray(Zone *zone, Handle<ArrayMap> map, Heap::Tenure tenure)
   12.17  {
   12.18      assert(map->type()->elements() != -1);
   12.19  
   12.20 -    Local<Array> array(zone, Array::New(zone, map, map->type()->elements(), Heap::Tenure_Stack));
   12.21 +    Local<Array> array(zone, Array::New(zone, map, map->type()->elements(), tenure));
   12.22      if (!array)
   12.23          return NULL;
   12.24  
   12.25 @@ -94,7 +95,7 @@
   12.26      Local<ArrayMap> contained(zone, map->contained());
   12.27      Local<Array> sub(zone);
   12.28      for (unsigned i = 0; i < unsigned(map->type()->elements()); i++) {
   12.29 -        sub = GenerateArray(zone, contained);
   12.30 +        sub = GenerateArray(zone, contained, tenure);
   12.31          if (!sub)
   12.32              return NULL;
   12.33          array->writeObject(zone, i, sub);
   12.34 @@ -685,10 +686,11 @@
   12.35      break;
   12.36  }
   12.37  
   12.38 -case OP_NEWARRAY_LIFO:
   12.39 +case OP_NEWARRAY:
   12.40  {
   12.41 -    Local<ArrayMap> map(zone, ArrayMap::cast(top.fp->code()->map(READ_UINT32(top.pc))));
   12.42 -    Array *array = GenerateArray(zone, map);
   12.43 +    Heap::Tenure tenure = (Heap::Tenure)top.pc[1];
   12.44 +    Local<ArrayMap> map(zone, ArrayMap::cast(top.fp->code()->map(READ_UINT32(top.pc + 1))));
   12.45 +    Array *array = GenerateArray(zone, map, tenure);
   12.46      if (!array)
   12.47          goto error;
   12.48      top.sp->obj = array;
   12.49 @@ -870,6 +872,51 @@
   12.50      break;
   12.51  }
   12.52  
   12.53 +case OP_GETGLOBAL_I:
   12.54 +{
   12.55 +    unsigned slot = READ_UINT32(top.pc);
   12.56 +    top.sp++;
   12.57 +    top.sp[-1].i32 = top.fp->code()->module()->environment()->getInt32(slot);
   12.58 +    break;
   12.59 +}
   12.60 +
   12.61 +case OP_GETGLOBAL_F:
   12.62 +{
   12.63 +    unsigned slot = READ_UINT32(top.pc);
   12.64 +    top.sp++;
   12.65 +    top.sp[-1].f = top.fp->code()->module()->environment()->getFloat(slot);
   12.66 +    break;
   12.67 +}
   12.68 +
   12.69 +case OP_GETGLOBAL_O:
   12.70 +{
   12.71 +    unsigned slot = READ_UINT32(top.pc);
   12.72 +    top.sp++;
   12.73 +    top.sp[-1].obj = top.fp->code()->module()->environment()->getObject(slot);
   12.74 +    break;
   12.75 +}
   12.76 +
   12.77 +case OP_SETGLOBAL_I:
   12.78 +{
   12.79 +    unsigned slot = READ_UINT32(top.pc);
   12.80 +    top.fp->code()->module()->environment()->setInt32(slot, top.sp[-1].i32);
   12.81 +    break;
   12.82 +}
   12.83 +
   12.84 +case OP_SETGLOBAL_F:
   12.85 +{
   12.86 +    unsigned slot = READ_UINT32(top.pc);
   12.87 +    top.fp->code()->module()->environment()->setFloat(slot, top.sp[-1].f);
   12.88 +    break;
   12.89 +}
   12.90 +
   12.91 +case OP_SETGLOBAL_O:
   12.92 +{
   12.93 +    unsigned slot = READ_UINT32(top.pc);
   12.94 +    top.fp->code()->module()->environment()->setObject(slot, top.sp[-1].obj);
   12.95 +    break;
   12.96 +}
   12.97 +
   12.98  default:
   12.99      assert(false);
  12.100      return false;
    13.1 --- a/jitcraft/Modules.cpp	Fri Jul 20 00:03:10 2012 -0700
    13.2 +++ b/jitcraft/Modules.cpp	Mon Jul 23 01:19:44 2012 -0700
    13.3 @@ -37,6 +37,7 @@
    13.4      module->file_ = NULL;
    13.5      module->publics_ = NULL;
    13.6      module->natives_ = NULL;
    13.7 +    module->environment_ = NULL;
    13.8      module->nativeIdentity_ = NULL;
    13.9      return module;
   13.10  }
    14.1 --- a/jitcraft/Modules.h	Fri Jul 20 00:03:10 2012 -0700
    14.2 +++ b/jitcraft/Modules.h	Mon Jul 23 01:19:44 2012 -0700
    14.3 @@ -24,12 +24,16 @@
    14.4  
    14.5  namespace ke {
    14.6  
    14.7 +class Environment;
    14.8 +
    14.9  class Module : public Object
   14.10  {
   14.11      Barriered<FixedArray> functions_;
   14.12      Barriered<FixedArray> publics_;
   14.13      Barriered<FixedArray> natives_;
   14.14      Barriered<String> file_;
   14.15 +    Barriered<Environment> environment_;
   14.16 +    Barriered<Code> code_;
   14.17      void *nativeIdentity_;
   14.18  
   14.19    public:
   14.20 @@ -53,6 +57,12 @@
   14.21      String *file() {
   14.22          return file_;
   14.23      }
   14.24 +    Environment *environment() {
   14.25 +        return environment_;
   14.26 +    }
   14.27 +    Code *code() {
   14.28 +        return code_;
   14.29 +    }
   14.30  
   14.31      void setPublics(Handle<FixedArray> publics) {
   14.32          publics_ = publics;
   14.33 @@ -63,6 +73,12 @@
   14.34      void setPath(Handle<String> path) {
   14.35          file_ = path;
   14.36      }
   14.37 +    void setEnvironment(Handle<Environment> environment) {
   14.38 +        environment_ = environment;
   14.39 +    }
   14.40 +    void setCode(Handle<Code> code) {
   14.41 +        code_ = code;
   14.42 +    }
   14.43  
   14.44      void *nativeIdentity() {
   14.45          return nativeIdentity_;
   14.46 @@ -84,6 +100,12 @@
   14.47      static inline size_t offsetOfFile() {
   14.48          return offsetof(Module, file_);
   14.49      }
   14.50 +    static inline size_t offsetOfEnvironment() {
   14.51 +        return offsetof(Module, environment_);
   14.52 +    }
   14.53 +    static inline size_t offsetOfCode() {
   14.54 +        return offsetof(Module, code_);
   14.55 +    }
   14.56      // End GC Descriptor.
   14.57  
   14.58      static inline Module *cast(Object *obj) {
    15.1 --- a/jitcraft/NameBinding.cpp	Fri Jul 20 00:03:10 2012 -0700
    15.2 +++ b/jitcraft/NameBinding.cpp	Mon Jul 23 01:19:44 2012 -0700
    15.3 @@ -18,6 +18,7 @@
    15.4  #include "NameBinding.h"
    15.5  #include "Strings.h"
    15.6  #include "Zone.h"
    15.7 +#include "Scopes.h"
    15.8  
    15.9  using namespace ke;
   15.10  
   15.11 @@ -42,3 +43,9 @@
   15.12      location_(UNALLOCATED)
   15.13  {
   15.14  }
   15.15 +
   15.16 +bool
   15.17 +Variable::needsHeapAllocation()
   15.18 +{
   15.19 +    return scope()->kind() == Scope::GLOBAL;
   15.20 +}
    16.1 --- a/jitcraft/NameBinding.h	Fri Jul 20 00:03:10 2012 -0700
    16.2 +++ b/jitcraft/NameBinding.h	Mon Jul 23 01:19:44 2012 -0700
    16.3 @@ -176,7 +176,8 @@
    16.4      enum Location {
    16.5          UNALLOCATED,
    16.6          STACK,
    16.7 -        PARAMETER
    16.8 +        PARAMETER,
    16.9 +        ENVIRONMENT
   16.10      };
   16.11  
   16.12      Variable(Scope *scope, Handle<String> name, const SourcePosition &pos);
   16.13 @@ -198,6 +199,7 @@
   16.14          assert(!unallocated());
   16.15          return slot_;
   16.16      }
   16.17 +    bool needsHeapAllocation();
   16.18  
   16.19    private:
   16.20      Location location_;
    17.1 --- a/jitcraft/ObjectVisitor.h	Fri Jul 20 00:03:10 2012 -0700
    17.2 +++ b/jitcraft/ObjectVisitor.h	Mon Jul 23 01:19:44 2012 -0700
    17.3 @@ -28,6 +28,7 @@
    17.4  #include "Functions.h"
    17.5  #include "Array.h"
    17.6  #include "Strings.h"
    17.7 +#include "Environments.h"
    17.8  
    17.9  namespace ke {
   17.10  
   17.11 @@ -82,6 +83,8 @@
   17.12          visitField(obj, Module::offsetOfPublics());
   17.13          visitField(obj, Module::offsetOfNatives());
   17.14          visitField(obj, Module::offsetOfFile());
   17.15 +        visitField(obj, Module::offsetOfEnvironment());
   17.16 +        visitField(obj, Module::offsetOfCode());
   17.17          return sizeof(Module);
   17.18      }
   17.19  
   17.20 @@ -119,6 +122,28 @@
   17.21          return sizeof(ArrayMap);
   17.22      }
   17.23  
   17.24 +    size_t iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray *env) {
   17.25 +        unsigned length = env->length();
   17.26 +        EnvironmentSlotDescriptor *desc = env->slots();
   17.27 +        for (unsigned i = 0; i < length; i++)
   17.28 +            this->visit(desc->type.addr());
   17.29 +        return env->size();
   17.30 +    }
   17.31 +
   17.32 +    size_t iterateEnvironmentMap(EnvironmentMap *map) {
   17.33 +        visitField(map, EnvironmentMap::offsetOfSlots());
   17.34 +        return map->size();
   17.35 +    }
   17.36 +
   17.37 +    size_t iterateEnvironment(Environment *env) {
   17.38 +        EnvironmentMap *map = env->map();
   17.39 +        const unsigned *offsets = map->traceOffsets();
   17.40 +        unsigned noffsets = map->traceOffsetCount();
   17.41 +        for (unsigned i = 0; i < noffsets; i++)
   17.42 +            visitField(env, Environment::offsetOfSlotOffset(offsets[i]));
   17.43 +        return env->size();
   17.44 +    }
   17.45 +
   17.46    public:
   17.47      size_t iterate(Object *obj) {
   17.48          visitField(obj, Object::offsetOfMap());
   17.49 @@ -154,12 +179,21 @@
   17.50            case MapKind_Array:
   17.51              return Align(iterateArray(Array::cast(obj), ArrayMap::cast(map)), kObjectAlignment);
   17.52  
   17.53 +          case MapKind_EnvironmentSlotDescriptorArray:
   17.54 +            return iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray::cast(obj));
   17.55 +
   17.56 +          case MapKind_Environment:
   17.57 +            return iterateEnvironment(Environment::cast(obj));
   17.58 +
   17.59            case MapKind_Native:
   17.60              return iterateNative(obj);
   17.61  
   17.62            case MapKind_MetaArray:
   17.63              return iterateArrayMap(ArrayMap::cast(obj));
   17.64  
   17.65 +          case MapKind_MetaEnvironment:
   17.66 +            return iterateEnvironmentMap(EnvironmentMap::cast(obj));
   17.67 +
   17.68            default:
   17.69              assert(map->kind() == MapKind_Meta);
   17.70              return sizeof(Map);
   17.71 @@ -201,9 +235,18 @@
   17.72        case MapKind_Array:
   17.73          return Align(Array::SizeOf(Array::cast(obj)), kObjectAlignment);
   17.74  
   17.75 +      case MapKind_EnvironmentSlotDescriptorArray:
   17.76 +        return EnvironmentSlotDescriptorArray::cast(obj)->size();
   17.77 +
   17.78 +      case MapKind_Environment:
   17.79 +        return Environment::cast(obj)->size();
   17.80 +
   17.81        case MapKind_MetaArray:
   17.82          return sizeof(ArrayMap);
   17.83  
   17.84 +      case MapKind_MetaEnvironment:
   17.85 +        return EnvironmentMap::cast(obj)->size();
   17.86 +
   17.87        case MapKind_FreeRegion:
   17.88          return *reinterpret_cast<size_t *>(reinterpret_cast<Address>(obj + 1));
   17.89  
    18.1 --- a/jitcraft/Objects.h	Fri Jul 20 00:03:10 2012 -0700
    18.2 +++ b/jitcraft/Objects.h	Mon Jul 23 01:19:44 2012 -0700
    18.3 @@ -48,14 +48,17 @@
    18.4      MapKind_String,
    18.5      MapKind_Native,
    18.6      MapKind_FreeRegion,     // Special map denoting freed space.
    18.7 +    MapKind_EnvironmentSlotDescriptorArray,
    18.8 +    MapKind_Environment,
    18.9  
   18.10      // Used to represent Arrays. This does not have a canonical map.
   18.11      MapKind_Array,
   18.12  
   18.13      // These represent special Map subclasses that require special tracing.
   18.14      MapKinds_Special,
   18.15 -    MapKind_Meta,           // (default map class)
   18.16 -    MapKind_MetaArray,      // ArrayMap instances
   18.17 +    MapKind_Meta,               // (default map class)
   18.18 +    MapKind_MetaArray,          // ArrayMap instances
   18.19 +    MapKind_MetaEnvironment,    // EnvironmentMap instances
   18.20      MapKinds_EndSpecial,
   18.21  
   18.22      MapKinds_Total
    19.1 --- a/jitcraft/Opcodes.cpp	Fri Jul 20 00:03:10 2012 -0700
    19.2 +++ b/jitcraft/Opcodes.cpp	Mon Jul 23 01:19:44 2012 -0700
    19.3 @@ -76,7 +76,7 @@
    19.4      // any other position indicates a failure to mark that position as a
    19.5      // safepoint, which is a bug.
    19.6      Opcode op = Opcode(*(start() + pcOffset));
    19.7 -    assert(op == OP_CALL || op == OP_NEWARRAY_LIFO || op == OP_VARREF_LIFO ||
    19.8 +    assert(op == OP_CALL || op == OP_NEWARRAY || op == OP_VARREF_LIFO ||
    19.9             op == OP_ARGREF_LIFO || op == OP_SLOTREF_LIFO || op == OP_ARRAYREF_LIFO ||
   19.10             op == OP_ARRAYCOPY);
   19.11  
   19.12 @@ -238,9 +238,10 @@
   19.13              fprintf(fp, "%u (%+d)", unsigned((pc + READ_INT32(pc)) - code->start()), READ_INT32(pc));
   19.14              break;
   19.15  
   19.16 -          case OP_NEWARRAY_LIFO:
   19.17 +          case OP_NEWARRAY:
   19.18            {
   19.19 -            ArrayMap *map = ArrayMap::cast(code->map(READ_UINT32(pc)));
   19.20 +            Heap::Tenure tenure = (Heap::Tenure)pc[1];
   19.21 +            ArrayMap *map = ArrayMap::cast(code->map(READ_UINT32(pc + 1)));
   19.22              fprintf(fp, "%s:", map->type()->innermost()->tag()
   19.23                                 ? map->type()->innermost()->tag()->chars()
   19.24                                 : "_");
   19.25 @@ -248,6 +249,10 @@
   19.26                  Type *type = map->type();
   19.27                  fprintf(fp, "[%d]", type->elements());
   19.28              }
   19.29 +            if (tenure == Heap::Tenure_Stack)
   19.30 +                fprintf(fp, " ; lifo");
   19.31 +            else if (tenure == Heap::Tenure_Old)
   19.32 +                fprintf(fp, " ; pretenured");
   19.33              break;
   19.34            }
   19.35  
   19.36 @@ -261,6 +266,12 @@
   19.37            case OP_ARGREF_LIFO:
   19.38            case OP_OBJECT:
   19.39            case OP_GETMODULE_FN:
   19.40 +          case OP_GETGLOBAL_I:
   19.41 +          case OP_GETGLOBAL_F:
   19.42 +          case OP_GETGLOBAL_O:
   19.43 +          case OP_SETGLOBAL_I:
   19.44 +          case OP_SETGLOBAL_F:
   19.45 +          case OP_SETGLOBAL_O:
   19.46              fprintf(fp, "%u", READ_UINT32(pc));
   19.47              break;
   19.48  
    20.1 --- a/jitcraft/Opcodes.tbl	Fri Jul 20 00:03:10 2012 -0700
    20.2 +++ b/jitcraft/Opcodes.tbl	Mon Jul 23 01:19:44 2012 -0700
    20.3 @@ -116,12 +116,12 @@
    20.4  OPDEF(OP_SETARRAY_C,    45,         "setarray.c",   1,      3,  1)
    20.5  OPDEF(OP_GETARRAY_O,    46,         "getarray.o",   1,      2,  1)
    20.6  
    20.7 -// Allocate an array, info LIFO space if possible. The ArrayMap to use is
    20.8 -// specified as an index into the script's Map table.
    20.9 +// Allocate an array. The HeapTenure is stored as a byte following pc. The
   20.10 +// ArrayMap to use is specified as an index into the script's Map table.
   20.11  //
   20.12  // Format:
   20.13  //  [u8 op] [u32 index]
   20.14 -OPDEF(OP_NEWARRAY_LIFO, 47,         "newarray.lifo", 5,     0,  1)
   20.15 +OPDEF(OP_NEWARRAY,      47,         "newarray",     6,      0,  1)
   20.16  
   20.17  // Performs a bounds check on an unsafe array.
   20.18  //
   20.19 @@ -236,3 +236,11 @@
   20.20  // Loads a function from a module object. The operand is the slot number
   20.21  // in the module.
   20.22  OPDEF(OP_GETMODULE_FN,  92,         "getmodule.fn", 5,      1, 1)
   20.23 +
   20.24 +// Opcodes for accessing an environment slot in the global scope.
   20.25 +OPDEF(OP_SETGLOBAL_I,   93,         "setglobal.i",  5,      1, 1)
   20.26 +OPDEF(OP_SETGLOBAL_F,   94,         "setglobal.f",  5,      1, 1)
   20.27 +OPDEF(OP_SETGLOBAL_O,   95,         "setglobal.o",  5,      1, 1)
   20.28 +OPDEF(OP_GETGLOBAL_I,   96,         "getglobal.i",  5,      0, 1)
   20.29 +OPDEF(OP_GETGLOBAL_F,   97,         "getglobal.f",  5,      0, 1)
   20.30 +OPDEF(OP_GETGLOBAL_O,   98,         "getglobal.o",  5,      0, 1)
   20.31 \ No newline at end of file
    21.1 --- a/jitcraft/Parser.cpp	Fri Jul 20 00:03:10 2012 -0700
    21.2 +++ b/jitcraft/Parser.cpp	Mon Jul 23 01:19:44 2012 -0700
    21.3 @@ -1076,14 +1076,14 @@
    21.4              break;
    21.5            }
    21.6  
    21.7 -          // case TOK_NEW:
    21.8 -          // {
    21.9 -          //   if ((statement = variableDeclaration()) == NULL)
   21.10 -          //      return NULL;
   21.11 -          //   if (!matchSemicolon())
   21.12 -          //       return NULL;
   21.13 -          //   break;
   21.14 -          // }
   21.15 +          case TOK_NEW:
   21.16 +          {
   21.17 +            if ((statement = variableDeclaration()) == NULL)
   21.18 +               return NULL;
   21.19 +            if (!matchSemicolon())
   21.20 +                return NULL;
   21.21 +            break;
   21.22 +          }
   21.23  
   21.24            case TOK_ENUM:
   21.25              if ((statement = enum_()) == NULL)
    22.1 --- a/jitcraft/Scopes.cpp	Fri Jul 20 00:03:10 2012 -0700
    22.2 +++ b/jitcraft/Scopes.cpp	Mon Jul 23 01:19:44 2012 -0700
    22.3 @@ -22,6 +22,7 @@
    22.4  #include "TypeManager.h"
    22.5  #include "Strings.h"
    22.6  #include "CompileContext.h"
    22.7 +#include "Environments.h"
    22.8  
    22.9  using namespace ke;
   22.10  
   22.11 @@ -152,6 +153,7 @@
   22.12          children_[i]->allocate();
   22.13      }
   22.14  
   22.15 +    Local<Type> type(ZONE());
   22.16      for (size_t i = 0; i < names_.length(); i++) {
   22.17          BoundName *name = names_[i];
   22.18          
   22.19 @@ -161,6 +163,8 @@
   22.20                  fun->allocate(numNatives_++);
   22.21              else
   22.22                  fun->allocate(numFunctions_++);
   22.23 +        } else if (name->kind() == BoundName::VARIABLE) {
   22.24 +            allocate(name->toVariable());
   22.25          }
   22.26      }
   22.27  }
   22.28 @@ -171,8 +175,13 @@
   22.29      if (!var->unallocated())
   22.30          return;
   22.31  
   22.32 -    var->allocate(Variable::STACK, maxContainedLocals_ + locals_);
   22.33 -    locals_++;
   22.34 +    if (kind() == GLOBAL) {
   22.35 +        var->allocate(Variable::ENVIRONMENT, envVars_.length());
   22.36 +        envVars_.append(var);
   22.37 +    } else {
   22.38 +        var->allocate(Variable::STACK, maxContainedLocals_ + locals_);
   22.39 +        locals_++;
   22.40 +    }
   22.41  }
   22.42  
   22.43  void
   22.44 @@ -256,3 +265,9 @@
   22.45      lifoSlot_ = new (pool_) Variable(this, name, SourcePosition());
   22.46      lifoSlot_->setType(type);
   22.47  }
   22.48 +
   22.49 +EnvironmentMap *
   22.50 +Scope::createEnvironmentMap(Zone *zone)
   22.51 +{
   22.52 +    return EnvironmentMap::New(zone, envVars_.length(), envVars_.buffer());
   22.53 +}
    23.1 --- a/jitcraft/Scopes.h	Fri Jul 20 00:03:10 2012 -0700
    23.2 +++ b/jitcraft/Scopes.h	Mon Jul 23 01:19:44 2012 -0700
    23.3 @@ -21,10 +21,12 @@
    23.4  #include "PoolAllocator.h"
    23.5  #include "AST.h"
    23.6  #include "NameBinding.h"
    23.7 +#include "Structures.h"
    23.8  
    23.9  namespace ke {
   23.10  
   23.11  class CompileContext;
   23.12 +class EnvironmentMap;
   23.13  
   23.14  class Scope : public PoolObject
   23.15  {
   23.16 @@ -36,6 +38,7 @@
   23.17      unsigned maxContainedLocals_;
   23.18      unsigned numFunctions_;
   23.19      unsigned numNatives_;
   23.20 +    PoolList<Variable *> envVars_;
   23.21      Variable *lifoSlot_;
   23.22      
   23.23      bool empty() const {
   23.24 @@ -75,6 +78,9 @@
   23.25      unsigned numArguments() const {
   23.26          return parameters_.length();
   23.27      }
   23.28 +    unsigned numEnvironmentVars() const {
   23.29 +        return envVars_.length();
   23.30 +    }
   23.31      Variable *getArgument(size_t index) {
   23.32          return parameters_[index];
   23.33      }
   23.34 @@ -93,6 +99,8 @@
   23.35      NamedEnum *declareEnum(Handle<String> name, const SourcePosition &pos);
   23.36      NamedConstant *declareConstant(Handle<String> name, const SourcePosition &pos);
   23.37  
   23.38 +    EnvironmentMap *createEnvironmentMap(Zone *zone);
   23.39 +
   23.40      void allocate(Variable *var);
   23.41      void allocate();
   23.42      void allocateGlobals();
    24.1 --- a/jitcraft/SemanticAnalysis.cpp	Fri Jul 20 00:03:10 2012 -0700
    24.2 +++ b/jitcraft/SemanticAnalysis.cpp	Mon Jul 23 01:19:44 2012 -0700
    24.3 @@ -21,6 +21,7 @@
    24.4  #include "Zone.h"
    24.5  #include "TypeManager.h"
    24.6  #include "Scopes.h"
    24.7 +#include "NameBinding.h"
    24.8  #include "Heap-inl.h"
    24.9  #include "Strings.h"
   24.10  
   24.11 @@ -111,6 +112,8 @@
   24.12      if (cc_.failures())
   24.13          return false;
   24.14  
   24.15 +    scope_ = tree_->scope();
   24.16 +
   24.17      for (size_t i = 0; i < tree_->statements()->length(); i++) {
   24.18          Statement *statement = tree_->statements()->at(i);
   24.19          if (statement->isFunctionStatement()) {
   24.20 @@ -609,10 +612,11 @@
   24.21                  check = check->contained();
   24.22          }
   24.23  
   24.24 -        // Right now, any array is allowed on the LIFO heap. In case the
   24.25 -        // runtime actually decides to use the LIFO heap, we must reserve
   24.26 -        // a slot so we can unwind the heap when the current scope leaves.
   24.27 -        scope_->setUsesLifoHeap();
   24.28 +        // If this variable is stack allocated, we could use the LIFO heap
   24.29 +        // to allocate it. If that's the case, make sure to reserve a slot
   24.30 +        // so we can unwind the LIFO heap at the end of this scope.
   24.31 +        if (!node->variable()->needsHeapAllocation())
   24.32 +            scope_->setUsesLifoHeap();
   24.33      } else {
   24.34          if (node->initialization()) {
   24.35              Local<Type> right(zone_, visitForLoad(node->initialization()));
   24.36 @@ -850,7 +854,7 @@
   24.37      if (given->primitive() != actual->primitive()) {
   24.38          // :TODO: leaks an interior pointer
   24.39          const char *givenTag = given->tag() ? given->tag()->chars() : "_";
   24.40 -        const char *actualTag = given->tag() ? given->tag()->chars() : "_";
   24.41 +        const char *actualTag = actual->tag() ? actual->tag()->chars() : "_";
   24.42          cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
   24.43          return false;
   24.44      }
    25.1 --- a/jitcraft/Stack.cpp	Fri Jul 20 00:03:10 2012 -0700
    25.2 +++ b/jitcraft/Stack.cpp	Mon Jul 23 01:19:44 2012 -0700
    25.3 @@ -95,6 +95,29 @@
    25.4  }
    25.5  
    25.6  bool
    25.7 +Stack::pushModuleFrame(Handle<Module> module, InvokeArgs &args)
    25.8 +{
    25.9 +    size_t nbytes = SizeForCodeFrame(module->code());
   25.10 +    if (reinterpret_cast<char *>(top_.sp) + nbytes >= end_) {
   25.11 +        assert(false);
   25.12 +        return false;
   25.13 +    }
   25.14 +
   25.15 +    args.args_ = top_.sp;
   25.16 +    args.nargs_ = 0;
   25.17 +    args.stack_ = this;
   25.18 +    
   25.19 +    Frame *frame = reinterpret_cast<Frame *>(top_.sp);
   25.20 +    new (frame) Frame(top_.fp, top_.pc, NULL, module->code(), zone_->heap().lifoPosition());
   25.21 +    
   25.22 +    top_.pc = frame->code()->start();
   25.23 +    top_.sp = frame->stackBase();
   25.24 +    top_.fp = frame;
   25.25 +
   25.26 +    return true;
   25.27 +}
   25.28 +
   25.29 +bool
   25.30  Stack::pushNativeFrame(Handle<Native> native, NativeArgs &args, unsigned argc)
   25.31  {
   25.32      size_t nbytes = sizeof(intptr_t) * argc + sizeof(Frame);
    26.1 --- a/jitcraft/Stack.h	Fri Jul 20 00:03:10 2012 -0700
    26.2 +++ b/jitcraft/Stack.h	Mon Jul 23 01:19:44 2012 -0700
    26.3 @@ -193,6 +193,7 @@
    26.4      Frame *popInlineFrame();
    26.5  
    26.6      bool pushInvokeFrame(Handle<Function> fun, InvokeArgs &args);
    26.7 +    bool pushModuleFrame(Handle<Module> module, InvokeArgs &args);
    26.8      bool pushNativeFrame(Handle<Native> native, NativeArgs &args, unsigned argc);
    26.9  
   26.10      Top *top() {
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/jitcraft/Structures.cpp	Mon Jul 23 01:19:44 2012 -0700
    27.3 @@ -0,0 +1,46 @@
    27.4 +/* vim: set ts=4 sw=4 tw=99 et
    27.5 + *
    27.6 + * Copyright (C) 2012 David Anderson
    27.7 + *
    27.8 + * This file is part of JITCraft.
    27.9 + *
   27.10 + * JITCraft is free software: you can redistribute it and/or modify it under
   27.11 + * the terms of the GNU General Public License as published by the Free
   27.12 + * Software Foundation, either version 3 of the License, or (at your option)
   27.13 + * any later version.
   27.14 + * 
   27.15 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
   27.16 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   27.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   27.18 + *
   27.19 + * You should have received a copy of the GNU General Public License along with
   27.20 + * JITCraft. If not, see http://www.gnu.org/licenses/.
   27.21 + */
   27.22 +#include "Structures.h"
   27.23 +#include "Types.h"
   27.24 +
   27.25 +using namespace ke;
   27.26 +
   27.27 +StructureBufferBuilder::StructureBufferBuilder()
   27.28 +  : size_(0)
   27.29 +{
   27.30 +}
   27.31 +
   27.32 +bool
   27.33 +StructureBufferBuilder::add(Handle<Type> type, unsigned *offset)
   27.34 +{
   27.35 +    *offset = size_;
   27.36 +
   27.37 +    if (!type->isTraceable()) {
   27.38 +        // For now, assume the size of primitives is 4-byte.
   27.39 +        assert(type->isInt32() || type->isFloat());
   27.40 +        size_ += 4;
   27.41 +        return true;
   27.42 +    }
   27.43 +
   27.44 +    if (!offsets_.append(size_))
   27.45 +        return false;
   27.46 +
   27.47 +    size_ += sizeof(Object *);
   27.48 +    return true;
   27.49 +}
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/jitcraft/Structures.h	Mon Jul 23 01:19:44 2012 -0700
    28.3 @@ -0,0 +1,60 @@
    28.4 +/* vim: set ts=4 sw=4 tw=99 et
    28.5 + *
    28.6 + * Copyright (C) 2012 David Anderson
    28.7 + *
    28.8 + * This file is part of JITCraft.
    28.9 + *
   28.10 + * JITCraft is free software: you can redistribute it and/or modify it under
   28.11 + * the terms of the GNU General Public License as published by the Free
   28.12 + * Software Foundation, either version 3 of the License, or (at your option)
   28.13 + * any later version.
   28.14 + * 
   28.15 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
   28.16 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   28.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   28.18 + *
   28.19 + * You should have received a copy of the GNU General Public License along with
   28.20 + * JITCraft. If not, see http://www.gnu.org/licenses/.
   28.21 + */
   28.22 +#ifndef _include_jc_structure_h_
   28.23 +#define _include_jc_structure_h_
   28.24 +
   28.25 +#include "Objects.h"
   28.26 +#include "Handles.h"
   28.27 +#include "Vector.h"
   28.28 +
   28.29 +namespace ke {
   28.30 +
   28.31 +class Type;
   28.32 +class String;
   28.33 +class FixedArray;
   28.34 +
   28.35 +// When describing composite structures, the GC must be able to trace interior
   28.36 +// references to Objects. To make this possible, maps that describe composite
   28.37 +// structures must provide a list of offsets into their objects that are
   28.38 +// traceable. StructureBufferBuilder assists with this.
   28.39 +class StructureBufferBuilder
   28.40 +{
   28.41 +  public:
   28.42 +    StructureBufferBuilder();
   28.43 +
   28.44 +    bool add(Handle<Type> type, unsigned *offset);
   28.45 +
   28.46 +    unsigned structureSize() const {
   28.47 +        return size_;
   28.48 +    }
   28.49 +    unsigned traceableOffsetCount() const {
   28.50 +        return offsets_.length();
   28.51 +    }
   28.52 +    const unsigned *offsets() {
   28.53 +        return offsets_.buffer();
   28.54 +    }
   28.55 +
   28.56 +  private:
   28.57 +    Vector<unsigned> offsets_;
   28.58 +    unsigned size_;
   28.59 +};
   28.60 +
   28.61 +}
   28.62 +
   28.63 +#endif // _include_jc_structure_h_
    29.1 --- a/jitcraft/Vector.h	Fri Jul 20 00:03:10 2012 -0700
    29.2 +++ b/jitcraft/Vector.h	Mon Jul 23 01:19:44 2012 -0700
    29.3 @@ -26,7 +26,7 @@
    29.4  
    29.5  namespace ke {
    29.6  
    29.7 -template <typename T, typename AllocPolicy = NormalAllocPolicy>
    29.8 +template <typename T, typename AllocPolicy = ZoneAllocatorPolicy>
    29.9  class Vector : public AllocPolicy
   29.10  {
   29.11    public:
    30.1 --- a/jitcraft/Zone.cpp	Fri Jul 20 00:03:10 2012 -0700
    30.2 +++ b/jitcraft/Zone.cpp	Mon Jul 23 01:19:44 2012 -0700
    30.3 @@ -76,6 +76,8 @@
    30.4          return false;
    30.5      if ((maps_[MapKind_MetaArray] = allocateMap(MapKind_MetaArray, sizeof(Map))) == NULL)
    30.6          return false;
    30.7 +    if ((maps_[MapKind_MetaEnvironment] = allocateMap(MapKind_MetaEnvironment, sizeof(Map))) == NULL)
    30.8 +        return false;
    30.9      if ((maps_[MapKind_Module] = allocateMap(MapKind_Module, sizeof(Map))) == NULL)
   30.10          return false;
   30.11      if ((maps_[MapKind_Function] = allocateMap(MapKind_Function, sizeof(Map))) == NULL)
   30.12 @@ -86,6 +88,11 @@
   30.13          return false;
   30.14      if ((maps_[MapKind_FreeRegion] = allocateMap(MapKind_FreeRegion, sizeof(Map))) == NULL)
   30.15          return false;
   30.16 +    if ((maps_[MapKind_EnvironmentSlotDescriptorArray] =
   30.17 +         allocateMap(MapKind_EnvironmentSlotDescriptorArray, sizeof(Map))) == NULL)
   30.18 +    {
   30.19 +        return false;
   30.20 +    }
   30.21  
   30.22      types_ = new TypeManager(this);
   30.23      if (!types_ || !types_->initialize())
    31.1 --- a/jitcraft/jitcraft.vcxproj	Fri Jul 20 00:03:10 2012 -0700
    31.2 +++ b/jitcraft/jitcraft.vcxproj	Mon Jul 23 01:19:44 2012 -0700
    31.3 @@ -99,6 +99,7 @@
    31.4      <ClCompile Include="BytecodeCompiler.cpp" />
    31.5      <ClCompile Include="BytecodeEmitter.cpp" />
    31.6      <ClCompile Include="CompileContext.cpp" />
    31.7 +    <ClCompile Include="Environments.cpp" />
    31.8      <ClCompile Include="Exception.cpp" />
    31.9      <ClCompile Include="FixedArray.cpp" />
   31.10      <ClCompile Include="Functions.cpp" />
   31.11 @@ -121,6 +122,7 @@
   31.12      <ClCompile Include="Stack.cpp" />
   31.13      <ClCompile Include="StringPool.cpp" />
   31.14      <ClCompile Include="Strings.cpp" />
   31.15 +    <ClCompile Include="Structures.cpp" />
   31.16      <ClCompile Include="TypeManager.cpp" />
   31.17      <ClCompile Include="Types.cpp" />
   31.18      <ClCompile Include="Zone.cpp" />
   31.19 @@ -136,6 +138,7 @@
   31.20      <ClInclude Include="BytecodeCompiler.h" />
   31.21      <ClInclude Include="CompactBuffer.h" />
   31.22      <ClInclude Include="CompileContext.h" />
   31.23 +    <ClInclude Include="Environments.h" />
   31.24      <ClInclude Include="FixedArray.h" />
   31.25      <ClInclude Include="Functions.h" />
   31.26      <ClInclude Include="GlobalRoots.h" />
   31.27 @@ -166,7 +169,7 @@
   31.28      <ClInclude Include="Stack.h" />
   31.29      <ClInclude Include="Strings.h" />
   31.30      <ClInclude Include="StringPool.h" />
   31.31 -    <ClInclude Include="Structure.h" />
   31.32 +    <ClInclude Include="Structures.h" />
   31.33      <ClInclude Include="TypeManager.h" />
   31.34      <ClInclude Include="Types.h" />
   31.35      <ClInclude Include="Vector.h" />
    32.1 --- a/jitcraft/main.cpp	Fri Jul 20 00:03:10 2012 -0700
    32.2 +++ b/jitcraft/main.cpp	Mon Jul 23 01:19:44 2012 -0700
    32.3 @@ -118,9 +118,9 @@
    32.4          if (!module)
    32.5              return 1;
    32.6  
    32.7 -        Ke::Local<Ke::Native> native = module->getNative(0);
    32.8 -        native->bind(reinterpret_cast<void *>(PrintToServer));
    32.9 -        module->setNativeIdentity(reinterpret_cast<void *>(5));
   32.10 +        //Ke::Local<Ke::Native> native = module->getNative(0);
   32.11 +        //native->bind(reinterpret_cast<void *>(PrintToServer));
   32.12 +        //module->setNativeIdentity(reinterpret_cast<void *>(5));
   32.13  
   32.14          int result;
   32.15          Ke::Local<Ke::Function> fun = module->getPublic(0);