src/OldByCo.cpp
author David Anderson <dvander@alliedmods.net>
Tue Jan 01 20:08:34 2013 -0800 (2013-01-01)
changeset 255 b3cf7e052ddf
parent 195 c1ba166f3fc4
child 263 ba85a47ee414
permissions -rw-r--r--
Fix FileSystem.cpp build on GCC.
     1 /* vim: set ts=4 sw=4 tw=99 et:
     2  *
     3  * Copyright (C) 2012 David Anderson
     4  *
     5  * This file is part of JITCraft.
     6  *
     7  * JITCraft is free software: you can redistribute it and/or modify it under
     8  * the terms of the GNU General Public License as published by the Free
     9  * Software Foundation, either version 3 of the License, or (at your option)
    10  * any later version.
    11  * 
    12  * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU General Public License along with
    17  * JITCraft. If not, see http://www.gnu.org/licenses/.
    18  */
    19 #include <string.h>
    20 #include "../Modules.h"
    21 #include "../Types.h"
    22 #include "../Array.h"
    23 #include "../Strings.h"
    24 #include "../Zone.h"
    25 #include "../Environments.h"
    26 #include "../Box.h"
    27 #include "../Heap-inl.h"
    28 #include "BytecodeCompiler.h"
    29 #include "Scopes.h"
    30 
    31 using namespace ke;
    32 
    33 typedef BytecodeEmitter::Label Label;
    34 
    35 #define __ emitter_.
    36 
    37 BytecodeCompiler::BytecodeCompiler(Zone *zone, ParseTree *tree, ModuleData *module)
    38   : zone_(zone),
    39     tree_(tree),
    40     emitter_(zone->pool()),
    41     locals_(NULL),
    42     scope_(NULL),
    43     moduleData_(module),
    44     loop_(NULL)
    45 {
    46 }
    47 
    48 static inline TokenKind
    49 ToCompare(Expression *expr)
    50 {
    51     if (expr->isBinaryExpression()) {
    52         BinaryExpression *b = expr->toBinaryExpression();
    53         if (b->token() >= TOK_EQUALS && b->token() <= TOK_OR)
    54             return b->token();
    55     } else if (expr->isUnaryExpression()) {
    56         UnaryExpression *u = expr->toUnaryExpression();
    57         if (u->token() == TOK_NOT)
    58             return TOK_NOT;
    59     }
    60     return TOK_EOF;
    61 }
    62 
    63 static inline Opcode
    64 CompareTokenToJump(TokenKind kind)
    65 {
    66     switch (kind) {
    67       case TOK_EQUALS:
    68         return OP_JEQ;
    69       case TOK_NOTEQUALS:
    70         return OP_JNE;
    71       case TOK_GT:
    72         return OP_JG;
    73       case TOK_GE:
    74         return OP_JGE;
    75       case TOK_LT:
    76         return OP_JL;
    77       default:
    78         assert(kind == TOK_LE);
    79         return OP_JLE;
    80     }
    81 }
    82 
    83 static inline Opcode
    84 TokenToOpcode(TokenKind kind)
    85 {
    86     switch (kind) {
    87       case TOK_PLUS:
    88         return OP_ADD;
    89       case TOK_MINUS:
    90         return OP_SUB;
    91       case TOK_STAR:
    92         return OP_MUL;
    93       case TOK_SLASH:
    94         return OP_DIV;
    95       case TOK_PERCENT:
    96         return OP_MOD;
    97       case TOK_SHR:
    98         return OP_SHR;
    99       case TOK_USHR:
   100         return OP_USHR;
   101       case TOK_SHL:
   102         return OP_SHL;
   103       case TOK_BITAND:
   104         return OP_BITAND;
   105       case TOK_BITOR:
   106         return OP_BITOR;
   107       case TOK_GT:
   108           return OP_GT;
   109       case TOK_GE:
   110           return OP_GE;
   111       case TOK_LT:
   112           return OP_LT;
   113       case TOK_LE:
   114           return OP_LE;
   115       case TOK_EQUALS:
   116           return OP_EQ;
   117       case TOK_NOTEQUALS:
   118           return OP_NE;
   119       default:
   120         assert(kind == TOK_BITXOR);
   121         return OP_BITXOR;
   122     }
   123 }
   124 
   125 void
   126 BytecodeCompiler::recordLifoSlot(Scope *scope)
   127 {
   128     if (!scope)
   129         return;
   130 
   131     if (Variable *var = scope->lifoSlot()) {
   132         locals_->set(zone_, var->slot(), var->type());
   133         __ savelifo(var->slot());
   134     }
   135 }
   136 
   137 void
   138 BytecodeCompiler::unwindTo(Scope *scope)
   139 {
   140     // Note: we only need to unwind to the outermost scope's LIFO slot.
   141     Variable *var = NULL;
   142     for (Scope *current = scope_; current != scope; current = current->enclosing()) {
   143         if (Variable *slot = current->lifoSlot())
   144             var = slot;
   145     }
   146 
   147     if (var)
   148         __ unwindlifo(var->slot());
   149 }
   150 
   151 void
   152 BytecodeCompiler::visit(NameProxy *name)
   153 {
   154     switch (name->binding()->kind()) {
   155       case BoundName::VARIABLE:
   156       {
   157         Variable *var = name->binding()->toVariable();
   158 
   159         if (var->location() == Variable::STACK) {
   160             __ getlocal(var);
   161             assert(!name->type()->isReference());
   162         } else if (var->location() == Variable::ENVIRONMENT) {
   163             getEnvSlot(var);
   164         } else {
   165             assert(var->location() == Variable::PARAMETER);
   166             __ getarg(var);
   167 
   168             // If this argument is actually a reference, dereference it now.
   169             if (var->type()->isReference())
   170                 __ getref(var->type()->contained());
   171         }
   172         break;
   173       }
   174 
   175       case BoundName::FUNCTION:
   176       {
   177         NamedFunction *fun = name->binding()->toNamedFunction();
   178         __ module();
   179         __ getmodule_fn(fun->slot());
   180         break;
   181       }
   182 
   183       default:
   184       {
   185         NamedConstant *constant = name->binding()->toNamedConstant();
   186         __ int_(constant->value().toInt());
   187         break;
   188       }
   189     }
   190 }
   191 
   192 void
   193 BytecodeCompiler::visit(ExpressionStatement *node)
   194 {
   195     // Expressions leave their value on the top of the stack, so we make sure
   196     // to balance the stack if they're used as a statement.
   197     node->expression()->accept(this);
   198     if (!node->expression()->type()->isVoid())
   199         __ pop();
   200 }
   201 
   202 static inline bool
   203 IsCompositeValueType(Type *type)
   204 {
   205     return type->isStruct() ||
   206            (type->isArray() && type->isFixedLength());
   207 }
   208 
   209 static inline Array *
   210 StringLiteralToArray(Zone *zone, StringLiteral *node)
   211 {
   212     Local<Type> type(zone, node->type());
   213     Local<ArrayMap> map(zone, ArrayMap::Attach(zone, type));
   214     if (!map)
   215         return NULL;
   216 
   217     return Array::NewString(zone,
   218                             map,
   219                             node->string()->raw(),
   220                             node->string()->length(),
   221                             Heap::Tenure_Old);
   222 }
   223 
   224 void
   225 BytecodeCompiler::visit(Assignment *node)
   226 {
   227     Local<Type> left(zone_, node->type());
   228     Local<Type> right(zone_, node->expression()->type());
   229 
   230     // The first step is three sub-steps:
   231     //
   232     //   (1) Bind the left-hand side.
   233     //   -- If a cumulative operation (+=, etc):
   234     //   (2) Save a copy of the binding on the stack.
   235     //   (3) Dereference the binding to get a value.
   236     //
   237     if (node->lvalue()->isNameProxy()) {
   238         NameProxy *proxy = node->lvalue()->toNameProxy();
   239         Variable *var = proxy->binding()->toVariable();
   240 
   241         // We need to fetch the variable under the following circumstances:
   242         //  (1) The variable is a reference, since we'll store into the ref.
   243         //  (2) The variable is a fixed array, since we need to copy into it.
   244         //  (3) The variable is a struct, since we need to copy into it.
   245         if (var->type()->isReference() || IsCompositeValueType(var->type()))
   246             __ get(var);
   247 
   248         // Get the value if needed.
   249         if (node->token() != TOK_ASSIGN) {
   250             // += etc is not allowed on arrays.
   251             assert(!var->type()->isArray());
   252 
   253             if (var->location() == Variable::ENVIRONMENT)
   254                 getEnvSlot(var);
   255 
   256             if (var->type()->isReference()) {
   257                 __ dup();
   258                 __ getref(var->type()->contained());
   259             } else if (var->location() != Variable::ENVIRONMENT) {
   260                 __ get(var);
   261             }
   262         }
   263     } else if (node->lvalue()->isFieldExpression()) {
   264         FieldExpression *expr = node->lvalue()->toFieldExpression();
   265         __ note_position(expr->pos());
   266 
   267         expr->left()->accept(this);
   268 
   269         if (node->token() != TOK_ASSIGN)
   270             __ dup();
   271 
   272         if (node->token() != TOK_ASSIGN || IsCompositeValueType(left))
   273             __ getfield(expr->fieldIndex(), left);
   274     } else {
   275         IndexExpression *index = node->lvalue()->toIndexExpression();
   276         __ note_position(index->pos());
   277 
   278         index->left()->accept(this);
   279         index->right()->accept(this);
   280 
   281         if (node->token() != TOK_ASSIGN)
   282             __ dup2();
   283 
   284         if (node->token() != TOK_ASSIGN || IsCompositeValueType(left))
   285             __ getelem(left);
   286     }
   287 
   288     if (node->token() == TOK_ASSIGN) {
   289         // Special case: if the left-hand side is a string literal, we must
   290         // spawn a new copy (:TODO: something about const?)
   291         if (node->expression()->isStringLiteral() && !left->isFixedLength()) {
   292             Local<Array> string(zone_,
   293                     StringLiteralToArray(zone_, node->expression()->toStringLiteral()));
   294             if (!string)
   295                 return;
   296 
   297             Local<ArrayMap> arrayMap(zone_, ArrayMap::cast(string->map()));
   298             __ note_position(node->expression()->pos());
   299             __ int_(string->length());
   300             __ newarray(OP_NEWSIZED, arrayMap, Heap::Tenure_Default);
   301             __ object(string);
   302             __ copyarray();
   303         } else {
   304             node->expression()->accept(this);
   305         }
   306     } else {
   307         visitForALU(left, node->expression());
   308 
   309         TokenKind alu = TokenKind(int(node->token()) - (TOK_ASSIGN_ADD - TOK_PLUS));
   310         __ note_position(node->pos());
   311         __ binary(TokenToOpcode(alu));
   312     }
   313 
   314     // Emit the store.
   315     if (left->isArray() && left->isFixedLength()) {
   316         // (x = y) returns the left-hand side; if |x| is a fixed-length array,
   317         // then |y| is as well, and we perform a deep copy.
   318         assert(right->isFixedLength());
   319         __ note_position(node->pos());
   320         __ copyarray();
   321     } else if (left->isStruct()) {
   322         // Structs have value semantics, so emit a full copy. We don't break
   323         // this down into u-ops, to avoid unnecessary bytecode explosion.
   324         assert(right->isStruct());
   325         __ note_position(node->pos());
   326         __ copystruct();
   327     } else if (node->lvalue()->isNameProxy()) {
   328         NameProxy *proxy = node->lvalue()->toNameProxy();
   329         Variable *var = proxy->binding()->toVariable();
   330 
   331         if (var->type()->isReference())
   332             __ setref(var->type()->contained());
   333         else if (var->location() == Variable::ENVIRONMENT)
   334             setEnvSlot(var);
   335         else
   336             __ set(var);
   337     } else if (node->lvalue()->isFieldExpression()) {
   338         FieldExpression *expr = node->lvalue()->toFieldExpression();
   339         __ setfield(expr->fieldIndex(), left);
   340     } else {
   341         __ setelem(left);
   342     }
   343 }
   344 
   345 void
   346 BytecodeCompiler::visit(IncDecExpression *node)
   347 {
   348     // In the postfix case, the logic looks like:
   349     //      (1) Bind       -> REF
   350     //      (2) Dup        -> REF REF
   351     //      (3) Fetch      -> REF VAL
   352     //      (4) Swap       -> VAL REF
   353     //      (5) Pick       -> VAL REF VAL
   354     //      (6) Add        -> VAL REF VAL+1
   355     //      (7) Store      -> VAL VAL+1
   356     //      (8) Drop       -> VAL
   357     //
   358     // In the prefix case, the logic looks like:
   359     //      (1) Bind       -> REF
   360     //      (2) Dup        -> REF REF
   361     //      (3) Fetch      -> REF VAL
   362     //      --
   363     //      --
   364     //      (6) Add        -> REF VAL+1
   365     //      (7) Store      -> VAL+1
   366     //      --
   367     //
   368     // This is squirrely enough such that we don't bother sharing too much
   369     // with the above.
   370     // 
   371     // Note: We simulate a "Pick" operation with a dup2+pop.
   372 
   373     // This is steps (1) to (5).
   374     Expression *expr = node->expression();
   375     if (expr->isNameProxy()) {
   376         NameProxy *proxy = expr->toNameProxy();
   377         Variable *var = proxy->binding()->toVariable();
   378 
   379         // Bind.
   380         if (var->location() == Variable::ENVIRONMENT)
   381             getEnvSlot(var);
   382         else if (var->type()->isReference() || var->type()->isArray())
   383             __ get(var);
   384 
   385         // Dup and fetch.
   386         if (var->type()->isReference()) {
   387             __ dup();
   388             __ getref(node->type());
   389             if (node->postfix()) {
   390                 __ swap();
   391                 __ pick2();
   392             }
   393         } else {
   394             assert(!var->type()->isArray());
   395             if (var->location() != Variable::ENVIRONMENT)
   396                 __ get(var);
   397             if (node->postfix())
   398                 __ dup();
   399         }
   400     } else if (expr->isFieldExpression()) {
   401         FieldExpression *field = expr->toFieldExpression();
   402 
   403         field->left()->accept(this);
   404         __ dup();
   405         __ getfield(field->fieldIndex(), field->type());
   406 
   407         if (node->postfix()) {
   408             // The stack looks like this now:
   409             // OBJECT VALUE
   410             __ swap();          // VALUE OBJECT
   411             __ pick2();         // VALUE OBJECT VALUE
   412         }
   413     } else {
   414         IndexExpression *index = expr->toIndexExpression();
   415         __ note_position(index->pos());
   416 
   417         index->left()->accept(this);
   418         index->right()->accept(this);
   419 
   420         assert(!node->type()->isArray());
   421         __ dup2();
   422         __ getelem(node->type());
   423 
   424         if (node->postfix()) {
   425             // The stack looks like this now:
   426             // ARRAY INDEX VALUE
   427             //
   428             // So we must use a PICK operation to rotate the stack into position.
   429             __ roll3();         // INDEX VALUE ARRAY
   430             __ roll3();         // VALUE ARRAY INDEX
   431             __ pick3();         // VALUE ARRAY INDEX VALUE
   432         }
   433     }
   434 
   435     // Perform step (6).
   436     if (node->type()->isFloat()) {
   437         __ float_(1.0);
   438     } else {
   439         assert(node->type()->isInt32());
   440         __ int_(1);
   441     }
   442 
   443     __ note_position(node->pos());
   444     if (node->token() == TOK_INCREMENT)
   445         __ binary(OP_ADD);
   446     else
   447         __ binary(OP_SUB);
   448 
   449     // Perform step (7).
   450     if (expr->isNameProxy()) {
   451         NameProxy *proxy = expr->toNameProxy();
   452         Variable *var = proxy->binding()->toVariable();
   453 
   454         if (var->type()->isReference())
   455             __ setref(node->type());
   456         else if (var->location() == Variable::ENVIRONMENT)
   457             setEnvSlot(var);
   458         else
   459             __ set(var);
   460     } else if (expr->isFieldExpression()) {
   461         FieldExpression *field = expr->toFieldExpression();
   462         __ setfield(field->fieldIndex(), field->type());
   463     } else {
   464         assert(expr->isIndexExpression());
   465         __ setelem(node->type());
   466     }
   467 
   468     // Perform step (8).
   469     if (node->postfix())
   470         __ pop();
   471 }
   472 
   473 void
   474 BytecodeCompiler::visitForALU(Type *needed, Expression *node)
   475 {
   476     node->accept(this);
   477     if (needed->isFloat() && !node->type()->isFloat())
   478         __ cvt_i2f();
   479     else
   480         assert(needed->primitive() == node->type()->primitive());
   481 }
   482 
   483 static inline Type *
   484 GetCoercionType(TokenKind tok, Type *left, Type *right)
   485 {
   486     if (left->isFloat())
   487         return left;
   488     return right;
   489 }
   490 
   491 void
   492 BytecodeCompiler::visit(UnaryExpression *node)
   493 {
   494     Local<Type> out(zone_, ((Expression *)node)->type());
   495 
   496     switch (node->token()) {
   497       case TOK_MINUS:
   498       {
   499         Local<Type> type(zone_, node->expression()->type());
   500         node->expression()->accept(this);
   501         
   502         if (out->isFloat())
   503             __ neg_f();
   504         else
   505             __ neg();
   506         break;
   507       }
   508 
   509       case TOK_NOT:
   510       {
   511         Local<Type> type(zone_, node->expression()->type());
   512         node->expression()->accept(this);
   513         
   514         if (out->isFloat())
   515             __ not_f();
   516         else
   517             __ not_();
   518         break;
   519       }
   520 
   521       case TOK_LABEL:
   522       {
   523         Local<Type> from(zone_, node->expression()->type());
   524 
   525         node->expression()->accept(this);
   526         if (!from->isFloat() && out->isFloat())
   527             __ bits_f2i();
   528         else if (from->isFloat() && !out->isFloat())
   529             __ bits_i2f();
   530         break;
   531       }
   532 
   533       case TOK_SIZEOF:
   534       {
   535         Local<Type> type(zone_, node->expression()->type());
   536         if (type->isFixedLength()) {
   537             __ int_(type->fixedLength());
   538         } else {
   539             node->expression()->accept(this);
   540             __ sizeof_();
   541         }
   542         break;
   543       }
   544 
   545       default:
   546         assert(node->token() == TOK_TILDE);
   547         node->expression()->accept(this);
   548         __ bitnot();
   549         break;
   550     }
   551 }
   552 
   553 void
   554 BytecodeCompiler::visit(BinaryExpression *node)
   555 {
   556     if (node->token() == TOK_AND || node->token() == TOK_OR) {
   557         Label success, failure, done;
   558         visitForTest(node, &success, &failure, &success);
   559         __ bind(&success);
   560         __ int_(1);
   561         __ drop(1);         // Otherwise, the stack depth will be +1 too much.
   562         __ jump(&done);
   563         __ bind(&failure);
   564         __ int_(0);
   565         __ bind(&done);
   566         return;
   567     }
   568 
   569     Local<Type> leftType(zone_, node->left()->type());
   570     Local<Type> rightType(zone_, node->right()->type());
   571     Local<Type> coerce(zone_, GetCoercionType(node->token(), leftType, rightType));
   572 
   573     visitForALU(coerce, node->left());
   574     visitForALU(coerce, node->right());
   575 
   576     Opcode op = TokenToOpcode(node->token());
   577     if (node->type()->isFloat())
   578         op = (Opcode)(int(op) + (OP_ADD_F - OP_ADD));
   579 
   580     __ note_position(node->pos());
   581     __ binary(op);
   582 }
   583 
   584 void
   585 BytecodeCompiler::visit(IndexExpression *node)
   586 {
   587     node->left()->accept(this);
   588     node->right()->accept(this);
   589     __ note_position(node->pos());
   590     __ getelem(node->type());
   591 }
   592 
   593 void
   594 BytecodeCompiler::visit(FieldExpression *node)
   595 {
   596     node->left()->accept(this);
   597     __ getfield(node->fieldIndex(), node->type());
   598 }
   599 
   600 void
   601 BytecodeCompiler::visit(ReturnStatement *node)
   602 {
   603     if (node->expression()) {
   604         node->expression()->accept(this);
   605         __ return_();
   606     } else {
   607         __ returnvoid();
   608     }
   609 }
   610 
   611 void
   612 BytecodeCompiler::visitForTest(Expression *expression,
   613                                Label *trueBranch,
   614                                Label *falseBranch,
   615                                Label *fallthrough)
   616 {
   617     TokenKind token = ToCompare(expression);
   618     if (token == TOK_EOF || token == TOK_NOT) {
   619         if (token == TOK_EOF)
   620             expression->accept(this);
   621         else
   622             expression->toUnaryExpression()->expression()->accept(this);
   623         
   624         bool jumpOnTrue = (fallthrough == falseBranch) ^ (token == TOK_NOT);
   625 
   626         Opcode op = jumpOnTrue ? OP_JT : OP_JF;
   627         if (expression->type()->isFloat())
   628             op = (Opcode)(int(op) + (OP_JL_F - OP_JL));
   629 
   630         if (fallthrough == falseBranch)
   631             __ j(op, trueBranch);
   632         else
   633             __ j(op, falseBranch); 
   634         return;
   635     }
   636 
   637     BinaryExpression *binary = expression->toBinaryExpression();
   638 
   639     if (token == TOK_AND || token == TOK_OR) {
   640         Label next;
   641         if (token == TOK_AND)
   642             visitForTest(binary->left(), &next, falseBranch, &next);
   643         else
   644             visitForTest(binary->left(), trueBranch, &next, &next);
   645         __ bind(&next);
   646         visitForTest(binary->right(), trueBranch, falseBranch, fallthrough);
   647         return;
   648     }
   649 
   650     Opcode op = CompareTokenToJump(token);
   651     if (fallthrough == trueBranch)
   652         op = Invert(op);
   653 
   654     Local<Type> leftType(zone_, binary->left()->type());
   655     Local<Type> rightType(zone_, binary->right()->type());
   656     Local<Type> coerce(zone_, GetCoercionType(binary->token(), leftType, rightType));
   657 
   658     visitForALU(coerce, binary->left());
   659     visitForALU(coerce, binary->right());
   660     if (coerce->isFloat())
   661         op = (Opcode)(int(op) + (OP_JL_F - OP_JL));
   662 
   663     if (fallthrough == trueBranch)
   664         __ j(op, falseBranch);
   665     else
   666         __ j(op, trueBranch);
   667 }
   668 
   669 void
   670 BytecodeCompiler::visit(ForStatement *node)
   671 {
   672     AutoEnterScope forScope(this, node->scope());
   673 
   674     recordLifoSlot(node->scope());
   675 
   676     Label join, update;
   677     LoopScope loop(scope_, &join, &update, &loop_);
   678 
   679     if (node->initialization())
   680         node->initialization()->accept(this);
   681 
   682     Label header, test;
   683     if (node->condition())
   684         __ jump(&test);
   685 
   686     __ bind(&header);
   687     node->body()->accept(this);
   688 
   689     __ bind(&update);
   690     if (node->update())
   691         node->update()->accept(this);
   692 
   693     if (node->condition()) {
   694         __ bind(&test);
   695         visitForTest(node->condition(), &header, &join, &join);
   696     } else {
   697         __ jump(&header);
   698     }
   699 
   700     __ bind(&join);
   701 
   702     if (node->scope())
   703         unwindTo(node->scope()->enclosing());
   704     assert(__ stackDepth() == 0);
   705 }
   706 
   707 void
   708 BytecodeCompiler::visit(WhileStatement *node)
   709 {
   710     Label header, join;
   711 
   712     __ bind(&header);
   713 
   714     LoopScope loop(scope_, &join, &header, &loop_);
   715 
   716     if (node->token() == TOK_WHILE) {
   717         Label body;
   718 
   719         visitForTest(node->condition(), &body, &join, &body);
   720         __ bind(&body);
   721         node->body()->accept(this);
   722         __ jump(&header);
   723     } else {
   724         node->body()->accept(this);
   725         visitForTest(node->condition(), &header, &join, &join);
   726     }
   727 
   728     __ bind(&join);
   729 }
   730 
   731 void
   732 BytecodeCompiler::visit(BreakStatement *node)
   733 {
   734     unwindTo(loop_->scope());
   735     __ jump(loop_->break_());
   736 }
   737 
   738 void
   739 BytecodeCompiler::visit(ContinueStatement *node)
   740 {
   741     unwindTo(loop_->scope());
   742     __ jump(loop_->continue_());
   743 }
   744 
   745 void
   746 BytecodeCompiler::visit(BlockStatement *node)
   747 {
   748     AutoEnterScope blockScope(this, node->scope());
   749 
   750     recordLifoSlot(node->scope());
   751 
   752     for (size_t i = 0; i < node->statements()->length(); i++) {
   753         Statement *statement = node->statements()->at(i);
   754         statement->accept(this);
   755         assert(__ stackDepth() == 0);
   756     }
   757 
   758     // We don't bother emitting an "unwind" instruction for function scopes,
   759     // since this is taken care of by the calling convention.
   760     if (node->scope() && node->scope()->enclosing()->kind() != Scope::FUNCTION)
   761         unwindTo(node->scope()->enclosing());
   762 }
   763 
   764 void
   765 BytecodeCompiler::visit(IntegerLiteral *node)
   766 {
   767     __ int_(node->value());
   768 }
   769 
   770 void
   771 BytecodeCompiler::visit(BooleanLiteral *node)
   772 {
   773     if (node->token() == TOK_TRUE)
   774         __ true_();
   775     else
   776         __ false_();
   777 }
   778 
   779 void
   780 BytecodeCompiler::visit(FloatLiteral *node)
   781 {
   782     __ float_((float)node->value());
   783 }
   784 
   785 void
   786 BytecodeCompiler::visit(StringLiteral *node)
   787 {
   788     Local<Array> array(zone_, StringLiteralToArray(zone_, node));
   789     if (!array)
   790         return;
   791 
   792     __ note_position(node->pos());
   793     __ object(array);
   794 }
   795 
   796 void
   797 BytecodeCompiler::getEnvSlot(Variable *var)
   798 {
   799     assert(var->scope()->kind() == Scope::GLOBAL);
   800     __ getglobal(var);
   801 }
   802 
   803 void
   804 BytecodeCompiler::setEnvSlot(Variable *var)
   805 {
   806     assert(var->scope()->kind() == Scope::GLOBAL);
   807     __ setglobal(var);
   808 }
   809 
   810 static bool
   811 FillArrayLiteral_String(Zone *zone, Handle<Array> array, ArrayLiteral *literal, unsigned *maxsize)
   812 {
   813     Local<Array> string(zone);
   814     for (size_t i = 0; i < literal->expressions()->length(); i++) {
   815         Expression *expr = literal->expressions()->at(i);
   816         StringLiteral *lit = expr->toStringLiteral();
   817         if ((string = StringLiteralToArray(zone, lit)) == NULL)
   818             return false;
   819 
   820         array->writeObject(zone, i, string);
   821 
   822         if (string->length() > *maxsize)
   823             *maxsize = string->length();
   824 
   825         assert(!array->type()->contained()->isFixedLength() ||
   826                 array->type()->contained()->fixedLength() >= string->length());
   827     }
   828 
   829     return true;
   830 }
   831 
   832 static bool
   833 FillArrayLiteral_Primitive(Zone *zone, Handle<Array> array, ArrayLiteral *literal)
   834 {
   835     assert(array->type()->fixedLength() == literal->expressions()->length());
   836 
   837     for (size_t i = 0; i < literal->expressions()->length(); i++) {
   838         Expression *expr = literal->expressions()->at(i);
   839         if (IntegerLiteral *lit = expr->asIntegerLiteral()) {
   840             array->writeInt32(i, lit->value());
   841             continue;
   842         }
   843         if (BooleanLiteral *lit = expr->asBooleanLiteral()) {
   844             if (lit->token() == TOK_TRUE)
   845                 array->writeInt32(i, 1);
   846             else
   847                 array->writeInt32(i, 0);
   848             continue;
   849         }
   850         if (FloatLiteral *lit = expr->asFloatLiteral()) {
   851             array->writeFloat(i, (float)lit->value());
   852             continue;
   853         }
   854 
   855         // Unrecognized literal type.
   856         assert(false);
   857     }
   858 
   859     return true;
   860 }
   861 
   862 static bool
   863 TraverseArrayLiteral(Zone *zone, ArrayLiteral *literal, Handle<Array> array, Handle<Type> type,
   864                      unsigned *maxsize)
   865 {
   866     assert(type->fixedLength() == literal->expressions()->length());
   867 
   868     Local<Type> contained(zone, type->contained());
   869     if (contained->isCharArray())
   870         return FillArrayLiteral_String(zone, array, literal, maxsize);
   871 
   872     if (!contained->isArray())
   873         return FillArrayLiteral_Primitive(zone, array, literal);
   874 
   875     Local<Array> subarray(zone);
   876     for (size_t i = 0; i < literal->expressions()->length(); i++) {
   877         Expression *expr = literal->expressions()->at(i);
   878         subarray = Array::cast(array->readObject(i));
   879         if (!TraverseArrayLiteral(zone, expr->toArrayLiteral(), subarray, contained, maxsize))
   880             return false;
   881     }
   882 
   883     return true;
   884 }
   885 
   886 static Array *
   887 BuildArrayLiteral(Zone *zone, ArrayLiteral *literal, Handle<ArrayMap> map, unsigned *maxsize)
   888 {
   889     Local<Array> root(zone, Array::NewFixed(zone, map, Heap::Tenure_Old));
   890     if (!root)
   891         return NULL;
   892 
   893     // This should have allocated everything in the array, so all we need to
   894     // do is traverse down to the lowest levels and copy things.
   895     Local<Type> type(zone, map->type());
   896     if (!TraverseArrayLiteral(zone, literal, root, type, maxsize))
   897         return NULL;
   898 
   899     return root;
   900 }
   901 
   902 static inline bool
   903 ArrayContainsCharBuffers(Type *type)
   904 {
   905     if (type->contained()->isArray())
   906         return ArrayContainsCharBuffers(type->contained());
   907     return type->isCharArray();
   908 }
   909 
   910 void
   911 BytecodeCompiler::visit(VariableDeclaration *node)
   912 {
   913     Variable *var = node->variable();
   914     
   915     Local<Type> type(zone_, var->type());
   916     if (type->isArray()) {
   917         Local<ArrayMap> map(zone_, ArrayMap::Attach(zone_, type));
   918         __ note_position(node->pos());
   919 
   920         Local<Type> right(zone_);
   921         if (node->initialization())
   922             right = node->initialization()->type();
   923 
   924         // There are a few methods for allocating, here:
   925         // (1) If the array is fixed,
   926         //    (a) Initializer not present,
   927         //              NEWFIXED
   928         //    (b) Left is const non-string:
   929         //              <nothing>
   930         //    (b) Otherwise:
   931         //              NEWFIXED
   932         //              COPYARRAY
   933         // (2) If the array is not fixed,
   934         //    (a) Initializer is not present,
   935         //              NEWEMPTY
   936         //    (b) Initializer is not a string literal,
   937         //        or left is const:
   938         //              <nothing>
   939         //    (c) Initializer is a string literal,
   940         //              NEWSIZED
   941         //              COPYARRAY
   942         //
   943 
   944         Heap::Tenure tenure = var->scope()->kind() == Scope::GLOBAL
   945                               ? Heap::Tenure_Old
   946                               : Heap::Tenure_Default;
   947 
   948         if (Expression *init = node->initialization()) {
   949             if (init->isArrayLiteral()) {
   950                 unsigned maxsize = 0;
   951                 Local<Array> array(zone_, BuildArrayLiteral(zone_, init->toArrayLiteral(), map, &maxsize));
   952                 if (!array)
   953                     return;
   954 
   955                 assert(type->isFixedLength());
   956 
   957                 if (type->isConst()) {
   958                     __ object(array);
   959                 } else if (ArrayContainsCharBuffers(type)) {
   960                     // This array contains mutable char buffers, so
   961                     // unfortunately this gets a little more complicated. We
   962                     // compute the maximum size needed for the innermost
   963                     // string, which is similar to SP1. This means we can use
   964                     // CopyArray rather than individually emit opcodes to clone
   965                     // every string.
   966                     Local<Type> child(zone_, type);
   967                     for (size_t i = 0; i < type->levels() - 1; i++) {
   968                         __ int_(child->fixedLength());
   969                         child = child->contained();
   970                     }
   971                     __ int_(maxsize);
   972                     __ newarray(OP_NEWSIZED, map, tenure);
   973                     __ object(array);
   974                     __ copyarray();
   975                 } else {
   976                     __ newarray(OP_NEWFIXED, map, tenure);
   977                     __ object(array);
   978                     __ copyarray();
   979                 }
   980             } else if (type->isFixedLength()) {
   981                 // Note in the case of:
   982                 // const String:buffer[50] = "hello";
   983                 //
   984                 // We want to preserve sizeof(buffer) == 50.
   985                 if (type->isConst() && !type->isCharArray()) {
   986                     init->accept(this);
   987                 } else {
   988                     __ newarray(OP_NEWFIXED, map, tenure);
   989                     init->accept(this);
   990                     __ copyarray();
   991                 }
   992             } else if (!type->isConst() && init->isStringLiteral()) {
   993                 // This is a degenerate case of ArrayLiteral.
   994                 __ int_(right->fixedLength());
   995                 __ newarray(OP_NEWSIZED, map, tenure);
   996                 init->accept(this);
   997                 __ copyarray();
   998             } else if (type->isConst()) {
   999                 init->accept(this);
  1000             }
  1001         } else if (type->isFixedLength()) {
  1002             __ newarray(OP_NEWFIXED, map, tenure);
  1003         } else {
  1004 #if 0
  1005             if (node->postDimensions()) {
  1006                 for (size_t i = 0; i < node->postDimensions()->length(); i++) {
  1007                     Expression *expr = node->postDimensions()->at(i);
  1008                     if (expr)
  1009                         expr->accept(this);
  1010                     else
  1011                         __ int_(0);
  1012                 }
  1013                 __ newarray(OP_NEWSIZED, map, tenure);
  1014             } else {
  1015                 __ newarray(OP_NEWEMPTY, map, tenure);
  1016             }
  1017 #endif
  1018         }
  1019     } else if (type->isStruct()) {
  1020         Local<StructMap> map(zone_, StructMap::cast(type->newMap()));
  1021 
  1022         // Because structs can contain arrays, any sort of composition
  1023         // triggers non-LIFO allocation. This is just for correctness.
  1024         // We could do better by:
  1025         //  (1) Limiting to structs that just (recursively) contain arrays,
  1026         //  (2) Swap Stack for Default tenure in Struct::New
  1027         //  (3) JIT analysis
  1028         if (var->scope()->kind() == Scope::GLOBAL)
  1029             __ newstruct(map, Heap::Tenure_Old);
  1030         else if (var->needsHeapAllocation() || map->composed())
  1031             __ newstruct(map, Heap::Tenure_Default);
  1032         else
  1033             __ newstruct(map, Heap::Tenure_Stack);
  1034     } else {
  1035         if (node->initialization()) {
  1036             node->initialization()->accept(this);
  1037         } else {
  1038             if (type->isInt32OrEnum() || type->isBool()) {
  1039                 __ int_(0);
  1040             } else {
  1041                 assert(type->isFloat());
  1042                 __ float_(0);
  1043             }
  1044         }
  1045     }
  1046 
  1047     if (var->location() == Variable::STACK) {
  1048         __ setlocal(var);
  1049         locals_->set(zone_, var->slot(), var->type());
  1050     } else {
  1051         assert(var->location() == Variable::ENVIRONMENT);
  1052         setEnvSlot(var);
  1053     }
  1054 
  1055     __ pop();
  1056 }
  1057 
  1058 void
  1059 BytecodeCompiler::visit(CallExpression *node)
  1060 {
  1061 #if 0
  1062     Local<Type> funType(zone_, node->callee()->type());
  1063 
  1064     // Sniff out natives, which have a specific opcode and are guaranteed to
  1065     // be called via name proxy.
  1066     NamedFunction *native = NULL;
  1067     if (funType->isNative())
  1068         native = node->callee()->toNameProxy()->binding()->toNamedFunction();
  1069 
  1070     Local<Type> given(zone_);
  1071     for (size_t i = node->arguments()->length() - 1; i < node->arguments()->length(); i--) {
  1072         Expression *arg = node->arguments()->at(i);
  1073 
  1074         given = arg->type();
  1075 
  1076         // We need to compute a reference if the parameter was in the form:
  1077         //  f(&a)
  1078         // Note this form does not allow: f({})
  1079         // 
  1080         // We also need to compute references for all variadic native
  1081         // arguments, but arrays and references are already in the
  1082         // appropriate form.
  1083         bool mustPushReference = false;
  1084         if (i >= funType->parameters()->length()) {
  1085             assert(funType->isNative() && funType->isNativeVariadic());
  1086             mustPushReference = !given->isArray() && !given->isReference();
  1087         } else if (funType->parameterAt(i)->isReference()) {
  1088             mustPushReference = !given->isReference();
  1089         }
  1090 
  1091         // If a native is passed to a native, it must only be one level deep.
  1092         assert(!funType->isNative() || !given->isArray() || given->levels() == 1);
  1093 
  1094         if (mustPushReference) {
  1095             if (arg->isNameProxy()) {
  1096                 // :TODO: test with functions and globals
  1097                 // Compute a reference to the name.
  1098                 Variable *var = arg->toNameProxy()->binding()->toVariable();
  1099                 __ note_position(node->pos());
  1100                 __ newref(var);
  1101             } else if (arg->isFieldExpression()) {
  1102                 FieldExpression *expr = arg->toFieldExpression();
  1103                 expr->left()->accept(this);
  1104                 __ note_position(expr->pos());
  1105                 __ fieldref_lifo(expr->fieldIndex());
  1106             } else {
  1107                 // We don't know how to, or can't, build a direct reference to
  1108                 // this type. Make an indirect one, by taking the top of the
  1109                 // stack and boxing it up.
  1110                 arg->accept(this);
  1111                 __ note_position(node->pos());
  1112                 __ slotref_lifo();
  1113             }
  1114         } else {
  1115             arg->accept(this);
  1116         }
  1117     }
  1118 
  1119     unsigned argc = node->arguments()->length();
  1120 
  1121     // If there are missing arguments, then we're not done and have to push
  1122     // default parameters.
  1123     Local<Box> box(zone_);
  1124     Local<Array> array(zone_);
  1125     Local<ArrayMap> map(zone_);
  1126     for (size_t i = node->arguments()->length(); i < funType->parameters()->length(); i++) {
  1127         box = Box::cast(funType->defaults()->at(i));
  1128 
  1129         if (box->type()->isPod()) {
  1130             if (box->type()->pod() == PrimitiveType_Int32)
  1131                 __ int_(box->toInt32());
  1132             else if (box->type()->pod() == PrimitiveType_Float)
  1133                 __ float_(box->toFloat());
  1134             else
  1135                 assert(false);
  1136 
  1137             if (funType->parameterAt(i)->isReference()) {
  1138                 __ note_position(node->pos());
  1139                 __ slotref_lifo();
  1140             }
  1141         } else {
  1142             assert(box->type()->isArray());
  1143 
  1144             array = Array::cast(box->toObject());
  1145             if (funType->parameterAt(i)->isConst()) {
  1146                 __ object(array);
  1147             } else {
  1148                 // We need to copy the array since it's mutable. Note that
  1149                 // although COPYARRAY returns its left-hand side, this may
  1150                 // change in the future, we do the same thing and dupe the
  1151                 // newly allocated array.
  1152                 map = ArrayMap::cast(array->map());
  1153                 
  1154                 // Natives cannot escape array references, so we can allocate
  1155                 // them on the LIFO stack.
  1156                 if (funType->isNative())
  1157                     __ newarray(OP_NEWFIXED, map, Heap::Tenure_Stack);
  1158                 else
  1159                     __ newarray(OP_NEWFIXED, map, Heap::Tenure_Default);
  1160                 __ dup();
  1161                 __ object(array);
  1162                 __ copyarray();
  1163                 __ pop();
  1164             }
  1165         }
  1166 
  1167         argc++;
  1168     }
  1169 
  1170     __ note_position(node->pos());
  1171     if (native) {
  1172         __ callnative(native->slot(), argc);
  1173         __ drop(argc);
  1174     } else {
  1175         node->callee()->accept(this);
  1176         __ call(funType);
  1177         __ drop(argc + 1);
  1178     }
  1179 #endif
  1180 }
  1181 
  1182 void
  1183 BytecodeCompiler::visit(TernaryExpression *node)
  1184 {
  1185     Label success, failure, join;
  1186 
  1187     visitForTest(node->condition(), &success, &failure, &success);
  1188     __ bind(&success);
  1189     node->left()->accept(this);
  1190     __ drop(1);
  1191     __ jump(&join);
  1192     __ bind(&failure);
  1193     node->right()->accept(this);
  1194     __ bind(&join);
  1195 }
  1196 
  1197 void
  1198 BytecodeCompiler::visit(IfStatement *node)
  1199 {
  1200     Label join;
  1201     if (!node->ifFalse()) {
  1202         Label success;
  1203 
  1204         visitForTest(node->condition(), &success, &join, &success);
  1205         __ bind(&success);
  1206         node->ifTrue()->accept(this);
  1207     } else {
  1208         Label success, next;
  1209 
  1210         visitForTest(node->condition(), &success, &next, &success);
  1211         __ bind(&success);
  1212         node->ifTrue()->accept(this);
  1213         __ jump(&join);
  1214         __ bind(&next);
  1215         node->ifFalse()->accept(this);
  1216     }
  1217 
  1218     __ bind(&join);
  1219 }
  1220 
  1221 bool
  1222 BytecodeCompiler::tableswitch(SwitchStatement *node)
  1223 {
  1224     CaseValueList *values = node->caseValueList();
  1225 
  1226     if (values->length() < 3)
  1227         return false;
  1228 
  1229     // Find the delta between the largest and smallest value.
  1230     int hi = values->at(values->length() - 1).box.toInt();
  1231     int lo = values->at(0).box.toInt();
  1232     assert(hi > lo);
  1233 
  1234     unsigned tablesize = TableSwitchEntries(lo, hi);
  1235     if (tablesize > MAX_TABLESWITCH_ENTRIES)
  1236         return false;
  1237 
  1238     Label def, join;
  1239 
  1240     // Create the list of labels that each statement will bind to.
  1241     Label *labels = new Label[node->cases()->length()];
  1242 
  1243     // Create the table of labels we'll use for each case.
  1244     Label **table = new Label *[tablesize];
  1245 
  1246     // Link all cases, by default, to the default label.
  1247     for (size_t i = 0; i < tablesize; i++)
  1248         table[i] = &def;
  1249 
  1250     // Now patch actual cases to their correct labels.
  1251     for (size_t i = 0; i < values->length(); i++) {
  1252         CaseValue &v = values->at(i);
  1253         assert(v.statement < node->cases()->length());
  1254 
  1255         unsigned index = unsigned(v.box.toInt() - lo);
  1256         assert(index < tablesize);
  1257 
  1258         table[index] = &labels[v.statement];
  1259     }
  1260 
  1261     // Emit the tableswitch opcode and the jump table.
  1262     __ tableswitch(lo, hi, &def, table);
  1263 
  1264     // We're done with the jump table now.
  1265     delete [] table;
  1266 
  1267     // Emit each statement.
  1268     for (size_t i = 0; i < node->cases()->length(); i++) {
  1269         Statement *stmt = node->cases()->at(i)->statement();
  1270 
  1271         __ bind(&labels[i]);
  1272         stmt->accept(this);
  1273         __ jump(&join);
  1274     }
  1275 
  1276     // We're done with the statement labels.
  1277     delete [] labels;
  1278 
  1279     // Emit the default case.
  1280     __ bind(&def);
  1281     if (node->defaultCase())
  1282         node->defaultCase()->accept(this);
  1283 
  1284     __ bind(&join);
  1285 
  1286     return true;
  1287 }
  1288 
  1289 void
  1290 BytecodeCompiler::visit(SwitchStatement *node)
  1291 {
  1292     node->expression()->accept(this);
  1293 
  1294     if (tableswitch(node))
  1295         return;
  1296 
  1297     Label join;
  1298 
  1299     for (size_t i = 0; i < node->cases()->length(); i++) {
  1300         Case *c = node->cases()->at(i);
  1301 
  1302         Label success, fail;
  1303         if (c->others()) {
  1304             for (size_t j = 0; j < c->others()->length(); j++) {
  1305                 Expression *expr = c->others()->at(j);
  1306 
  1307                 __ dup();
  1308                 expr->accept(this);
  1309                 __ j(OP_JEQ, &success);
  1310             }
  1311         }
  1312 
  1313         // The final test.
  1314         __ dup();
  1315         c->expression()->accept(this);
  1316         __ j(OP_JNE, &fail);
  1317         __ bind(&success);
  1318         c->statement()->accept(this);
  1319         __ jump(&join);
  1320         __ bind(&fail);
  1321     }
  1322 
  1323     if (node->defaultCase())
  1324         node->defaultCase()->accept(this);
  1325 
  1326     __ pop();
  1327     __ bind(&join);
  1328 }
  1329 
  1330 void
  1331 BytecodeCompiler::visit(FunctionStatement *node)
  1332 {
  1333     if (!node->fun()->used())
  1334         return;
  1335 
  1336     if (node->fun()->isNative()) {
  1337         assert(!moduleData_->natives->at(node->fun()->slot()));
  1338 
  1339         Local<FunctionType> type(zone_, FunctionType::cast(node->fun()->type()));
  1340         Local<String> name(zone_, node->fun()->name());
  1341         Local<Native> native(zone_, Native::New(zone_, type, name));
  1342         if (!native)
  1343             return;
  1344 
  1345         moduleData_->natives->set(zone_, node->fun()->slot(), native);
  1346         return;
  1347     }
  1348 
  1349     // If the function has no body, then it's just a declaration.
  1350     if (!node->body()) {
  1351         assert(node->fun()->isForward() || node->fun()->isPublic());
  1352         return;
  1353     }
  1354 
  1355     BytecodeCompiler child(zone_, tree_, moduleData_);
  1356     Local<Function> fun(zone_, child.compileFunction(moduleData_, node));
  1357     if (!fun)
  1358         return;
  1359     
  1360     assert(!moduleData_->module->getFunction(node->fun()->slot()));
  1361     moduleData_->module->setFunction(zone_, node->fun()->slot(), fun);
  1362 }
  1363 
  1364 void
  1365 BytecodeCompiler::visit(FunctionTypeStatement *node)
  1366 {
  1367 }
  1368 
  1369 void
  1370 BytecodeCompiler::visit(EnumStatement *node)
  1371 {
  1372 }
  1373 
  1374 void
  1375 BytecodeCompiler::visit(StructureStatement *node)
  1376 {
  1377 }
  1378 
  1379 void
  1380 BytecodeCompiler::visit(ArrayLiteral *node)
  1381 {
  1382     // We shouldn't reach these; they're handled manually when initializing
  1383     // declared arrays.
  1384     assert(false);
  1385 }
  1386 
  1387 void
  1388 BytecodeCompiler::visit(ImportStatement *node)
  1389 {
  1390 }
  1391 
  1392 Code *
  1393 BytecodeCompiler::compileCode(Scope *scope, unsigned lineno)
  1394 {
  1395     // STOP doubles as RETURNVOID.
  1396     __ stop();
  1397 
  1398     if (__ oom() || zone_->hasPendingException())
  1399         return NULL;
  1400 
  1401     Local<ByteArray> bytes(zone_, ByteArray::New(zone_, __ length() * sizeof(bytecode), Heap::Tenure_Old));
  1402     if (!bytes)
  1403         return NULL;
  1404     memcpy(bytes->raw(), __ buffer(), __ length());
  1405 
  1406     for (size_t i = 0; i < scope->maxContainedLocals(); i++)
  1407         assert(locals_->at(i));
  1408 
  1409     Local<FixedArray> objects(zone_, FixedArray::New(zone_, __ objects()->length(), Heap::Tenure_Old));
  1410     if (!objects)
  1411         return NULL;
  1412 
  1413     for (size_t i = 0; i < __ objects()->length(); i++)
  1414         objects->set(zone_, i, *(__ objects()->at(i)));
  1415 
  1416     Local<ByteArray> safepoints(zone_);
  1417 
  1418     // If any stack slots hold gc pointers at potential failure points in the
  1419     // bytecode, record them now. We do this by building a list of tuples;
  1420     // each tuple contains the pc offset, and a bitset containing which stack
  1421     // slots must be scanned by the gc.
  1422     if (__ oopRecords()->length()) {
  1423         size_t bytesPerSafepoint = Code::BytesPerSafepoint(__ maxStackDepth());
  1424         size_t gcmapSize = bytesPerSafepoint * __ oopRecords()->length();
  1425         safepoints = ByteArray::New(zone_, gcmapSize, Heap::Tenure_Old);
  1426         if (!safepoints)
  1427             return NULL;
  1428 
  1429         Address cursor = safepoints->raw();
  1430         for (size_t i = 0; i < __ oopRecords()->length(); i++) {
  1431             OopRecord *record = __ oopRecords()->at(i);
  1432             assert(record->depth <= __ maxStackDepth());
  1433 
  1434             *reinterpret_cast<unsigned *>(cursor) = record->offset;
  1435 
  1436             unsigned char *bits = reinterpret_cast<unsigned char *>(cursor + sizeof(unsigned));
  1437             for (unsigned i = 0; i < record->depth; i++)
  1438                 bits[i / 8] |= (1 << (i % 8));
  1439 
  1440             cursor += bytesPerSafepoint;
  1441         }
  1442 
  1443         assert(cursor == safepoints->raw() + gcmapSize);
  1444     }
  1445 
  1446     Local<ByteArray> sourcemap(zone_);
  1447     if (__ sourcemapLength()) {
  1448         sourcemap = ByteArray::New(zone_, __ sourcemapLength(), Heap::Tenure_Old);
  1449         if (!sourcemap)
  1450             return NULL;
  1451 
  1452         memcpy(sourcemap->raw(), __ sourcemap(), __ sourcemapLength());
  1453     }
  1454 
  1455     Local<Code> code(zone_);
  1456 
  1457     code = Code::New(zone_,
  1458                      bytes,
  1459                      locals_,
  1460                      objects,
  1461                      __ maxStackDepth(),
  1462                      moduleData_->module,
  1463                      safepoints,
  1464                      sourcemap,
  1465                      lineno);
  1466     return code;
  1467 }
  1468 
  1469 Function *
  1470 BytecodeCompiler::compileFunction(ModuleData *module, FunctionStatement *node)
  1471 {
  1472     // Note: No need to record a life slot here, since it's part of the Frame.
  1473     AutoEnterScope functionScope(this, node->scope());
  1474 
  1475     // Set the initial line, because line mappings are deltas.
  1476     __ setFirstLine(node->pos().line);
  1477     locals_ = FixedArray::New(zone_, node->scope()->maxContainedLocals(), Heap::Tenure_Old);
  1478 
  1479     node->body()->accept(this);
  1480 
  1481     unsigned nargs = node->scope()->numArguments();
  1482     Local<FixedArray> args(zone_, FixedArray::New(zone_, nargs, Heap::Tenure_Old));
  1483     if (!args)
  1484         return NULL;
  1485 
  1486     for (size_t i = 0; i < node->scope()->numArguments(); i++)
  1487         args->set(zone_, i, node->scope()->getArgument(i)->type());
  1488 
  1489 
  1490     Local<Code> code(zone_, compileCode(node->scope(), node->pos().line));
  1491     if (!code)
  1492         return NULL;
  1493 
  1494     Local<FunctionType> type(zone_, FunctionType::cast(node->fun()->type()));
  1495     Local<String> name(zone_, node->fun()->name());
  1496     Local<Function> fun(zone_, Function::New(zone_, code, type, name, node->pos()));
  1497     if (!fun)
  1498         return NULL;
  1499 
  1500     // If this function had a forward, export it as a named public.
  1501     if (node->fun()->isPublic()) {
  1502         assert(node->fun()->isPublic());
  1503         ScopedRoot<Function> root(fun);
  1504         if (!root)
  1505             return NULL;
  1506         if (!moduleData_->publics.append(root))
  1507             return NULL;
  1508     }
  1509 
  1510 #ifndef NDEBUG
  1511     Disassemble(code, stdout);
  1512 #endif
  1513     
  1514     return fun;
  1515 }
  1516 
  1517 Module *
  1518 BytecodeCompiler::compile()
  1519 {
  1520     AutoEnterScope scope(this, tree_->globalScope());
  1521 
  1522     ModuleData moduleData;
  1523 
  1524     moduleData_ = &moduleData;
  1525     moduleData_->module = Module::New(zone_, tree_->globalScope()->numFunctions());
  1526 
  1527     if (!moduleData_)
  1528         return NULL;
  1529     
  1530     moduleData_->natives = FixedArray::New(zone_, tree_->globalScope()->numNatives(), Heap::Tenure_Old);
  1531     if (!moduleData_->natives)
  1532         return NULL;
  1533 
  1534     for (size_t i = 0; i < tree_->statements()->length(); i++) {
  1535         Statement *statement = tree_->statements()->at(i);
  1536         statement->accept(this);
  1537     }
  1538 
  1539     if (zone_->hasPendingException())
  1540         return NULL;
  1541 
  1542 #ifndef NDEBUG
  1543     for (size_t i = 0; i < tree_->globalScope()->numFunctions(); i++)
  1544         assert(moduleData_->module->getFunction(i));
  1545     for (size_t i = 0; i < tree_->globalScope()->numNatives(); i++)
  1546         assert(moduleData_->natives->at(i));
  1547 #endif
  1548 
  1549     if (moduleData_->publics.length()) {
  1550         Local<Function> fun(zone_);
  1551         Local<FixedArray> list(zone_, FixedArray::New(zone_, moduleData_->publics.length(),
  1552                                Heap::Tenure_Old));
  1553         if (!list)
  1554             return NULL;
  1555 
  1556         for (size_t i = 0; i < moduleData_->publics.length(); i++)
  1557             list->set(zone_, i, moduleData_->publics[i]);
  1558 
  1559         moduleData_->module->setPublics(list);
  1560     }
  1561 
  1562     moduleData_->module->setNatives(moduleData_->natives);
  1563 
  1564     if (scope_->numEnvironmentVars()) {
  1565         Local<EnvironmentMap> globalMap(zone_, scope_->createEnvironmentMap(zone_));
  1566         if (!globalMap)
  1567             return NULL;
  1568 
  1569         Local<Environment> environment(zone_, Environment::New(zone_, globalMap));
  1570         if (!environment)
  1571             return NULL;
  1572 
  1573         moduleData_->module->setEnvironment(environment);
  1574     }
  1575 
  1576     Local<Code> code(zone_, compileCode(tree_->globalScope(), 1));
  1577     if (!code)
  1578         return NULL;
  1579 
  1580     Disassemble(code, stdout);
  1581 
  1582     moduleData_->module->setCode(code);
  1583 
  1584     return moduleData_->module;
  1585 }