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