jitcraft/BytecodeCompiler.cpp
changeset 12 75e385f68b7e
parent 10 0c3bcd50e361
child 14 0784ac5cc347
     1.1 --- a/jitcraft/BytecodeCompiler.cpp	Fri Jun 29 19:35:17 2012 -0700
     1.2 +++ b/jitcraft/BytecodeCompiler.cpp	Sat Jun 30 19:38:53 2012 -0700
     1.3 @@ -19,6 +19,9 @@
     1.4  #include "Scopes.h"
     1.5  #include "Modules.h"
     1.6  #include "Types.h"
     1.7 +#include "Array.h"
     1.8 +#include "Zone.h"
     1.9 +#include "Heap-inl.h"
    1.10  
    1.11  using namespace jc;
    1.12  
    1.13 @@ -95,22 +98,29 @@
    1.14  }
    1.15  
    1.16  void
    1.17 -BytecodeCompiler::leaveScope(Scope *scope)
    1.18 +BytecodeCompiler::recordLifoSlot(Scope *scope)
    1.19  {
    1.20      if (!scope)
    1.21          return;
    1.22  
    1.23 -    if (Variable *var = scope->firstUnsafeArray())
    1.24 -        __ unwind(var->slot());
    1.25 +    if (Variable *var = scope->lifoSlot()) {
    1.26 +        locals_->set(ZONE(), var->slot(), var->type());
    1.27 +        __ savelifo(var->slot());
    1.28 +    }
    1.29  }
    1.30  
    1.31  void
    1.32  BytecodeCompiler::unwindTo(Scope *scope)
    1.33  {
    1.34 +    // Note: we only need to unwind to the outermost scope's LIFO slot.
    1.35 +    Variable *var = NULL;
    1.36      for (Scope *current = scope_; current != scope; current = current->enclosing()) {
    1.37 -        if (Variable *var = current->firstUnsafeArray())
    1.38 -            __ unwind(var->slot());
    1.39 +        if (Variable *slot = current->lifoSlot())
    1.40 +            var = slot;
    1.41      }
    1.42 +
    1.43 +    if (var)
    1.44 +        __ unwindlifo(var->slot());
    1.45  }
    1.46  
    1.47  void
    1.48 @@ -255,8 +265,9 @@
    1.49  {
    1.50      AutoEnterScope forScope(this, node->scope());
    1.51  
    1.52 +    recordLifoSlot(node->scope());
    1.53 +
    1.54      Label join, update;
    1.55 -
    1.56      LoopScope loop(scope_, &join, &update, &loop_);
    1.57  
    1.58      if (node->declaration())
    1.59 @@ -282,7 +293,8 @@
    1.60  
    1.61      __ bind(&join);
    1.62  
    1.63 -    leaveScope(node->scope());
    1.64 +    if (node->scope())
    1.65 +        unwindTo(node->scope()->enclosing());
    1.66      assert(__ stackDepth() == 0);
    1.67  }
    1.68  
    1.69 @@ -326,6 +338,8 @@
    1.70  {
    1.71      AutoEnterScope blockScope(this, node->scope());
    1.72  
    1.73 +    recordLifoSlot(node->scope());
    1.74 +
    1.75      for (size_t i = 0; i < node->statements()->length(); i++) {
    1.76          Statement *statement = node->statements()->at(i);
    1.77          statement->accept(this);
    1.78 @@ -335,7 +349,7 @@
    1.79      // We don't bother emitting an "unwind" instruction for function scopes,
    1.80      // since this is taken care of by the calling convention.
    1.81      if (node->scope() && node->scope()->enclosing()->kind() != Scope::FUNCTION)
    1.82 -        leaveScope(node->scope());
    1.83 +        unwindTo(node->scope()->enclosing());
    1.84  }
    1.85  
    1.86  void
    1.87 @@ -350,6 +364,20 @@
    1.88      __ float_((float)node->value());
    1.89  }
    1.90  
    1.91 +static inline ArrayMap *
    1.92 +BuildArrayMap(Zone *zone, Type *type)
    1.93 +{
    1.94 +    // :TODO: use local
    1.95 +    ArrayMap *contained = NULL;
    1.96 +    if (type->levels() > 1) {
    1.97 +        contained = BuildArrayMap(zone, type->contained());
    1.98 +        if (!contained)
    1.99 +            return NULL;
   1.100 +    }
   1.101 +
   1.102 +    return ArrayMap::New(zone, type, contained);
   1.103 +}
   1.104 +
   1.105  void
   1.106  BytecodeCompiler::visit(VariableDeclaration *node)
   1.107  {
   1.108 @@ -358,22 +386,9 @@
   1.109      
   1.110      Type *type = var->type();
   1.111      if (type->isArray()) {
   1.112 -        bool isConstant = true;
   1.113 -        for (Type *child = type; child->isArray(); child = child->contained()) {
   1.114 -            if (child->elements() == Type::UNKNOWN_SIZE) {
   1.115 -                isConstant = false;
   1.116 -                break;
   1.117 -            }
   1.118 -        }
   1.119 -
   1.120 -        if (!isConstant) {
   1.121 -            for (size_t i = 0; i < node->postDimensions()->size(); i++) {
   1.122 -                Expression *expr = node->postDimensions()->at(i);
   1.123 -                expr->accept(this);
   1.124 -            }
   1.125 -        }
   1.126 -
   1.127 -        __ stackarray(type);
   1.128 +        // :TODO: use Local
   1.129 +        ArrayMap *map = BuildArrayMap(ZONE(), type);
   1.130 +        __ lifoarray(map);
   1.131      } else {
   1.132          if (node->initialization()) {
   1.133              node->initialization()->accept(this);
   1.134 @@ -385,7 +400,7 @@
   1.135      __ setlocal(var->slot());
   1.136      __ pop();
   1.137  
   1.138 -    locals_[var->slot()] = var->type();
   1.139 +    locals_->set(ZONE(), var->slot(), var->type());
   1.140  }
   1.141  
   1.142  void
   1.143 @@ -439,38 +454,43 @@
   1.144  Code *
   1.145  BytecodeCompiler::compileFunction(Module *module, FunctionStatement *node)
   1.146  {
   1.147 +    // Note: No need to record a life slot here, since it's part of the Frame.
   1.148      AutoEnterScope functionScope(this, node->scope());
   1.149  
   1.150 -    locals_ = new Type *[node->scope()->maxContainedLocals()];
   1.151 -    memset(locals_, 0, sizeof(Type *) * node->scope()->maxContainedLocals());
   1.152 +    // :TODO: use locals
   1.153 +    locals_ = FixedArray::New(ZONE(), node->scope()->maxContainedLocals(), Heap::Tenure_Old);
   1.154  
   1.155      node->body()->accept(this);
   1.156  
   1.157      __ stop();
   1.158  
   1.159      if (__ oom())
   1.160 -        return false;
   1.161 +        return NULL;
   1.162  
   1.163 -    bytecode *start = (bytecode *)malloc(__ length() * sizeof(bytecode));
   1.164 -    memcpy(start, __ buffer(), __ length());
   1.165 +    ByteArray *bytes = ByteArray::New(ZONE(), __ length() * sizeof(bytecode), Heap::Tenure_Old);
   1.166 +    if (!bytes)
   1.167 +        return NULL;
   1.168 +    memcpy(bytes->raw(), __ buffer(), __ length());
   1.169  
   1.170      unsigned nargs = node->scope()->numArguments();
   1.171 -    Type **args = new Type *[nargs];
   1.172 +    FixedArray *args = FixedArray::New(ZONE(), nargs, Heap::Tenure_Old);
   1.173 +    if (!args)
   1.174 +        return NULL;
   1.175 +
   1.176      for (size_t i = 0; i < node->scope()->numArguments(); i++)
   1.177 -        args[i] = node->scope()->getArgument(i)->type();
   1.178 +        args->set(ZONE(), i, node->scope()->getArgument(i)->type());
   1.179  
   1.180      for (size_t i = 0; i < node->scope()->maxContainedLocals(); i++)
   1.181 -        assert(locals_[i]);
   1.182 +        assert(locals_->at(i));
   1.183  
   1.184 -    Code *code = new Code(module,
   1.185 -                          start,
   1.186 -                          __ length(),
   1.187 -                          args,
   1.188 -                          nargs,
   1.189 -                          locals_,
   1.190 -                          node->scope()->maxContainedLocals(),
   1.191 -                          __ maxStackDepth());
   1.192 +    FixedArray *maps = FixedArray::New(ZONE(), __ maps()->size(), Heap::Tenure_Old);
   1.193 +    if (!maps)
   1.194 +        return NULL;
   1.195  
   1.196 +    for (size_t i = 0; i < __ maps()->size(); i++)
   1.197 +        maps->set(ZONE(), i, __ maps()->at(i));
   1.198 +
   1.199 +    Code *code = Code::New(ZONE(), bytes, locals_, args, maps, __ maxStackDepth(), module_);
   1.200      return code;
   1.201  }
   1.202