src/BytecodeCompiler.cpp
author David Anderson <dvander@alliedmods.net>
Sat Sep 01 16:36:20 2012 -0700 (2012-09-01)
changeset 174 e718b56aba78
parent 173 bbf9f3809d55
child 175 f875ce723f2c
permissions -rw-r--r--
Implemented callbacks.
     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->location() == Variable::ENVIRONMENT)
   337             getEnvSlot(var);
   338         else if (var->type()->isReference() || var->type()->isArray())
   339             __ get(var);
   340 
   341         // Dup and fetch.
   342         if (var->type()->isReference()) {
   343             __ dup();
   344             __ getref(node->type());
   345             if (node->postfix()) {
   346                 __ swap();
   347                 __ pick2();
   348             }
   349         } else {
   350             assert(!var->type()->isArray());
   351             if (var->location() != Variable::ENVIRONMENT)
   352                 __ get(var);
   353             if (node->postfix())
   354                 __ dup();
   355         }
   356     } else if (expr->isFieldExpression()) {
   357         FieldExpression *field = expr->toFieldExpression();
   358 
   359         field->left()->accept(this);
   360         __ dup();
   361         __ getfield(field->fieldIndex(), field->type());
   362 
   363         if (node->postfix()) {
   364             // The stack looks like this now:
   365             // OBJECT VALUE
   366             __ swap();          // VALUE OBJECT
   367             __ pick2();         // VALUE OBJECT VALUE
   368         }
   369     } else {
   370         IndexExpression *index = expr->toIndexExpression();
   371         __ note_position(index->pos());
   372 
   373         index->left()->accept(this);
   374         index->right()->accept(this);
   375 
   376         assert(!node->type()->isArray());
   377         __ dup2();
   378         __ getelem(node->type());
   379 
   380         if (node->postfix()) {
   381             // The stack looks like this now:
   382             // ARRAY INDEX VALUE
   383             //
   384             // So we must use a PICK operation to rotate the stack into position.
   385             __ roll3();         // INDEX VALUE ARRAY
   386             __ roll3();         // VALUE ARRAY INDEX
   387             __ pick3();         // VALUE ARRAY INDEX VALUE
   388         }
   389     }
   390 
   391     // Perform step (6).
   392     if (node->type()->isFloat()) {
   393         __ float_(1.0);
   394     } else {
   395         assert(node->type()->isInt32());
   396         __ int_(1);
   397     }
   398 
   399     __ note_position(node->pos());
   400     if (node->token() == TOK_INCREMENT)
   401         __ binary(OP_ADD);
   402     else
   403         __ binary(OP_SUB);
   404 
   405     // Perform step (7).
   406     if (expr->isNameProxy()) {
   407         NameProxy *proxy = expr->toNameProxy();
   408         Variable *var = proxy->binding()->toVariable();
   409 
   410         if (var->type()->isReference())
   411             __ setref(node->type());
   412         else if (var->location() == Variable::ENVIRONMENT)
   413             setEnvSlot(var);
   414         else
   415             __ set(var);
   416     } else if (expr->isFieldExpression()) {
   417         FieldExpression *field = expr->toFieldExpression();
   418         __ setfield(field->fieldIndex(), field->type());
   419     } else {
   420         assert(expr->isIndexExpression());
   421         __ setelem(node->type());
   422     }
   423 
   424     // Perform step (8).
   425     if (node->postfix())
   426         __ pop();
   427 }
   428 
   429 void
   430 BytecodeCompiler::visitForALU(Type *needed, Expression *node)
   431 {
   432     node->accept(this);
   433     if (needed->isFloat() && !node->type()->isFloat())
   434         __ cvt_i2f();
   435     else
   436         assert(needed->primitive() == node->type()->primitive());
   437 }
   438 
   439 static inline Type *
   440 GetCoercionType(TokenKind tok, Type *left, Type *right)
   441 {
   442     if (left->isFloat())
   443         return left;
   444     return right;
   445 }
   446 
   447 void
   448 BytecodeCompiler::visit(UnaryExpression *node)
   449 {
   450     Local<Type> out(zone_, ((Expression *)node)->type());
   451 
   452     switch (node->token()) {
   453       case TOK_MINUS:
   454       {
   455         Local<Type> type(zone_, node->expression()->type());
   456         node->expression()->accept(this);
   457         
   458         if (out->isFloat())
   459             __ neg_f();
   460         else
   461             __ neg();
   462         break;
   463       }
   464 
   465       case TOK_NOT:
   466       {
   467         Local<Type> type(zone_, node->expression()->type());
   468         node->expression()->accept(this);
   469         
   470         if (out->isFloat())
   471             __ not_f();
   472         else
   473             __ not_();
   474         break;
   475       }
   476 
   477       case TOK_LABEL:
   478       {
   479         Local<Type> from(zone_, node->expression()->type());
   480 
   481         node->expression()->accept(this);
   482         if (!from->isFloat() && out->isFloat())
   483             __ bits_f2i();
   484         else if (from->isFloat() && !out->isFloat())
   485             __ bits_i2f();
   486         break;
   487       }
   488 
   489       default:
   490         assert(node->token() == TOK_TILDE);
   491         node->expression()->accept(this);
   492         __ bitnot();
   493         break;
   494     }
   495 }
   496 
   497 void
   498 BytecodeCompiler::visit(BinaryExpression *node)
   499 {
   500     if (node->token() == TOK_AND || node->token() == TOK_OR) {
   501         Label success, failure, done;
   502         visitForTest(node, &success, &failure, &success);
   503         __ bind(&success);
   504         __ int_(1);
   505         __ drop(1);         // Otherwise, the stack depth will be +1 too much.
   506         __ jump(&done);
   507         __ bind(&failure);
   508         __ int_(0);
   509         __ bind(&done);
   510         return;
   511     }
   512 
   513     Local<Type> leftType(zone_, node->left()->type());
   514     Local<Type> rightType(zone_, node->right()->type());
   515     Local<Type> coerce(zone_, GetCoercionType(node->token(), leftType, rightType));
   516 
   517     visitForALU(coerce, node->left());
   518     visitForALU(coerce, node->right());
   519 
   520     Opcode op = TokenToOpcode(node->token());
   521     if (node->type()->isFloat())
   522         op = (Opcode)(int(op) + (OP_ADD_F - OP_ADD));
   523 
   524     __ note_position(node->pos());
   525     __ binary(op);
   526 }
   527 
   528 void
   529 BytecodeCompiler::visit(IndexExpression *node)
   530 {
   531     node->left()->accept(this);
   532     node->right()->accept(this);
   533     __ note_position(node->pos());
   534     __ getelem(node->type());
   535 }
   536 
   537 void
   538 BytecodeCompiler::visit(FieldExpression *node)
   539 {
   540     node->left()->accept(this);
   541     __ getfield(node->fieldIndex(), node->type());
   542 }
   543 
   544 void
   545 BytecodeCompiler::visit(ReturnStatement *node)
   546 {
   547     if (node->expression()) {
   548         node->expression()->accept(this);
   549         __ return_();
   550     } else {
   551         __ returnvoid();
   552     }
   553 }
   554 
   555 void
   556 BytecodeCompiler::visitForTest(Expression *expression,
   557                                Label *trueBranch,
   558                                Label *falseBranch,
   559                                Label *fallthrough)
   560 {
   561     TokenKind token = ToCompare(expression);
   562     if (token == TOK_EOF || token == TOK_NOT) {
   563         if (token == TOK_EOF)
   564             expression->accept(this);
   565         else
   566             expression->toUnaryExpression()->expression()->accept(this);
   567         
   568         bool jumpOnTrue = (fallthrough == falseBranch) ^ (token == TOK_NOT);
   569 
   570         Opcode op = jumpOnTrue ? OP_JT : OP_JF;
   571         if (expression->type()->isFloat())
   572             op = (Opcode)(int(op) + (OP_JL_F - OP_JL));
   573 
   574         if (fallthrough == falseBranch)
   575             __ j(op, trueBranch);
   576         else
   577             __ j(op, falseBranch); 
   578         return;
   579     }
   580 
   581     BinaryExpression *binary = expression->toBinaryExpression();
   582 
   583     if (token == TOK_AND || token == TOK_OR) {
   584         Label next;
   585         if (token == TOK_AND)
   586             visitForTest(binary->left(), &next, falseBranch, &next);
   587         else
   588             visitForTest(binary->left(), trueBranch, &next, &next);
   589         __ bind(&next);
   590         visitForTest(binary->right(), trueBranch, falseBranch, fallthrough);
   591         return;
   592     }
   593 
   594     Opcode op = CompareTokenToJump(token);
   595     if (fallthrough == trueBranch)
   596         op = Invert(op);
   597 
   598     Local<Type> leftType(zone_, binary->left()->type());
   599     Local<Type> rightType(zone_, binary->right()->type());
   600     Local<Type> coerce(zone_, GetCoercionType(binary->token(), leftType, rightType));
   601 
   602     visitForALU(coerce, binary->left());
   603     visitForALU(coerce, binary->right());
   604     if (coerce->isFloat())
   605         op = (Opcode)(int(op) + (OP_JL_F - OP_JL));
   606 
   607     if (fallthrough == trueBranch)
   608         __ j(op, falseBranch);
   609     else
   610         __ j(op, trueBranch);
   611 }
   612 
   613 void
   614 BytecodeCompiler::visit(ForStatement *node)
   615 {
   616     AutoEnterScope forScope(this, node->scope());
   617 
   618     recordLifoSlot(node->scope());
   619 
   620     Label join, update;
   621     LoopScope loop(scope_, &join, &update, &loop_);
   622 
   623     if (node->initialization())
   624         node->initialization()->accept(this);
   625 
   626     Label header, test;
   627     if (node->condition())
   628         __ jump(&test);
   629 
   630     __ bind(&header);
   631     node->body()->accept(this);
   632 
   633     __ bind(&update);
   634     if (node->update())
   635         node->update()->accept(this);
   636 
   637     if (node->condition()) {
   638         __ bind(&test);
   639         visitForTest(node->condition(), &header, &join, &join);
   640     } else {
   641         __ jump(&header);
   642     }
   643 
   644     __ bind(&join);
   645 
   646     if (node->scope())
   647         unwindTo(node->scope()->enclosing());
   648     assert(__ stackDepth() == 0);
   649 }
   650 
   651 void
   652 BytecodeCompiler::visit(WhileStatement *node)
   653 {
   654     Label header, join;
   655 
   656     __ bind(&header);
   657 
   658     LoopScope loop(scope_, &join, &header, &loop_);
   659 
   660     if (node->token() == TOK_WHILE) {
   661         Label body;
   662 
   663         visitForTest(node->condition(), &body, &join, &body);
   664         __ bind(&body);
   665         node->body()->accept(this);
   666         __ jump(&header);
   667     } else {
   668         node->body()->accept(this);
   669         visitForTest(node->condition(), &header, &join, &join);
   670     }
   671 
   672     __ bind(&join);
   673 }
   674 
   675 void
   676 BytecodeCompiler::visit(BreakStatement *node)
   677 {
   678     unwindTo(loop_->scope());
   679     __ jump(loop_->break_());
   680 }
   681 
   682 void
   683 BytecodeCompiler::visit(ContinueStatement *node)
   684 {
   685     unwindTo(loop_->scope());
   686     __ jump(loop_->continue_());
   687 }
   688 
   689 void
   690 BytecodeCompiler::visit(BlockStatement *node)
   691 {
   692     AutoEnterScope blockScope(this, node->scope());
   693 
   694     recordLifoSlot(node->scope());
   695 
   696     for (size_t i = 0; i < node->statements()->length(); i++) {
   697         Statement *statement = node->statements()->at(i);
   698         statement->accept(this);
   699         assert(__ stackDepth() == 0);
   700     }
   701 
   702     // We don't bother emitting an "unwind" instruction for function scopes,
   703     // since this is taken care of by the calling convention.
   704     if (node->scope() && node->scope()->enclosing()->kind() != Scope::FUNCTION)
   705         unwindTo(node->scope()->enclosing());
   706 }
   707 
   708 void
   709 BytecodeCompiler::visit(IntegerLiteral *node)
   710 {
   711     __ int_(node->value());
   712 }
   713 
   714 void
   715 BytecodeCompiler::visit(BooleanLiteral *node)
   716 {
   717     if (node->token() == TOK_TRUE)
   718         __ true_();
   719     else
   720         __ false_();
   721 }
   722 
   723 void
   724 BytecodeCompiler::visit(FloatLiteral *node)
   725 {
   726     __ float_((float)node->value());
   727 }
   728 
   729 void
   730 BytecodeCompiler::visit(StringLiteral *node)
   731 {
   732     Local<Type> type(zone_, node->type());
   733     Local<ArrayMap> map(zone_, ArrayMap::Attach(zone_, type));
   734     if (!map)
   735         return;
   736 
   737     Local<Array> array(zone_,
   738         Array::NewString(zone_,
   739                          map,
   740                          node->string()->raw(),
   741                          node->string()->length(),
   742                          Heap::Tenure_Old));
   743     if (!array)
   744         return;
   745 
   746     __ note_position(node->pos());
   747     __ object(array);
   748 }
   749 
   750 void
   751 BytecodeCompiler::getEnvSlot(Variable *var)
   752 {
   753     assert(var->scope()->kind() == Scope::GLOBAL);
   754     __ getglobal(var);
   755 }
   756 
   757 void
   758 BytecodeCompiler::setEnvSlot(Variable *var)
   759 {
   760     assert(var->scope()->kind() == Scope::GLOBAL);
   761     __ setglobal(var);
   762 }
   763 
   764 void
   765 BytecodeCompiler::visit(VariableDeclaration *node)
   766 {
   767     Variable *var = node->variable();
   768     
   769     Local<Type> type(zone_, var->type());
   770     if (type->isArray()) {
   771         Local<ArrayMap> map(zone_, ArrayMap::Attach(zone_, type));
   772         __ note_position(node->pos());
   773         if (var->scope()->kind() == Scope::GLOBAL)
   774             __ newarray(map, Heap::Tenure_Old);
   775         else if (var->needsHeapAllocation())
   776             __ newarray(map, Heap::Tenure_Default);
   777         else
   778             __ newarray(map, Heap::Tenure_Stack);
   779 
   780         if (node->initialization()) {
   781             node->initialization()->accept(this);
   782             __ note_position(node->pos());
   783             __ copyarray();
   784         }
   785     } else if (type->isStruct()) {
   786         Local<Map> map(zone_, type->newMap());
   787         if (var->scope()->kind() == Scope::GLOBAL)
   788             __ newstruct(map, Heap::Tenure_Old);
   789         else if (var->needsHeapAllocation())
   790             __ newstruct(map, Heap::Tenure_Default);
   791         else
   792             __ newstruct(map, Heap::Tenure_Stack);
   793     } else {
   794         if (node->initialization()) {
   795             node->initialization()->accept(this);
   796         } else {
   797             if (type->isInt32OrEnum() || type->isBool()) {
   798                 __ int_(0);
   799             } else {
   800                 assert(type->isFloat());
   801                 __ float_(0);
   802             }
   803         }
   804     }
   805 
   806     if (var->location() == Variable::STACK) {
   807         __ setlocal(var);
   808         locals_->set(zone_, var->slot(), var->type());
   809     } else {
   810         assert(var->location() == Variable::ENVIRONMENT);
   811         setEnvSlot(var);
   812     }
   813 
   814     __ pop();
   815 }
   816 
   817 void
   818 BytecodeCompiler::visit(CallExpression *node)
   819 {
   820     Local<Type> funType(zone_, node->callee()->type());
   821 
   822     // Sniff out natives, which have a specific opcode and are guaranteed to
   823     // be called via name proxy.
   824     NamedFunction *native = NULL;
   825     if (funType->isNative()) {
   826         native = node->callee()->toNameProxy()->binding()->toNamedFunction();
   827     }
   828 
   829     Local<Type> given(zone_);
   830     for (size_t i = node->arguments()->length() - 1; i < node->arguments()->length(); i--) {
   831         Expression *arg = node->arguments()->at(i);
   832 
   833         given = arg->type();
   834 
   835         // We need to compute a reference if the parameter was in the form:
   836         //  f(&a)
   837         // Note this form does not allow: f({})
   838         // 
   839         // We also need to compute references for all variadic native
   840         // arguments, but arrays and references are already in the
   841         // appropriate form.
   842         bool mustPushReference = false;
   843         if (i >= funType->parameters()->length()) {
   844             assert(funType->isNative() && funType->isNativeVariadic());
   845             mustPushReference = !given->isArray() && !given->isReference();
   846         } else if (funType->parameterAt(i)->isReference()) {
   847             mustPushReference = !given->isReference();
   848         }
   849 
   850         // If a native is passed to a native, it must only be one level deep.
   851         assert(!funType->isNative() || !given->isArray() || given->levels() == 1);
   852 
   853         if (mustPushReference) {
   854             if (arg->isNameProxy()) {
   855                 // :TODO: test with functions and globals
   856                 // Compute a reference to the name.
   857                 Variable *var = arg->toNameProxy()->binding()->toVariable();
   858                 __ note_position(node->pos());
   859                 __ newref(var);
   860             } else if (arg->isIndexExpression()) {
   861                 IndexExpression *expr = arg->toIndexExpression();
   862                 expr->left()->accept(this);
   863                 expr->right()->accept(this);
   864                 __ note_position(expr->pos());
   865                 __ arrayref_lifo();
   866             } else if (arg->isFieldExpression()) {
   867                 FieldExpression *expr = arg->toFieldExpression();
   868                 expr->left()->accept(this);
   869                 __ note_position(expr->pos());
   870                 __ fieldref_lifo(expr->fieldIndex());
   871             } else {
   872                 // We don't know how to, or can't, build a direct reference to
   873                 // this type. Make an indirect one, by taking the top of the
   874                 // stack and boxing it up.
   875                 arg->accept(this);
   876                 __ note_position(node->pos());
   877                 __ slotref_lifo();
   878             }
   879         } else {
   880             arg->accept(this);
   881         }
   882     }
   883 
   884     unsigned argc = node->arguments()->length();
   885 
   886     // If there are missing arguments, then we're not done and have to push
   887     // default parameters.
   888     Local<Box> box(zone_);
   889     Local<Array> array(zone_);
   890     Local<ArrayMap> map(zone_);
   891     for (size_t i = node->arguments()->length(); i < funType->parameters()->length(); i++) {
   892         box = Box::cast(funType->defaults()->at(i));
   893 
   894         if (box->type()->isPod()) {
   895             if (box->type()->pod() == PrimitiveType_Int32)
   896                 __ int_(box->toInt32());
   897             else if (box->type()->pod() == PrimitiveType_Float)
   898                 __ float_(box->toFloat());
   899             else
   900                 assert(false);
   901 
   902             if (funType->parameterAt(i)->isReference()) {
   903                 __ note_position(node->pos());
   904                 __ slotref_lifo();
   905             }
   906         } else {
   907             assert(box->type()->isArray());
   908 
   909             array = Array::cast(box->toObject());
   910             if (funType->parameterAt(i)->isConst()) {
   911                 __ object(array);
   912             } else {
   913                 // We need to copy the array since it's mutable. Note that
   914                 // although COPYARRAY returns its left-hand side, this may
   915                 // change in the future, we do the same thing and dupe the
   916                 // newly allocated array.
   917                 map = ArrayMap::cast(array->map());
   918                 __ newarray(map, Heap::Tenure_Stack);
   919                 __ dup();
   920                 __ object(array);
   921                 __ copyarray();
   922                 __ pop();
   923             }
   924         }
   925 
   926         argc++;
   927     }
   928 
   929     __ note_position(node->pos());
   930     if (native) {
   931         __ callnative(native->slot(), argc);
   932         __ drop(argc);
   933     } else {
   934         node->callee()->accept(this);
   935         __ call(funType);
   936         __ drop(argc + 1);
   937     }
   938 }
   939 
   940 void
   941 BytecodeCompiler::visit(TernaryExpression *node)
   942 {
   943     Label success, failure, join;
   944 
   945     visitForTest(node->condition(), &success, &failure, &success);
   946     __ bind(&success);
   947     node->left()->accept(this);
   948     __ drop(1);
   949     __ jump(&join);
   950     __ bind(&failure);
   951     node->right()->accept(this);
   952     __ bind(&join);
   953 }
   954 
   955 void
   956 BytecodeCompiler::visit(IfStatement *node)
   957 {
   958     Label join;
   959     if (!node->ifFalse()) {
   960         Label success;
   961 
   962         visitForTest(node->condition(), &success, &join, &success);
   963         __ bind(&success);
   964         node->ifTrue()->accept(this);
   965     } else {
   966         Label success, next;
   967 
   968         visitForTest(node->condition(), &success, &next, &success);
   969         __ bind(&success);
   970         node->ifTrue()->accept(this);
   971         __ jump(&join);
   972         __ bind(&next);
   973         node->ifFalse()->accept(this);
   974     }
   975 
   976     __ bind(&join);
   977 }
   978 
   979 bool
   980 BytecodeCompiler::tableswitch(SwitchStatement *node)
   981 {
   982     CaseValueList *values = node->caseValueList();
   983 
   984     if (values->length() < 3)
   985         return false;
   986 
   987     // Find the delta between the largest and smallest value.
   988     int hi = values->at(values->length() - 1).box.toInt();
   989     int lo = values->at(0).box.toInt();
   990     assert(hi > lo);
   991 
   992     unsigned tablesize = TableSwitchEntries(lo, hi);
   993     if (tablesize > MAX_TABLESWITCH_ENTRIES)
   994         return false;
   995 
   996     Label def, join;
   997 
   998     // Create the list of labels that each statement will bind to.
   999     Label *labels = new Label[node->cases()->length()];
  1000 
  1001     // Create the table of labels we'll use for each case.
  1002     Label **table = new Label *[tablesize];
  1003 
  1004     // Link all cases, by default, to the default label.
  1005     for (size_t i = 0; i < tablesize; i++)
  1006         table[i] = &def;
  1007 
  1008     // Now patch actual cases to their correct labels.
  1009     for (size_t i = 0; i < values->length(); i++) {
  1010         CaseValue &v = values->at(i);
  1011         assert(v.statement < node->cases()->length());
  1012 
  1013         unsigned index = unsigned(v.box.toInt() - lo);
  1014         assert(index < tablesize);
  1015 
  1016         table[index] = &labels[v.statement];
  1017     }
  1018 
  1019     // Emit the tableswitch opcode and the jump table.
  1020     __ tableswitch(lo, hi, &def, table);
  1021 
  1022     // We're done with the jump table now.
  1023     delete [] table;
  1024 
  1025     // Emit each statement.
  1026     for (size_t i = 0; i < node->cases()->length(); i++) {
  1027         Statement *stmt = node->cases()->at(i)->statement();
  1028 
  1029         __ bind(&labels[i]);
  1030         stmt->accept(this);
  1031         __ jump(&join);
  1032     }
  1033 
  1034     // We're done with the statement labels.
  1035     delete [] labels;
  1036 
  1037     // Emit the default case.
  1038     __ bind(&def);
  1039     if (node->defaultCase())
  1040         node->defaultCase()->accept(this);
  1041 
  1042     __ bind(&join);
  1043 
  1044     return true;
  1045 }
  1046 
  1047 void
  1048 BytecodeCompiler::visit(SwitchStatement *node)
  1049 {
  1050     node->expression()->accept(this);
  1051 
  1052     if (tableswitch(node))
  1053         return;
  1054 
  1055     Label join;
  1056 
  1057     for (size_t i = 0; i < node->cases()->length(); i++) {
  1058         Case *c = node->cases()->at(i);
  1059 
  1060         Label success, fail;
  1061         if (c->others()) {
  1062             for (size_t j = 0; j < c->others()->length(); j++) {
  1063                 Expression *expr = c->others()->at(j);
  1064 
  1065                 __ dup();
  1066                 expr->accept(this);
  1067                 __ j(OP_JEQ, &success);
  1068             }
  1069         }
  1070 
  1071         // The final test.
  1072         __ dup();
  1073         c->expression()->accept(this);
  1074         __ j(OP_JNE, &fail);
  1075         __ bind(&success);
  1076         c->statement()->accept(this);
  1077         __ jump(&join);
  1078         __ bind(&fail);
  1079     }
  1080 
  1081     if (node->defaultCase())
  1082         node->defaultCase()->accept(this);
  1083 
  1084     __ pop();
  1085     __ bind(&join);
  1086 }
  1087 
  1088 void
  1089 BytecodeCompiler::visit(FunctionStatement *node)
  1090 {
  1091     if (!node->fun()->used())
  1092         return;
  1093 
  1094     if (node->fun()->isNative()) {
  1095         assert(!moduleData_->natives->at(node->fun()->slot()));
  1096 
  1097         Local<Type> type(zone_, node->fun()->type());
  1098         Local<String> name(zone_, node->fun()->name());
  1099         Local<Native> native(zone_, Native::New(zone_, type, name));
  1100         if (!native)
  1101             return;
  1102 
  1103         moduleData_->natives->set(zone_, node->fun()->slot(), native);
  1104         return;
  1105     }
  1106 
  1107     // If the function has no body, then it's just a declaration.
  1108     if (!node->body()) {
  1109         assert(node->fun()->isForward() || node->fun()->isPublic());
  1110         return;
  1111     }
  1112 
  1113     BytecodeCompiler child(zone_, tree_, moduleData_);
  1114     Local<Function> fun(zone_, child.compileFunction(moduleData_, node));
  1115     if (!fun)
  1116         return;
  1117     
  1118     assert(!moduleData_->module->getFunction(node->fun()->slot()));
  1119     moduleData_->module->setFunction(zone_, node->fun()->slot(), fun);
  1120 }
  1121 
  1122 void
  1123 BytecodeCompiler::visit(FunctionTypeStatement *node)
  1124 {
  1125 }
  1126 
  1127 void
  1128 BytecodeCompiler::visit(EnumStatement *node)
  1129 {
  1130 }
  1131 
  1132 void
  1133 BytecodeCompiler::visit(StructureStatement *node)
  1134 {
  1135 }
  1136 
  1137 Code *
  1138 BytecodeCompiler::compileCode(Scope *scope, unsigned lineno)
  1139 {
  1140     // STOP doubles as RETURNVOID.
  1141     __ stop();
  1142 
  1143     if (__ oom() || zone_->hasPendingException())
  1144         return NULL;
  1145 
  1146     Local<ByteArray> bytes(zone_, ByteArray::New(zone_, __ length() * sizeof(bytecode), Heap::Tenure_Old));
  1147     if (!bytes)
  1148         return NULL;
  1149     memcpy(bytes->raw(), __ buffer(), __ length());
  1150 
  1151     for (size_t i = 0; i < scope->maxContainedLocals(); i++)
  1152         assert(locals_->at(i));
  1153 
  1154     Local<FixedArray> objects(zone_, FixedArray::New(zone_, __ objects()->length(), Heap::Tenure_Old));
  1155     if (!objects)
  1156         return NULL;
  1157 
  1158     for (size_t i = 0; i < __ objects()->length(); i++)
  1159         objects->set(zone_, i, *(__ objects()->at(i)));
  1160 
  1161     Local<ByteArray> safepoints(zone_);
  1162 
  1163     // If any stack slots hold gc pointers at potential failure points in the
  1164     // bytecode, record them now. We do this by building a list of tuples;
  1165     // each tuple contains the pc offset, and a bitset containing which stack
  1166     // slots must be scanned by the gc.
  1167     if (__ oopRecords()->length()) {
  1168         size_t bytesPerSafepoint = Code::BytesPerSafepoint(__ maxStackDepth());
  1169         size_t gcmapSize = bytesPerSafepoint * __ oopRecords()->length();
  1170         safepoints = ByteArray::New(zone_, gcmapSize, Heap::Tenure_Old);
  1171         if (!safepoints)
  1172             return NULL;
  1173 
  1174         Address cursor = safepoints->raw();
  1175         for (size_t i = 0; i < __ oopRecords()->length(); i++) {
  1176             OopRecord *record = __ oopRecords()->at(i);
  1177             assert(record->depth <= __ maxStackDepth());
  1178 
  1179             *reinterpret_cast<unsigned *>(cursor) = record->offset;
  1180 
  1181             unsigned char *bits = reinterpret_cast<unsigned char *>(cursor + sizeof(unsigned));
  1182             for (unsigned i = 0; i < record->depth; i++)
  1183                 bits[i / 8] |= (1 << (i % 8));
  1184 
  1185             cursor += bytesPerSafepoint;
  1186         }
  1187 
  1188         assert(cursor == safepoints->raw() + gcmapSize);
  1189     }
  1190 
  1191     Local<ByteArray> sourcemap(zone_);
  1192     if (__ sourcemapLength()) {
  1193         sourcemap = ByteArray::New(zone_, __ sourcemapLength(), Heap::Tenure_Old);
  1194         if (!sourcemap)
  1195             return NULL;
  1196 
  1197         memcpy(sourcemap->raw(), __ sourcemap(), __ sourcemapLength());
  1198     }
  1199 
  1200     Local<Code> code(zone_);
  1201 
  1202     code = Code::New(zone_,
  1203                      bytes,
  1204                      locals_,
  1205                      objects,
  1206                      __ maxStackDepth(),
  1207                      moduleData_->module,
  1208                      safepoints,
  1209                      sourcemap,
  1210                      lineno);
  1211     return code;
  1212 }
  1213 
  1214 Function *
  1215 BytecodeCompiler::compileFunction(ModuleData *module, FunctionStatement *node)
  1216 {
  1217     // Note: No need to record a life slot here, since it's part of the Frame.
  1218     AutoEnterScope functionScope(this, node->scope());
  1219 
  1220     // Set the initial line, because line mappings are deltas.
  1221     __ setFirstLine(node->pos().line);
  1222     locals_ = FixedArray::New(zone_, node->scope()->maxContainedLocals(), Heap::Tenure_Old);
  1223 
  1224     node->body()->accept(this);
  1225 
  1226     unsigned nargs = node->scope()->numArguments();
  1227     Local<FixedArray> args(zone_, FixedArray::New(zone_, nargs, Heap::Tenure_Old));
  1228     if (!args)
  1229         return NULL;
  1230 
  1231     for (size_t i = 0; i < node->scope()->numArguments(); i++)
  1232         args->set(zone_, i, node->scope()->getArgument(i)->type());
  1233 
  1234 
  1235     Local<Code> code(zone_, compileCode(node->scope(), node->pos().line));
  1236     if (!code)
  1237         return NULL;
  1238 
  1239     Local<Type> type(zone_, node->fun()->type());
  1240     Local<String> name(zone_, node->fun()->name());
  1241     Local<Function> fun(zone_, Function::New(zone_, code, type, name, node->pos()));
  1242     if (!fun)
  1243         return NULL;
  1244 
  1245     // If this function had a forward, export it as a named public.
  1246     if (node->fun()->isPublic()) {
  1247         assert(node->fun()->isPublic());
  1248         ScopedRoot<Function> root(fun);
  1249         if (!root)
  1250             return NULL;
  1251         if (!moduleData_->publics.append(root))
  1252             return NULL;
  1253     }
  1254 
  1255 #ifndef NDEBUG
  1256     Disassemble(code, stdout);
  1257 #endif
  1258     
  1259     return fun;
  1260 }
  1261 
  1262 Module *
  1263 BytecodeCompiler::compile()
  1264 {
  1265     AutoEnterScope scope(this, tree_->scope());
  1266 
  1267     ModuleData moduleData;
  1268 
  1269     moduleData_ = &moduleData;
  1270     moduleData_->module = Module::New(zone_, tree_->scope()->numFunctions());
  1271 
  1272     if (!moduleData_)
  1273         return NULL;
  1274     
  1275     moduleData_->natives = FixedArray::New(zone_, tree_->scope()->numNatives(), Heap::Tenure_Old);
  1276     if (!moduleData_->natives)
  1277         return NULL;
  1278 
  1279     for (size_t i = 0; i < tree_->statements()->length(); i++) {
  1280         Statement *statement = tree_->statements()->at(i);
  1281         statement->accept(this);
  1282     }
  1283 
  1284     if (zone_->hasPendingException())
  1285         return NULL;
  1286 
  1287 #ifndef NDEBUG
  1288     for (size_t i = 0; i < tree_->scope()->numFunctions(); i++)
  1289         assert(moduleData_->module->getFunction(i));
  1290     for (size_t i = 0; i < tree_->scope()->numNatives(); i++)
  1291         assert(moduleData_->natives->at(i));
  1292 #endif
  1293 
  1294     if (moduleData_->publics.length()) {
  1295         Local<Function> fun(zone_);
  1296         Local<FixedArray> list(zone_, FixedArray::New(zone_, moduleData_->publics.length(),
  1297                                Heap::Tenure_Old));
  1298         if (!list)
  1299             return NULL;
  1300 
  1301         for (size_t i = 0; i < moduleData_->publics.length(); i++)
  1302             list->set(zone_, i, moduleData_->publics[i]);
  1303 
  1304         moduleData_->module->setPublics(list);
  1305     }
  1306 
  1307     moduleData_->module->setNatives(moduleData_->natives);
  1308 
  1309     if (scope_->numEnvironmentVars()) {
  1310         Local<EnvironmentMap> globalMap(zone_, scope_->createEnvironmentMap(zone_));
  1311         if (!globalMap)
  1312             return NULL;
  1313 
  1314         Local<Environment> environment(zone_, Environment::New(zone_, globalMap));
  1315         if (!environment)
  1316             return NULL;
  1317 
  1318         moduleData_->module->setEnvironment(environment);
  1319     }
  1320 
  1321     Local<Code> code(zone_, compileCode(tree_->scope(), 1));
  1322     if (!code)
  1323         return NULL;
  1324 
  1325     Disassemble(code, stdout);
  1326 
  1327     moduleData_->module->setCode(code);
  1328 
  1329     return moduleData_->module;
  1330 }