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