src/BytecodeCompiler.cpp
author David Anderson <dvander@alliedmods.net>
Sun Aug 05 21:24:41 2012 -0700 (2012-08-05)
changeset 168 4d0fff61d65e
parent 164 3bf7c007883d
child 169 0456a16c2a63
permissions -rw-r--r--
Added runtime support for default arguments.
     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 void
   203 BytecodeCompiler::visit(Assignment *node)
   204 {
   205     Local<Type> type(zone_, node->expression()->type());
   206 
   207     // The first step is three sub-steps:
   208     //
   209     //   (1) Bind the left-hand side.
   210     //   -- If a cumulative operation (+=, etc):
   211     //   (2) Save a copy of the binding on the stack.
   212     //   (3) Dereference the binding to get a value.
   213     //
   214     if (node->lvalue()->isNameProxy()) {
   215         NameProxy *proxy = node->lvalue()->toNameProxy();
   216         Variable *var = proxy->binding()->toVariable();
   217 
   218         // Bind.
   219         if (var->type()->isReference() ||
   220             var->type()->isArray() ||
   221             var->type()->isStruct())
   222         {
   223             __ get(var);
   224         }
   225 
   226         // Get the value if needed.
   227         if (node->token() != TOK_ASSIGN) {
   228             // += etc is not allowed on arrays.
   229             assert(!var->type()->isArray());
   230 
   231             if (var->type()->isReference()) {
   232                 __ dup();
   233                 __ getref(var->type()->contained());
   234             } else {
   235                 __ get(var);
   236             }
   237         }
   238     } else if (node->lvalue()->isFieldExpression()) {
   239         FieldExpression *expr = node->lvalue()->toFieldExpression();
   240         __ note_position(expr->pos());
   241 
   242         expr->left()->accept(this);
   243 
   244         if (node->token() != TOK_ASSIGN)
   245             __ dup();
   246 
   247         if (node->token() != TOK_ASSIGN || (type->isStruct() || type->isArray()))
   248             __ getfield(expr->fieldIndex(), expr->type());
   249     } else {
   250         IndexExpression *index = node->lvalue()->toIndexExpression();
   251         __ note_position(index->pos());
   252 
   253         index->left()->accept(this);
   254         index->right()->accept(this);
   255 
   256         if (node->token() != TOK_ASSIGN)
   257             __ dup2();
   258 
   259         if (node->token() != TOK_ASSIGN || (type->isStruct() || type->isArray()))
   260             __ getelem(index->type());
   261     }
   262 
   263     if (node->token() == TOK_ASSIGN) {
   264         node->expression()->accept(this);
   265     } else {
   266         visitForALU(node->type(), node->expression());
   267 
   268         TokenKind alu = TokenKind(int(node->token()) - (TOK_ASSIGN_ADD - TOK_PLUS));
   269         __ note_position(node->pos());
   270         __ binary(TokenToOpcode(alu));
   271     }
   272 
   273     // Emit the store.
   274     if (type->isArray()) {
   275         // Unlike references, which can only be computed from a NamePRoxy,
   276         // arrays can be computed from multiple lvalue types.
   277         __ note_position(node->pos());
   278         __ copyarray();
   279     } else if (type->isStruct()) {
   280         // Structs have value semantics, so emit a full copy. We don't break
   281         // this down into u-ops, to avoid unnecessary bytecode explosion.
   282         __ note_position(node->pos());
   283         __ copystruct();
   284     } else if (node->lvalue()->isNameProxy()) {
   285         NameProxy *proxy = node->lvalue()->toNameProxy();
   286         Variable *var = proxy->binding()->toVariable();
   287 
   288         if (var->type()->isReference())
   289             __ setref(var->type()->contained());
   290         else
   291             __ set(var);
   292     } else if (node->lvalue()->isFieldExpression()) {
   293         FieldExpression *expr = node->lvalue()->toFieldExpression();
   294         __ setfield(expr->fieldIndex(), expr->type());
   295     } else {
   296         IndexExpression *index = node->lvalue()->toIndexExpression();
   297         __ setelem(index->type());
   298     }
   299 }
   300 
   301 void
   302 BytecodeCompiler::visit(IncDecExpression *node)
   303 {
   304     // In the postfix case, the logic looks like:
   305     //      (1) Bind       -> REF
   306     //      (2) Dup        -> REF REF
   307     //      (3) Fetch      -> REF VAL
   308     //      (4) Swap       -> VAL REF
   309     //      (5) Pick       -> VAL REF VAL
   310     //      (6) Add        -> VAL REF VAL+1
   311     //      (7) Store      -> VAL VAL+1
   312     //      (8) Drop       -> VAL
   313     //
   314     // In the prefix case, the logic looks like:
   315     //      (1) Bind       -> REF
   316     //      (2) Dup        -> REF REF
   317     //      (3) Fetch      -> REF VAL
   318     //      --
   319     //      --
   320     //      (6) Add        -> REF VAL+1
   321     //      (7) Store      -> VAL+1
   322     //      --
   323     //
   324     // This is squirrely enough such that we don't bother sharing too much
   325     // with the above.
   326     // 
   327     // Note: We simulate a "Pick" operation with a dup2+pop.
   328 
   329     // This is steps (1) to (5).
   330     Expression *expr = node->expression();
   331     if (expr->isNameProxy()) {
   332         NameProxy *proxy = expr->toNameProxy();
   333         Variable *var = proxy->binding()->toVariable();
   334 
   335         // Bind.
   336         if (var->type()->isReference() || var->type()->isArray())
   337             __ get(var);
   338 
   339         // Dup and fetch.
   340         if (var->type()->isReference()) {
   341             __ dup();
   342             __ getref(node->type());
   343             if (node->postfix()) {
   344                 __ swap();
   345                 __ pick2();
   346             }
   347         } else {
   348             assert(!var->type()->isArray());
   349             __ get(var);
   350             if (node->postfix())
   351                 __ dup();
   352         }
   353     } else if (expr->isFieldExpression()) {
   354         FieldExpression *field = expr->toFieldExpression();
   355 
   356         field->left()->accept(this);
   357         __ dup();
   358         __ getfield(field->fieldIndex(), field->type());
   359 
   360         if (node->postfix()) {
   361             // The stack looks like this now:
   362             // OBJECT VALUE
   363             __ swap();          // VALUE OBJECT
   364             __ pick2();         // VALUE OBJECT VALUE
   365         }
   366     } else {
   367         IndexExpression *index = expr->toIndexExpression();
   368         __ note_position(index->pos());
   369 
   370         index->left()->accept(this);
   371         index->right()->accept(this);
   372 
   373         assert(!node->type()->isArray());
   374         __ dup2();
   375         __ getelem(node->type());
   376 
   377         if (node->postfix()) {
   378             // The stack looks like this now:
   379             // ARRAY INDEX VALUE
   380             //
   381             // So we must use a PICK operation to rotate the stack into position.
   382             __ roll3();         // INDEX VALUE ARRAY
   383             __ roll3();         // VALUE ARRAY INDEX
   384             __ pick3();         // VALUE ARRAY INDEX VALUE
   385         }
   386     }
   387 
   388     // Perform step (6).
   389     if (node->type()->isFloat()) {
   390         __ float_(1.0);
   391     } else {
   392         assert(node->type()->isInt32());
   393         __ int_(1);
   394     }
   395 
   396     __ note_position(node->pos());
   397     if (node->token() == TOK_INCREMENT)
   398         __ binary(OP_ADD);
   399     else
   400         __ binary(OP_SUB);
   401 
   402     // Perform step (7).
   403     if (expr->isNameProxy()) {
   404         NameProxy *proxy = expr->toNameProxy();
   405         Variable *var = proxy->binding()->toVariable();
   406 
   407         if (var->type()->isReference())
   408             __ setref(node->type());
   409         else
   410             __ set(var);
   411     } else if (expr->isFieldExpression()) {
   412         FieldExpression *field = expr->toFieldExpression();
   413         __ setfield(field->fieldIndex(), field->type());
   414     } else {
   415         assert(expr->isIndexExpression());
   416         __ setelem(node->type());
   417     }
   418 
   419     // Perform step (8).
   420     if (node->postfix())
   421         __ pop();
   422 }
   423 
   424 void
   425 BytecodeCompiler::visitForALU(Type *needed, Expression *node)
   426 {
   427     node->accept(this);
   428     if (needed->isFloat() && !node->type()->isFloat())
   429         __ cvt_i2f();
   430     else
   431         assert(needed->primitive() == node->type()->primitive());
   432 }
   433 
   434 static inline Type *
   435 GetCoercionType(TokenKind tok, Type *left, Type *right)
   436 {
   437     if (left->isFloat())
   438         return left;
   439     return right;
   440 }
   441 
   442 void
   443 BytecodeCompiler::visit(UnaryExpression *node)
   444 {
   445     Local<Type> out(zone_, ((Expression *)node)->type());
   446 
   447     switch (node->token()) {
   448       case TOK_MINUS:
   449       {
   450         Local<Type> type(zone_, node->expression()->type());
   451         node->expression()->accept(this);
   452         
   453         if (out->isFloat())
   454             __ neg_f();
   455         else
   456             __ neg();
   457         break;
   458       }
   459 
   460       case TOK_NOT:
   461       {
   462         Local<Type> type(zone_, node->expression()->type());
   463         node->expression()->accept(this);
   464         
   465         if (out->isFloat())
   466             __ not_f();
   467         else
   468             __ not_();
   469         break;
   470       }
   471 
   472       case TOK_LABEL:
   473       {
   474         Local<Type> from(zone_, node->expression()->type());
   475 
   476         node->expression()->accept(this);
   477         if (!from->isFloat() && out->isFloat())
   478             __ bits_f2i();
   479         else if (from->isFloat() && !out->isFloat())
   480             __ bits_i2f();
   481         break;
   482       }
   483 
   484       default:
   485         assert(node->token() == TOK_TILDE);
   486         node->expression()->accept(this);
   487         __ bitnot();
   488         break;
   489     }
   490 }
   491 
   492 void
   493 BytecodeCompiler::visit(BinaryExpression *node)
   494 {
   495     if (node->token() == TOK_AND || node->token() == TOK_OR) {
   496         Label success, failure, done;
   497         visitForTest(node, &success, &failure, &success);
   498         __ bind(&success);
   499         __ int_(1);
   500         __ drop(1);         // Otherwise, the stack depth will be +1 too much.
   501         __ jump(&done);
   502         __ bind(&failure);
   503         __ int_(0);
   504         __ bind(&done);
   505         return;
   506     }
   507 
   508     Local<Type> leftType(zone_, node->left()->type());
   509     Local<Type> rightType(zone_, node->right()->type());
   510     Local<Type> coerce(zone_, GetCoercionType(node->token(), leftType, rightType));
   511 
   512     visitForALU(coerce, node->left());
   513     visitForALU(coerce, node->right());
   514 
   515     Opcode op = TokenToOpcode(node->token());
   516     if (node->type()->isFloat())
   517         op = (Opcode)(int(op) + (OP_ADD_F - OP_ADD));
   518 
   519     __ note_position(node->pos());
   520     __ binary(op);
   521 }
   522 
   523 void
   524 BytecodeCompiler::visit(IndexExpression *node)
   525 {
   526     node->left()->accept(this);
   527     node->right()->accept(this);
   528     __ note_position(node->pos());
   529     __ getelem(node->type());
   530 }
   531 
   532 void
   533 BytecodeCompiler::visit(FieldExpression *node)
   534 {
   535     node->left()->accept(this);
   536     __ getfield(node->fieldIndex(), node->type());
   537 }
   538 
   539 void
   540 BytecodeCompiler::visit(ReturnStatement *node)
   541 {
   542     if (node->expression()) {
   543         node->expression()->accept(this);
   544         __ return_();
   545     } else {
   546         __ returnvoid();
   547     }
   548 }
   549 
   550 void
   551 BytecodeCompiler::visitForTest(Expression *expression,
   552                                Label *trueBranch,
   553                                Label *falseBranch,
   554                                Label *fallthrough)
   555 {
   556     TokenKind token = ToCompare(expression);
   557     if (token == TOK_EOF || token == TOK_NOT) {
   558         if (token == TOK_EOF)
   559             expression->accept(this);
   560         else
   561             expression->toUnaryExpression()->expression()->accept(this);
   562         
   563         bool jumpOnTrue = (fallthrough == falseBranch) ^ (token == TOK_NOT);
   564 
   565         Opcode op = jumpOnTrue ? OP_JT : OP_JF;
   566         if (expression->type()->isFloat())
   567             op = (Opcode)(int(op) + (OP_JL_F - OP_JL));
   568 
   569         if (fallthrough == falseBranch)
   570             __ j(op, trueBranch);
   571         else
   572             __ j(op, falseBranch); 
   573         return;
   574     }
   575 
   576     BinaryExpression *binary = expression->toBinaryExpression();
   577 
   578     if (token == TOK_AND || token == TOK_OR) {
   579         Label next;
   580         if (token == TOK_AND)
   581             visitForTest(binary->left(), &next, falseBranch, &next);
   582         else
   583             visitForTest(binary->left(), trueBranch, &next, &next);
   584         __ bind(&next);
   585         visitForTest(binary->right(), trueBranch, falseBranch, fallthrough);
   586         return;
   587     }
   588 
   589     Opcode op = CompareTokenToJump(token);
   590     if (fallthrough == trueBranch)
   591         op = Invert(op);
   592 
   593     Local<Type> leftType(zone_, binary->left()->type());
   594     Local<Type> rightType(zone_, binary->right()->type());
   595     Local<Type> coerce(zone_, GetCoercionType(binary->token(), leftType, rightType));
   596 
   597     visitForALU(coerce, binary->left());
   598     visitForALU(coerce, binary->right());
   599     if (coerce->isFloat())
   600         op = (Opcode)(int(op) + (OP_JL_F - OP_JL));
   601 
   602     if (fallthrough == trueBranch)
   603         __ j(op, falseBranch);
   604     else
   605         __ j(op, trueBranch);
   606 }
   607 
   608 void
   609 BytecodeCompiler::visit(ForStatement *node)
   610 {
   611     AutoEnterScope forScope(this, node->scope());
   612 
   613     recordLifoSlot(node->scope());
   614 
   615     Label join, update;
   616     LoopScope loop(scope_, &join, &update, &loop_);
   617 
   618     if (node->initialization())
   619         node->initialization()->accept(this);
   620 
   621     Label header, test;
   622     if (node->condition())
   623         __ jump(&test);
   624 
   625     __ bind(&header);
   626     node->body()->accept(this);
   627 
   628     __ bind(&update);
   629     if (node->update())
   630         node->update()->accept(this);
   631 
   632     if (node->condition()) {
   633         __ bind(&test);
   634         visitForTest(node->condition(), &header, &join, &join);
   635     } else {
   636         __ jump(&header);
   637     }
   638 
   639     __ bind(&join);
   640 
   641     if (node->scope())
   642         unwindTo(node->scope()->enclosing());
   643     assert(__ stackDepth() == 0);
   644 }
   645 
   646 void
   647 BytecodeCompiler::visit(WhileStatement *node)
   648 {
   649     Label header, join;
   650 
   651     __ bind(&header);
   652 
   653     LoopScope loop(scope_, &join, &header, &loop_);
   654 
   655     if (node->token() == TOK_WHILE) {
   656         Label body;
   657 
   658         visitForTest(node->condition(), &body, &join, &body);
   659         __ bind(&body);
   660         node->body()->accept(this);
   661         __ jump(&header);
   662     } else {
   663         node->body()->accept(this);
   664         visitForTest(node->condition(), &header, &join, &join);
   665     }
   666 
   667     __ bind(&join);
   668 }
   669 
   670 void
   671 BytecodeCompiler::visit(BreakStatement *node)
   672 {
   673     unwindTo(loop_->scope());
   674     __ jump(loop_->break_());
   675 }
   676 
   677 void
   678 BytecodeCompiler::visit(ContinueStatement *node)
   679 {
   680     unwindTo(loop_->scope());
   681     __ jump(loop_->continue_());
   682 }
   683 
   684 void
   685 BytecodeCompiler::visit(BlockStatement *node)
   686 {
   687     AutoEnterScope blockScope(this, node->scope());
   688 
   689     recordLifoSlot(node->scope());
   690 
   691     for (size_t i = 0; i < node->statements()->length(); i++) {
   692         Statement *statement = node->statements()->at(i);
   693         statement->accept(this);
   694         assert(__ stackDepth() == 0);
   695     }
   696 
   697     // We don't bother emitting an "unwind" instruction for function scopes,
   698     // since this is taken care of by the calling convention.
   699     if (node->scope() && node->scope()->enclosing()->kind() != Scope::FUNCTION)
   700         unwindTo(node->scope()->enclosing());
   701 }
   702 
   703 void
   704 BytecodeCompiler::visit(IntegerLiteral *node)
   705 {
   706     __ int_(node->value());
   707 }
   708 
   709 void
   710 BytecodeCompiler::visit(BooleanLiteral *node)
   711 {
   712     if (node->token() == TOK_TRUE)
   713         __ true_();
   714     else
   715         __ false_();
   716 }
   717 
   718 void
   719 BytecodeCompiler::visit(FloatLiteral *node)
   720 {
   721     __ float_((float)node->value());
   722 }
   723 
   724 static inline ArrayMap *
   725 BuildArrayMap(Zone *zone, Handle<Type> type)
   726 {
   727     if (type->newMap())
   728         return ArrayMap::cast(type->newMap());
   729 
   730     Local<ArrayMap> map(zone, ArrayMap::New(zone, type));
   731     if (!map)
   732         return NULL;
   733 
   734     // Ensure the inner type has an array map if needed.
   735     if (type->contained()->isArray()) {
   736         Local<Type> contained(zone, type->contained());
   737         if (!BuildArrayMap(zone, contained))
   738             return NULL;
   739     }
   740 
   741     type->setNewMap(map);
   742     return map;
   743 }
   744 
   745 void
   746 BytecodeCompiler::visit(StringLiteral *node)
   747 {
   748     Local<Type> type(zone_, node->type());
   749     Local<ArrayMap> map(zone_, BuildArrayMap(zone_, type));
   750     if (!map)
   751         return;
   752 
   753     Local<Array> array(zone_, Array::New(zone_, map, node->string()->length(), Heap::Tenure_Old));
   754     if (!array)
   755         return;
   756 
   757     assert(array->length() >= node->string()->length());
   758     memcpy(array->chars(), node->string()->raw(), node->string()->length() * sizeof(char));
   759 
   760     __ note_position(node->pos());
   761     __ object(array);
   762 }
   763 
   764 void
   765 BytecodeCompiler::getEnvSlot(Variable *var)
   766 {
   767     assert(var->scope()->kind() == Scope::GLOBAL);
   768     __ getglobal(var);
   769 }
   770 
   771 void
   772 BytecodeCompiler::setEnvSlot(Variable *var)
   773 {
   774     assert(var->scope()->kind() == Scope::GLOBAL);
   775     __ setglobal(var);
   776 }
   777 
   778 void
   779 BytecodeCompiler::visit(VariableDeclaration *node)
   780 {
   781     Variable *var = node->variable();
   782     
   783     Local<Type> type(zone_, var->type());
   784     if (type->isArray()) {
   785         Local<ArrayMap> map(zone_, BuildArrayMap(zone_, type));
   786         __ note_position(node->pos());
   787         if (var->scope()->kind() == Scope::GLOBAL)
   788             __ newarray(map, Heap::Tenure_Old);
   789         else if (var->needsHeapAllocation())
   790             __ newarray(map, Heap::Tenure_Default);
   791         else
   792             __ newarray(map, Heap::Tenure_Stack);
   793 
   794         if (node->initialization()) {
   795             node->initialization()->accept(this);
   796             __ note_position(node->pos());
   797             __ copyarray();
   798         }
   799     } else if (type->isStruct()) {
   800         Local<Map> map(zone_, type->newMap());
   801         if (var->scope()->kind() == Scope::GLOBAL)
   802             __ newstruct(map, Heap::Tenure_Old);
   803         else if (var->needsHeapAllocation())
   804             __ newstruct(map, Heap::Tenure_Default);
   805         else
   806             __ newstruct(map, Heap::Tenure_Stack);
   807     } else {
   808         if (node->initialization()) {
   809             node->initialization()->accept(this);
   810         } else {
   811             if (type->isInt32OrEnum() || type->isBool()) {
   812                 __ int_(0);
   813             } else {
   814                 assert(type->isFloat());
   815                 __ float_(0);
   816             }
   817         }
   818     }
   819 
   820     if (var->location() == Variable::STACK) {
   821         __ setlocal(var);
   822         locals_->set(zone_, var->slot(), var->type());
   823     } else {
   824         assert(var->location() == Variable::ENVIRONMENT);
   825         setEnvSlot(var);
   826     }
   827 
   828     __ pop();
   829 }
   830 
   831 void
   832 BytecodeCompiler::visit(CallExpression *node)
   833 {
   834     Local<Type> funType(zone_, node->callee()->type());
   835 
   836     // Sniff out natives, which have a specific opcode and are guaranteed to
   837     // be called via name proxy.
   838     NamedFunction *native = NULL;
   839     if (funType->isNative()) {
   840         native = node->callee()->toNameProxy()->binding()->toNamedFunction();
   841     }
   842 
   843     Local<Type> given(zone_);
   844     for (size_t i = node->arguments()->length() - 1; i < node->arguments()->length(); i--) {
   845         Expression *arg = node->arguments()->at(i);
   846 
   847         given = arg->type();
   848 
   849         // We need to compute a reference if the parameter was in the form:
   850         //  f(&a)
   851         // Note this form does not allow: f({})
   852         // 
   853         // We also need to compute references for all variadic native
   854         // arguments, but arrays and references are already in the
   855         // appropriate form.
   856         bool mustPushReference = false;
   857         if (i >= funType->parameters()->length()) {
   858             assert(funType->isNative() && funType->isNativeVariadic());
   859             mustPushReference = !given->isArray() && !given->isReference();
   860         } else if (funType->parameterAt(i)->isReference()) {
   861             mustPushReference = !given->isReference();
   862         }
   863 
   864         // If a native is passed to a native, it must only be one level deep.
   865         assert(!funType->isNative() || !given->isArray() || given->levels() == 1);
   866 
   867         if (mustPushReference) {
   868             if (arg->isNameProxy()) {
   869                 // :TODO: test with functions and globals
   870                 // Compute a reference to the name.
   871                 Variable *var = arg->toNameProxy()->binding()->toVariable();
   872                 __ note_position(node->pos());
   873                 __ newref(var);
   874             } else if (arg->isIndexExpression()) {
   875                 IndexExpression *expr = arg->toIndexExpression();
   876                 expr->left()->accept(this);
   877                 expr->right()->accept(this);
   878                 __ note_position(expr->pos());
   879                 __ arrayref_lifo();
   880             } else if (arg->isFieldExpression()) {
   881                 FieldExpression *expr = arg->toFieldExpression();
   882                 expr->left()->accept(this);
   883                 __ note_position(expr->pos());
   884                 __ fieldref_lifo(expr->fieldIndex());
   885             } else {
   886                 // We don't know how to, or can't, build a direct reference to
   887                 // this type. Make an indirect one, by taking the top of the
   888                 // stack and boxing it up.
   889                 arg->accept(this);
   890                 __ note_position(node->pos());
   891                 __ slotref_lifo();
   892             }
   893         } else {
   894             arg->accept(this);
   895         }
   896     }
   897 
   898     unsigned argc = node->arguments()->length();
   899 
   900     // If there are missing arguments, then we're not done and have to push
   901     // default parameters.
   902     Local<Box> box(zone_);
   903     for (size_t i = node->arguments()->length(); i < funType->parameters()->length(); i++) {
   904         box = Box::cast(funType->defaults()->at(i));
   905 
   906         if (box->type()->isPod()) {
   907             if (box->type()->pod() == PrimitiveType_Int32)
   908                 __ int_(box->toInt32());
   909             else if (box->type()->pod() == PrimitiveType_Float)
   910                 __ float_(box->toFloat());
   911             else
   912                 assert(false);
   913         } else {
   914             assert(false);
   915         }
   916 
   917         if (funType->parameterAt(i)->isReference()) {
   918             __ note_position(node->pos());
   919             __ slotref_lifo();
   920         }
   921 
   922         argc++;
   923     }
   924 
   925     __ note_position(node->pos());
   926     if (native) {
   927         __ callnative(native->slot(), argc);
   928         __ drop(argc);
   929     } else {
   930         node->callee()->accept(this);
   931         __ call(funType);
   932         __ drop(argc + 1);
   933     }
   934 }
   935 
   936 void
   937 BytecodeCompiler::visit(TernaryExpression *node)
   938 {
   939     Label success, failure, join;
   940 
   941     visitForTest(node->condition(), &success, &failure, &success);
   942     __ bind(&success);
   943     node->left()->accept(this);
   944     __ drop(1);
   945     __ jump(&join);
   946     __ bind(&failure);
   947     node->right()->accept(this);
   948     __ bind(&join);
   949 }
   950 
   951 void
   952 BytecodeCompiler::visit(IfStatement *node)
   953 {
   954     Label join;
   955     if (!node->ifFalse()) {
   956         Label success;
   957 
   958         visitForTest(node->condition(), &success, &join, &success);
   959         __ bind(&success);
   960         node->ifTrue()->accept(this);
   961     } else {
   962         Label success, next;
   963 
   964         visitForTest(node->condition(), &success, &next, &success);
   965         __ bind(&success);
   966         node->ifTrue()->accept(this);
   967         __ jump(&join);
   968         __ bind(&next);
   969         node->ifFalse()->accept(this);
   970     }
   971 
   972     __ bind(&join);
   973 }
   974 
   975 void
   976 BytecodeCompiler::visit(FunctionStatement *node)
   977 {
   978     if (!node->fun()->used())
   979         return;
   980 
   981     if (node->fun()->isNative()) {
   982         assert(!moduleData_->natives->at(node->fun()->slot()));
   983 
   984         Local<Type> type(zone_, node->fun()->type());
   985         Local<String> name(zone_, node->fun()->name());
   986         Local<Native> native(zone_, Native::New(zone_, type, name));
   987         if (!native)
   988             return;
   989 
   990         moduleData_->natives->set(zone_, node->fun()->slot(), native);
   991         return;
   992     }
   993 
   994     // If the function has no body, then it's just a declaration.
   995     if (!node->body()) {
   996         assert(node->fun()->isForward() || node->fun()->isPublic());
   997         return;
   998     }
   999 
  1000     BytecodeCompiler child(zone_, tree_, moduleData_);
  1001     Local<Function> fun(zone_, child.compileFunction(moduleData_, node));
  1002     if (!fun)
  1003         return;
  1004     
  1005     assert(!moduleData_->module->getFunction(node->fun()->slot()));
  1006     moduleData_->module->setFunction(zone_, node->fun()->slot(), fun);
  1007 }
  1008 
  1009 void
  1010 BytecodeCompiler::visit(EnumStatement *node)
  1011 {
  1012     // :TODO: eventually, we'll export these.
  1013 }
  1014 
  1015 void
  1016 BytecodeCompiler::visit(StructureStatement *node)
  1017 {
  1018 }
  1019 
  1020 Code *
  1021 BytecodeCompiler::compileCode(Scope *scope, unsigned lineno)
  1022 {
  1023     // STOP doubles as RETURNVOID.
  1024     __ stop();
  1025 
  1026     if (__ oom() || zone_->hasPendingException())
  1027         return NULL;
  1028 
  1029     Local<ByteArray> bytes(zone_, ByteArray::New(zone_, __ length() * sizeof(bytecode), Heap::Tenure_Old));
  1030     if (!bytes)
  1031         return NULL;
  1032     memcpy(bytes->raw(), __ buffer(), __ length());
  1033 
  1034     for (size_t i = 0; i < scope->maxContainedLocals(); i++)
  1035         assert(locals_->at(i));
  1036 
  1037     Local<FixedArray> objects(zone_, FixedArray::New(zone_, __ objects()->length(), Heap::Tenure_Old));
  1038     if (!objects)
  1039         return NULL;
  1040 
  1041     for (size_t i = 0; i < __ objects()->length(); i++)
  1042         objects->set(zone_, i, *(__ objects()->at(i)));
  1043 
  1044     Local<ByteArray> safepoints(zone_);
  1045 
  1046     // If any stack slots hold gc pointers at potential failure points in the
  1047     // bytecode, record them now. We do this by building a list of tuples;
  1048     // each tuple contains the pc offset, and a bitset containing which stack
  1049     // slots must be scanned by the gc.
  1050     if (__ oopRecords()->length()) {
  1051         size_t bytesPerSafepoint = Code::BytesPerSafepoint(__ maxStackDepth());
  1052         size_t gcmapSize = bytesPerSafepoint * __ oopRecords()->length();
  1053         safepoints = ByteArray::New(zone_, gcmapSize, Heap::Tenure_Old);
  1054         if (!safepoints)
  1055             return NULL;
  1056 
  1057         Address cursor = safepoints->raw();
  1058         for (size_t i = 0; i < __ oopRecords()->length(); i++) {
  1059             OopRecord *record = __ oopRecords()->at(i);
  1060             assert(record->depth <= __ maxStackDepth());
  1061 
  1062             *reinterpret_cast<unsigned *>(cursor) = record->offset;
  1063 
  1064             unsigned char *bits = reinterpret_cast<unsigned char *>(cursor + sizeof(unsigned));
  1065             for (unsigned i = 0; i < record->depth; i++)
  1066                 bits[i / 8] |= (1 << (i % 8));
  1067 
  1068             cursor += bytesPerSafepoint;
  1069         }
  1070 
  1071         assert(cursor == safepoints->raw() + gcmapSize);
  1072     }
  1073 
  1074     Local<ByteArray> sourcemap(zone_);
  1075     if (__ sourcemapLength()) {
  1076         sourcemap = ByteArray::New(zone_, __ sourcemapLength(), Heap::Tenure_Old);
  1077         if (!sourcemap)
  1078             return NULL;
  1079 
  1080         memcpy(sourcemap->raw(), __ sourcemap(), __ sourcemapLength());
  1081     }
  1082 
  1083     Local<Code> code(zone_);
  1084 
  1085     code = Code::New(zone_,
  1086                      bytes,
  1087                      locals_,
  1088                      objects,
  1089                      __ maxStackDepth(),
  1090                      moduleData_->module,
  1091                      safepoints,
  1092                      sourcemap,
  1093                      lineno);
  1094     return code;
  1095 }
  1096 
  1097 Function *
  1098 BytecodeCompiler::compileFunction(ModuleData *module, FunctionStatement *node)
  1099 {
  1100     // Note: No need to record a life slot here, since it's part of the Frame.
  1101     AutoEnterScope functionScope(this, node->scope());
  1102 
  1103     // Set the initial line, because line mappings are deltas.
  1104     __ setFirstLine(node->pos().line);
  1105     locals_ = FixedArray::New(zone_, node->scope()->maxContainedLocals(), Heap::Tenure_Old);
  1106 
  1107     node->body()->accept(this);
  1108 
  1109     unsigned nargs = node->scope()->numArguments();
  1110     Local<FixedArray> args(zone_, FixedArray::New(zone_, nargs, Heap::Tenure_Old));
  1111     if (!args)
  1112         return NULL;
  1113 
  1114     for (size_t i = 0; i < node->scope()->numArguments(); i++)
  1115         args->set(zone_, i, node->scope()->getArgument(i)->type());
  1116 
  1117 
  1118     Local<Code> code(zone_, compileCode(node->scope(), node->pos().line));
  1119     if (!code)
  1120         return NULL;
  1121 
  1122     Local<Type> type(zone_, node->fun()->type());
  1123     Local<String> name(zone_, node->fun()->name());
  1124     Local<Function> fun(zone_, Function::New(zone_, code, type, name, node->pos()));
  1125     if (!fun)
  1126         return NULL;
  1127 
  1128     // If this function had a forward, export it as a named public.
  1129     if (node->fun()->isPublic()) {
  1130         assert(node->fun()->isPublic());
  1131         ScopedRoot<Function> root(fun);
  1132         if (!root)
  1133             return NULL;
  1134         if (!moduleData_->publics.append(root))
  1135             return NULL;
  1136     }
  1137 
  1138 #ifndef NDEBUG
  1139     Disassemble(code, stdout);
  1140 #endif
  1141     
  1142     return fun;
  1143 }
  1144 
  1145 Module *
  1146 BytecodeCompiler::compile()
  1147 {
  1148     AutoEnterScope scope(this, tree_->scope());
  1149 
  1150     ModuleData moduleData;
  1151 
  1152     moduleData_ = &moduleData;
  1153     moduleData_->module = Module::New(zone_, tree_->scope()->numFunctions());
  1154 
  1155     if (!moduleData_)
  1156         return NULL;
  1157     
  1158     moduleData_->natives = FixedArray::New(zone_, tree_->scope()->numNatives(), Heap::Tenure_Old);
  1159     if (!moduleData_->natives)
  1160         return NULL;
  1161 
  1162     for (size_t i = 0; i < tree_->statements()->length(); i++) {
  1163         Statement *statement = tree_->statements()->at(i);
  1164         statement->accept(this);
  1165     }
  1166 
  1167     if (zone_->hasPendingException())
  1168         return NULL;
  1169 
  1170 #ifndef NDEBUG
  1171     for (size_t i = 0; i < tree_->scope()->numFunctions(); i++)
  1172         assert(moduleData_->module->getFunction(i));
  1173     for (size_t i = 0; i < tree_->scope()->numNatives(); i++)
  1174         assert(moduleData_->natives->at(i));
  1175 #endif
  1176 
  1177     if (moduleData_->publics.length()) {
  1178         Local<Function> fun(zone_);
  1179         Local<FixedArray> list(zone_, FixedArray::New(zone_, moduleData_->publics.length(),
  1180                                Heap::Tenure_Old));
  1181         if (!list)
  1182             return NULL;
  1183 
  1184         for (size_t i = 0; i < moduleData_->publics.length(); i++)
  1185             list->set(zone_, i, moduleData_->publics[i]);
  1186 
  1187         moduleData_->module->setPublics(list);
  1188     }
  1189 
  1190     moduleData_->module->setNatives(moduleData_->natives);
  1191 
  1192     if (scope_->numEnvironmentVars()) {
  1193         Local<EnvironmentMap> globalMap(zone_, scope_->createEnvironmentMap(zone_));
  1194         if (!globalMap)
  1195             return NULL;
  1196 
  1197         Local<Environment> environment(zone_, Environment::New(zone_, globalMap));
  1198         if (!environment)
  1199             return NULL;
  1200 
  1201         moduleData_->module->setEnvironment(environment);
  1202     }
  1203 
  1204     Local<Code> code(zone_, compileCode(tree_->scope(), 1));
  1205     if (!code)
  1206         return NULL;
  1207 
  1208     Disassemble(code, stdout);
  1209 
  1210     moduleData_->module->setCode(code);
  1211 
  1212     return moduleData_->module;
  1213 }