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