src/BytecodeCompiler.cpp
author David Anderson <dvander@alliedmods.net>
Sat Aug 11 12:11:39 2012 -0700 (2012-08-11)
changeset 170 5e4570966ece
parent 169 0456a16c2a63
child 172 48cffae8c9e0
permissions -rw-r--r--
Parser support for public variables.
     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 void
   725 BytecodeCompiler::visit(StringLiteral *node)
   726 {
   727     Local<Type> type(zone_, node->type());
   728     Local<ArrayMap> map(zone_, ArrayMap::Attach(zone_, type));
   729     if (!map)
   730         return;
   731 
   732     Local<Array> array(zone_,
   733         Array::NewString(zone_,
   734                          map,
   735                          node->string()->raw(),
   736                          node->string()->length(),
   737                          Heap::Tenure_Old));
   738     if (!array)
   739         return;
   740 
   741     __ note_position(node->pos());
   742     __ object(array);
   743 }
   744 
   745 void
   746 BytecodeCompiler::getEnvSlot(Variable *var)
   747 {
   748     assert(var->scope()->kind() == Scope::GLOBAL);
   749     __ getglobal(var);
   750 }
   751 
   752 void
   753 BytecodeCompiler::setEnvSlot(Variable *var)
   754 {
   755     assert(var->scope()->kind() == Scope::GLOBAL);
   756     __ setglobal(var);
   757 }
   758 
   759 void
   760 BytecodeCompiler::visit(VariableDeclaration *node)
   761 {
   762     Variable *var = node->variable();
   763     
   764     Local<Type> type(zone_, var->type());
   765     if (type->isArray()) {
   766         Local<ArrayMap> map(zone_, ArrayMap::Attach(zone_, type));
   767         __ note_position(node->pos());
   768         if (var->scope()->kind() == Scope::GLOBAL)
   769             __ newarray(map, Heap::Tenure_Old);
   770         else if (var->needsHeapAllocation())
   771             __ newarray(map, Heap::Tenure_Default);
   772         else
   773             __ newarray(map, Heap::Tenure_Stack);
   774 
   775         if (node->initialization()) {
   776             node->initialization()->accept(this);
   777             __ note_position(node->pos());
   778             __ copyarray();
   779         }
   780     } else if (type->isStruct()) {
   781         Local<Map> map(zone_, type->newMap());
   782         if (var->scope()->kind() == Scope::GLOBAL)
   783             __ newstruct(map, Heap::Tenure_Old);
   784         else if (var->needsHeapAllocation())
   785             __ newstruct(map, Heap::Tenure_Default);
   786         else
   787             __ newstruct(map, Heap::Tenure_Stack);
   788     } else {
   789         if (node->initialization()) {
   790             node->initialization()->accept(this);
   791         } else {
   792             if (type->isInt32OrEnum() || type->isBool()) {
   793                 __ int_(0);
   794             } else {
   795                 assert(type->isFloat());
   796                 __ float_(0);
   797             }
   798         }
   799     }
   800 
   801     if (var->location() == Variable::STACK) {
   802         __ setlocal(var);
   803         locals_->set(zone_, var->slot(), var->type());
   804     } else {
   805         assert(var->location() == Variable::ENVIRONMENT);
   806         setEnvSlot(var);
   807     }
   808 
   809     __ pop();
   810 }
   811 
   812 void
   813 BytecodeCompiler::visit(CallExpression *node)
   814 {
   815     Local<Type> funType(zone_, node->callee()->type());
   816 
   817     // Sniff out natives, which have a specific opcode and are guaranteed to
   818     // be called via name proxy.
   819     NamedFunction *native = NULL;
   820     if (funType->isNative()) {
   821         native = node->callee()->toNameProxy()->binding()->toNamedFunction();
   822     }
   823 
   824     Local<Type> given(zone_);
   825     for (size_t i = node->arguments()->length() - 1; i < node->arguments()->length(); i--) {
   826         Expression *arg = node->arguments()->at(i);
   827 
   828         given = arg->type();
   829 
   830         // We need to compute a reference if the parameter was in the form:
   831         //  f(&a)
   832         // Note this form does not allow: f({})
   833         // 
   834         // We also need to compute references for all variadic native
   835         // arguments, but arrays and references are already in the
   836         // appropriate form.
   837         bool mustPushReference = false;
   838         if (i >= funType->parameters()->length()) {
   839             assert(funType->isNative() && funType->isNativeVariadic());
   840             mustPushReference = !given->isArray() && !given->isReference();
   841         } else if (funType->parameterAt(i)->isReference()) {
   842             mustPushReference = !given->isReference();
   843         }
   844 
   845         // If a native is passed to a native, it must only be one level deep.
   846         assert(!funType->isNative() || !given->isArray() || given->levels() == 1);
   847 
   848         if (mustPushReference) {
   849             if (arg->isNameProxy()) {
   850                 // :TODO: test with functions and globals
   851                 // Compute a reference to the name.
   852                 Variable *var = arg->toNameProxy()->binding()->toVariable();
   853                 __ note_position(node->pos());
   854                 __ newref(var);
   855             } else if (arg->isIndexExpression()) {
   856                 IndexExpression *expr = arg->toIndexExpression();
   857                 expr->left()->accept(this);
   858                 expr->right()->accept(this);
   859                 __ note_position(expr->pos());
   860                 __ arrayref_lifo();
   861             } else if (arg->isFieldExpression()) {
   862                 FieldExpression *expr = arg->toFieldExpression();
   863                 expr->left()->accept(this);
   864                 __ note_position(expr->pos());
   865                 __ fieldref_lifo(expr->fieldIndex());
   866             } else {
   867                 // We don't know how to, or can't, build a direct reference to
   868                 // this type. Make an indirect one, by taking the top of the
   869                 // stack and boxing it up.
   870                 arg->accept(this);
   871                 __ note_position(node->pos());
   872                 __ slotref_lifo();
   873             }
   874         } else {
   875             arg->accept(this);
   876         }
   877     }
   878 
   879     unsigned argc = node->arguments()->length();
   880 
   881     // If there are missing arguments, then we're not done and have to push
   882     // default parameters.
   883     Local<Box> box(zone_);
   884     Local<Array> array(zone_);
   885     Local<ArrayMap> map(zone_);
   886     for (size_t i = node->arguments()->length(); i < funType->parameters()->length(); i++) {
   887         box = Box::cast(funType->defaults()->at(i));
   888 
   889         if (box->type()->isPod()) {
   890             if (box->type()->pod() == PrimitiveType_Int32)
   891                 __ int_(box->toInt32());
   892             else if (box->type()->pod() == PrimitiveType_Float)
   893                 __ float_(box->toFloat());
   894             else
   895                 assert(false);
   896 
   897             if (funType->parameterAt(i)->isReference()) {
   898                 __ note_position(node->pos());
   899                 __ slotref_lifo();
   900             }
   901         } else {
   902             assert(box->type()->isArray());
   903 
   904             array = Array::cast(box->toObject());
   905             if (funType->parameterAt(i)->isConst()) {
   906                 __ object(array);
   907             } else {
   908                 // We need to copy the array since it's mutable. Note that
   909                 // although COPYARRAY returns its left-hand side, this may
   910                 // change in the future, we do the same thing and dupe the
   911                 // newly allocated array.
   912                 map = ArrayMap::cast(array->map());
   913                 __ newarray(map, Heap::Tenure_Stack);
   914                 __ dup();
   915                 __ object(array);
   916                 __ copyarray();
   917                 __ pop();
   918             }
   919         }
   920 
   921         argc++;
   922     }
   923 
   924     __ note_position(node->pos());
   925     if (native) {
   926         __ callnative(native->slot(), argc);
   927         __ drop(argc);
   928     } else {
   929         node->callee()->accept(this);
   930         __ call(funType);
   931         __ drop(argc + 1);
   932     }
   933 }
   934 
   935 void
   936 BytecodeCompiler::visit(TernaryExpression *node)
   937 {
   938     Label success, failure, join;
   939 
   940     visitForTest(node->condition(), &success, &failure, &success);
   941     __ bind(&success);
   942     node->left()->accept(this);
   943     __ drop(1);
   944     __ jump(&join);
   945     __ bind(&failure);
   946     node->right()->accept(this);
   947     __ bind(&join);
   948 }
   949 
   950 void
   951 BytecodeCompiler::visit(IfStatement *node)
   952 {
   953     Label join;
   954     if (!node->ifFalse()) {
   955         Label success;
   956 
   957         visitForTest(node->condition(), &success, &join, &success);
   958         __ bind(&success);
   959         node->ifTrue()->accept(this);
   960     } else {
   961         Label success, next;
   962 
   963         visitForTest(node->condition(), &success, &next, &success);
   964         __ bind(&success);
   965         node->ifTrue()->accept(this);
   966         __ jump(&join);
   967         __ bind(&next);
   968         node->ifFalse()->accept(this);
   969     }
   970 
   971     __ bind(&join);
   972 }
   973 
   974 void
   975 BytecodeCompiler::visit(FunctionStatement *node)
   976 {
   977     if (!node->fun()->used())
   978         return;
   979 
   980     if (node->fun()->isNative()) {
   981         assert(!moduleData_->natives->at(node->fun()->slot()));
   982 
   983         Local<Type> type(zone_, node->fun()->type());
   984         Local<String> name(zone_, node->fun()->name());
   985         Local<Native> native(zone_, Native::New(zone_, type, name));
   986         if (!native)
   987             return;
   988 
   989         moduleData_->natives->set(zone_, node->fun()->slot(), native);
   990         return;
   991     }
   992 
   993     // If the function has no body, then it's just a declaration.
   994     if (!node->body()) {
   995         assert(node->fun()->isForward() || node->fun()->isPublic());
   996         return;
   997     }
   998 
   999     BytecodeCompiler child(zone_, tree_, moduleData_);
  1000     Local<Function> fun(zone_, child.compileFunction(moduleData_, node));
  1001     if (!fun)
  1002         return;
  1003     
  1004     assert(!moduleData_->module->getFunction(node->fun()->slot()));
  1005     moduleData_->module->setFunction(zone_, node->fun()->slot(), fun);
  1006 }
  1007 
  1008 void
  1009 BytecodeCompiler::visit(EnumStatement *node)
  1010 {
  1011     // :TODO: eventually, we'll export these.
  1012 }
  1013 
  1014 void
  1015 BytecodeCompiler::visit(StructureStatement *node)
  1016 {
  1017 }
  1018 
  1019 Code *
  1020 BytecodeCompiler::compileCode(Scope *scope, unsigned lineno)
  1021 {
  1022     // STOP doubles as RETURNVOID.
  1023     __ stop();
  1024 
  1025     if (__ oom() || zone_->hasPendingException())
  1026         return NULL;
  1027 
  1028     Local<ByteArray> bytes(zone_, ByteArray::New(zone_, __ length() * sizeof(bytecode), Heap::Tenure_Old));
  1029     if (!bytes)
  1030         return NULL;
  1031     memcpy(bytes->raw(), __ buffer(), __ length());
  1032 
  1033     for (size_t i = 0; i < scope->maxContainedLocals(); i++)
  1034         assert(locals_->at(i));
  1035 
  1036     Local<FixedArray> objects(zone_, FixedArray::New(zone_, __ objects()->length(), Heap::Tenure_Old));
  1037     if (!objects)
  1038         return NULL;
  1039 
  1040     for (size_t i = 0; i < __ objects()->length(); i++)
  1041         objects->set(zone_, i, *(__ objects()->at(i)));
  1042 
  1043     Local<ByteArray> safepoints(zone_);
  1044 
  1045     // If any stack slots hold gc pointers at potential failure points in the
  1046     // bytecode, record them now. We do this by building a list of tuples;
  1047     // each tuple contains the pc offset, and a bitset containing which stack
  1048     // slots must be scanned by the gc.
  1049     if (__ oopRecords()->length()) {
  1050         size_t bytesPerSafepoint = Code::BytesPerSafepoint(__ maxStackDepth());
  1051         size_t gcmapSize = bytesPerSafepoint * __ oopRecords()->length();
  1052         safepoints = ByteArray::New(zone_, gcmapSize, Heap::Tenure_Old);
  1053         if (!safepoints)
  1054             return NULL;
  1055 
  1056         Address cursor = safepoints->raw();
  1057         for (size_t i = 0; i < __ oopRecords()->length(); i++) {
  1058             OopRecord *record = __ oopRecords()->at(i);
  1059             assert(record->depth <= __ maxStackDepth());
  1060 
  1061             *reinterpret_cast<unsigned *>(cursor) = record->offset;
  1062 
  1063             unsigned char *bits = reinterpret_cast<unsigned char *>(cursor + sizeof(unsigned));
  1064             for (unsigned i = 0; i < record->depth; i++)
  1065                 bits[i / 8] |= (1 << (i % 8));
  1066 
  1067             cursor += bytesPerSafepoint;
  1068         }
  1069 
  1070         assert(cursor == safepoints->raw() + gcmapSize);
  1071     }
  1072 
  1073     Local<ByteArray> sourcemap(zone_);
  1074     if (__ sourcemapLength()) {
  1075         sourcemap = ByteArray::New(zone_, __ sourcemapLength(), Heap::Tenure_Old);
  1076         if (!sourcemap)
  1077             return NULL;
  1078 
  1079         memcpy(sourcemap->raw(), __ sourcemap(), __ sourcemapLength());
  1080     }
  1081 
  1082     Local<Code> code(zone_);
  1083 
  1084     code = Code::New(zone_,
  1085                      bytes,
  1086                      locals_,
  1087                      objects,
  1088                      __ maxStackDepth(),
  1089                      moduleData_->module,
  1090                      safepoints,
  1091                      sourcemap,
  1092                      lineno);
  1093     return code;
  1094 }
  1095 
  1096 Function *
  1097 BytecodeCompiler::compileFunction(ModuleData *module, FunctionStatement *node)
  1098 {
  1099     // Note: No need to record a life slot here, since it's part of the Frame.
  1100     AutoEnterScope functionScope(this, node->scope());
  1101 
  1102     // Set the initial line, because line mappings are deltas.
  1103     __ setFirstLine(node->pos().line);
  1104     locals_ = FixedArray::New(zone_, node->scope()->maxContainedLocals(), Heap::Tenure_Old);
  1105 
  1106     node->body()->accept(this);
  1107 
  1108     unsigned nargs = node->scope()->numArguments();
  1109     Local<FixedArray> args(zone_, FixedArray::New(zone_, nargs, Heap::Tenure_Old));
  1110     if (!args)
  1111         return NULL;
  1112 
  1113     for (size_t i = 0; i < node->scope()->numArguments(); i++)
  1114         args->set(zone_, i, node->scope()->getArgument(i)->type());
  1115 
  1116 
  1117     Local<Code> code(zone_, compileCode(node->scope(), node->pos().line));
  1118     if (!code)
  1119         return NULL;
  1120 
  1121     Local<Type> type(zone_, node->fun()->type());
  1122     Local<String> name(zone_, node->fun()->name());
  1123     Local<Function> fun(zone_, Function::New(zone_, code, type, name, node->pos()));
  1124     if (!fun)
  1125         return NULL;
  1126 
  1127     // If this function had a forward, export it as a named public.
  1128     if (node->fun()->isPublic()) {
  1129         assert(node->fun()->isPublic());
  1130         ScopedRoot<Function> root(fun);
  1131         if (!root)
  1132             return NULL;
  1133         if (!moduleData_->publics.append(root))
  1134             return NULL;
  1135     }
  1136 
  1137 #ifndef NDEBUG
  1138     Disassemble(code, stdout);
  1139 #endif
  1140     
  1141     return fun;
  1142 }
  1143 
  1144 Module *
  1145 BytecodeCompiler::compile()
  1146 {
  1147     AutoEnterScope scope(this, tree_->scope());
  1148 
  1149     ModuleData moduleData;
  1150 
  1151     moduleData_ = &moduleData;
  1152     moduleData_->module = Module::New(zone_, tree_->scope()->numFunctions());
  1153 
  1154     if (!moduleData_)
  1155         return NULL;
  1156     
  1157     moduleData_->natives = FixedArray::New(zone_, tree_->scope()->numNatives(), Heap::Tenure_Old);
  1158     if (!moduleData_->natives)
  1159         return NULL;
  1160 
  1161     for (size_t i = 0; i < tree_->statements()->length(); i++) {
  1162         Statement *statement = tree_->statements()->at(i);
  1163         statement->accept(this);
  1164     }
  1165 
  1166     if (zone_->hasPendingException())
  1167         return NULL;
  1168 
  1169 #ifndef NDEBUG
  1170     for (size_t i = 0; i < tree_->scope()->numFunctions(); i++)
  1171         assert(moduleData_->module->getFunction(i));
  1172     for (size_t i = 0; i < tree_->scope()->numNatives(); i++)
  1173         assert(moduleData_->natives->at(i));
  1174 #endif
  1175 
  1176     if (moduleData_->publics.length()) {
  1177         Local<Function> fun(zone_);
  1178         Local<FixedArray> list(zone_, FixedArray::New(zone_, moduleData_->publics.length(),
  1179                                Heap::Tenure_Old));
  1180         if (!list)
  1181             return NULL;
  1182 
  1183         for (size_t i = 0; i < moduleData_->publics.length(); i++)
  1184             list->set(zone_, i, moduleData_->publics[i]);
  1185 
  1186         moduleData_->module->setPublics(list);
  1187     }
  1188 
  1189     moduleData_->module->setNatives(moduleData_->natives);
  1190 
  1191     if (scope_->numEnvironmentVars()) {
  1192         Local<EnvironmentMap> globalMap(zone_, scope_->createEnvironmentMap(zone_));
  1193         if (!globalMap)
  1194             return NULL;
  1195 
  1196         Local<Environment> environment(zone_, Environment::New(zone_, globalMap));
  1197         if (!environment)
  1198             return NULL;
  1199 
  1200         moduleData_->module->setEnvironment(environment);
  1201     }
  1202 
  1203     Local<Code> code(zone_, compileCode(tree_->scope(), 1));
  1204     if (!code)
  1205         return NULL;
  1206 
  1207     Disassemble(code, stdout);
  1208 
  1209     moduleData_->module->setCode(code);
  1210 
  1211     return moduleData_->module;
  1212 }