src/BytecodeCompiler.cpp
author David Anderson <dvander@alliedmods.net>
Sat Sep 15 13:15:51 2012 -0700 (2012-09-15)
changeset 182 c52ca323063f
parent 175 f875ce723f2c
child 184 387d76b1e981
permissions -rw-r--r--
Do not create LIFO arrays.
     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
   781             __ newarray(map, Heap::Tenure_Default);
   782 
   783         if (node->initialization()) {
   784             node->initialization()->accept(this);
   785             __ note_position(node->pos());
   786             __ copyarray();
   787         }
   788     } else if (type->isStruct()) {
   789         Local<Map> map(zone_, type->newMap());
   790         if (var->scope()->kind() == Scope::GLOBAL)
   791             __ newstruct(map, Heap::Tenure_Old);
   792         else if (var->needsHeapAllocation())
   793             __ newstruct(map, Heap::Tenure_Default);
   794         else
   795             __ newstruct(map, Heap::Tenure_Stack);
   796     } else {
   797         if (node->initialization()) {
   798             node->initialization()->accept(this);
   799         } else {
   800             if (type->isInt32OrEnum() || type->isBool()) {
   801                 __ int_(0);
   802             } else {
   803                 assert(type->isFloat());
   804                 __ float_(0);
   805             }
   806         }
   807     }
   808 
   809     if (var->location() == Variable::STACK) {
   810         __ setlocal(var);
   811         locals_->set(zone_, var->slot(), var->type());
   812     } else {
   813         assert(var->location() == Variable::ENVIRONMENT);
   814         setEnvSlot(var);
   815     }
   816 
   817     __ pop();
   818 }
   819 
   820 void
   821 BytecodeCompiler::visit(CallExpression *node)
   822 {
   823     Local<Type> funType(zone_, node->callee()->type());
   824 
   825     // Sniff out natives, which have a specific opcode and are guaranteed to
   826     // be called via name proxy.
   827     NamedFunction *native = NULL;
   828     if (funType->isNative())
   829         native = node->callee()->toNameProxy()->binding()->toNamedFunction();
   830 
   831     Local<Type> given(zone_);
   832     for (size_t i = node->arguments()->length() - 1; i < node->arguments()->length(); i--) {
   833         Expression *arg = node->arguments()->at(i);
   834 
   835         given = arg->type();
   836 
   837         // We need to compute a reference if the parameter was in the form:
   838         //  f(&a)
   839         // Note this form does not allow: f({})
   840         // 
   841         // We also need to compute references for all variadic native
   842         // arguments, but arrays and references are already in the
   843         // appropriate form.
   844         bool mustPushReference = false;
   845         if (i >= funType->parameters()->length()) {
   846             assert(funType->isNative() && funType->isNativeVariadic());
   847             mustPushReference = !given->isArray() && !given->isReference();
   848         } else if (funType->parameterAt(i)->isReference()) {
   849             mustPushReference = !given->isReference();
   850         }
   851 
   852         // If a native is passed to a native, it must only be one level deep.
   853         assert(!funType->isNative() || !given->isArray() || given->levels() == 1);
   854 
   855         if (mustPushReference) {
   856             if (arg->isNameProxy()) {
   857                 // :TODO: test with functions and globals
   858                 // Compute a reference to the name.
   859                 Variable *var = arg->toNameProxy()->binding()->toVariable();
   860                 __ note_position(node->pos());
   861                 __ newref(var);
   862             } else if (arg->isIndexExpression()) {
   863                 IndexExpression *expr = arg->toIndexExpression();
   864                 expr->left()->accept(this);
   865                 expr->right()->accept(this);
   866                 __ note_position(expr->pos());
   867                 __ arrayref_lifo();
   868             } else if (arg->isFieldExpression()) {
   869                 FieldExpression *expr = arg->toFieldExpression();
   870                 expr->left()->accept(this);
   871                 __ note_position(expr->pos());
   872                 __ fieldref_lifo(expr->fieldIndex());
   873             } else {
   874                 // We don't know how to, or can't, build a direct reference to
   875                 // this type. Make an indirect one, by taking the top of the
   876                 // stack and boxing it up.
   877                 arg->accept(this);
   878                 __ note_position(node->pos());
   879                 __ slotref_lifo();
   880             }
   881         } else {
   882             arg->accept(this);
   883         }
   884     }
   885 
   886     unsigned argc = node->arguments()->length();
   887 
   888     // If there are missing arguments, then we're not done and have to push
   889     // default parameters.
   890     Local<Box> box(zone_);
   891     Local<Array> array(zone_);
   892     Local<ArrayMap> map(zone_);
   893     for (size_t i = node->arguments()->length(); i < funType->parameters()->length(); i++) {
   894         box = Box::cast(funType->defaults()->at(i));
   895 
   896         if (box->type()->isPod()) {
   897             if (box->type()->pod() == PrimitiveType_Int32)
   898                 __ int_(box->toInt32());
   899             else if (box->type()->pod() == PrimitiveType_Float)
   900                 __ float_(box->toFloat());
   901             else
   902                 assert(false);
   903 
   904             if (funType->parameterAt(i)->isReference()) {
   905                 __ note_position(node->pos());
   906                 __ slotref_lifo();
   907             }
   908         } else {
   909             assert(box->type()->isArray());
   910 
   911             array = Array::cast(box->toObject());
   912             if (funType->parameterAt(i)->isConst()) {
   913                 __ object(array);
   914             } else {
   915                 // We need to copy the array since it's mutable. Note that
   916                 // although COPYARRAY returns its left-hand side, this may
   917                 // change in the future, we do the same thing and dupe the
   918                 // newly allocated array.
   919                 map = ArrayMap::cast(array->map());
   920                 
   921                 // Natives cannot escape array references, so we can allocate
   922                 // them on the LIFO stack.
   923                 if (funType->isNative())
   924                     __ newarray(map, Heap::Tenure_Stack);
   925                 else
   926                     __ newarray(map, Heap::Tenure_Default);
   927                 __ dup();
   928                 __ object(array);
   929                 __ copyarray();
   930                 __ pop();
   931             }
   932         }
   933 
   934         argc++;
   935     }
   936 
   937     __ note_position(node->pos());
   938     if (native) {
   939         __ callnative(native->slot(), argc);
   940         __ drop(argc);
   941     } else {
   942         node->callee()->accept(this);
   943         __ call(funType);
   944         __ drop(argc + 1);
   945     }
   946 }
   947 
   948 void
   949 BytecodeCompiler::visit(TernaryExpression *node)
   950 {
   951     Label success, failure, join;
   952 
   953     visitForTest(node->condition(), &success, &failure, &success);
   954     __ bind(&success);
   955     node->left()->accept(this);
   956     __ drop(1);
   957     __ jump(&join);
   958     __ bind(&failure);
   959     node->right()->accept(this);
   960     __ bind(&join);
   961 }
   962 
   963 void
   964 BytecodeCompiler::visit(IfStatement *node)
   965 {
   966     Label join;
   967     if (!node->ifFalse()) {
   968         Label success;
   969 
   970         visitForTest(node->condition(), &success, &join, &success);
   971         __ bind(&success);
   972         node->ifTrue()->accept(this);
   973     } else {
   974         Label success, next;
   975 
   976         visitForTest(node->condition(), &success, &next, &success);
   977         __ bind(&success);
   978         node->ifTrue()->accept(this);
   979         __ jump(&join);
   980         __ bind(&next);
   981         node->ifFalse()->accept(this);
   982     }
   983 
   984     __ bind(&join);
   985 }
   986 
   987 bool
   988 BytecodeCompiler::tableswitch(SwitchStatement *node)
   989 {
   990     CaseValueList *values = node->caseValueList();
   991 
   992     if (values->length() < 3)
   993         return false;
   994 
   995     // Find the delta between the largest and smallest value.
   996     int hi = values->at(values->length() - 1).box.toInt();
   997     int lo = values->at(0).box.toInt();
   998     assert(hi > lo);
   999 
  1000     unsigned tablesize = TableSwitchEntries(lo, hi);
  1001     if (tablesize > MAX_TABLESWITCH_ENTRIES)
  1002         return false;
  1003 
  1004     Label def, join;
  1005 
  1006     // Create the list of labels that each statement will bind to.
  1007     Label *labels = new Label[node->cases()->length()];
  1008 
  1009     // Create the table of labels we'll use for each case.
  1010     Label **table = new Label *[tablesize];
  1011 
  1012     // Link all cases, by default, to the default label.
  1013     for (size_t i = 0; i < tablesize; i++)
  1014         table[i] = &def;
  1015 
  1016     // Now patch actual cases to their correct labels.
  1017     for (size_t i = 0; i < values->length(); i++) {
  1018         CaseValue &v = values->at(i);
  1019         assert(v.statement < node->cases()->length());
  1020 
  1021         unsigned index = unsigned(v.box.toInt() - lo);
  1022         assert(index < tablesize);
  1023 
  1024         table[index] = &labels[v.statement];
  1025     }
  1026 
  1027     // Emit the tableswitch opcode and the jump table.
  1028     __ tableswitch(lo, hi, &def, table);
  1029 
  1030     // We're done with the jump table now.
  1031     delete [] table;
  1032 
  1033     // Emit each statement.
  1034     for (size_t i = 0; i < node->cases()->length(); i++) {
  1035         Statement *stmt = node->cases()->at(i)->statement();
  1036 
  1037         __ bind(&labels[i]);
  1038         stmt->accept(this);
  1039         __ jump(&join);
  1040     }
  1041 
  1042     // We're done with the statement labels.
  1043     delete [] labels;
  1044 
  1045     // Emit the default case.
  1046     __ bind(&def);
  1047     if (node->defaultCase())
  1048         node->defaultCase()->accept(this);
  1049 
  1050     __ bind(&join);
  1051 
  1052     return true;
  1053 }
  1054 
  1055 void
  1056 BytecodeCompiler::visit(SwitchStatement *node)
  1057 {
  1058     node->expression()->accept(this);
  1059 
  1060     if (tableswitch(node))
  1061         return;
  1062 
  1063     Label join;
  1064 
  1065     for (size_t i = 0; i < node->cases()->length(); i++) {
  1066         Case *c = node->cases()->at(i);
  1067 
  1068         Label success, fail;
  1069         if (c->others()) {
  1070             for (size_t j = 0; j < c->others()->length(); j++) {
  1071                 Expression *expr = c->others()->at(j);
  1072 
  1073                 __ dup();
  1074                 expr->accept(this);
  1075                 __ j(OP_JEQ, &success);
  1076             }
  1077         }
  1078 
  1079         // The final test.
  1080         __ dup();
  1081         c->expression()->accept(this);
  1082         __ j(OP_JNE, &fail);
  1083         __ bind(&success);
  1084         c->statement()->accept(this);
  1085         __ jump(&join);
  1086         __ bind(&fail);
  1087     }
  1088 
  1089     if (node->defaultCase())
  1090         node->defaultCase()->accept(this);
  1091 
  1092     __ pop();
  1093     __ bind(&join);
  1094 }
  1095 
  1096 void
  1097 BytecodeCompiler::visit(FunctionStatement *node)
  1098 {
  1099     if (!node->fun()->used())
  1100         return;
  1101 
  1102     if (node->fun()->isNative()) {
  1103         assert(!moduleData_->natives->at(node->fun()->slot()));
  1104 
  1105         Local<Type> type(zone_, node->fun()->type());
  1106         Local<String> name(zone_, node->fun()->name());
  1107         Local<Native> native(zone_, Native::New(zone_, type, name));
  1108         if (!native)
  1109             return;
  1110 
  1111         moduleData_->natives->set(zone_, node->fun()->slot(), native);
  1112         return;
  1113     }
  1114 
  1115     // If the function has no body, then it's just a declaration.
  1116     if (!node->body()) {
  1117         assert(node->fun()->isForward() || node->fun()->isPublic());
  1118         return;
  1119     }
  1120 
  1121     BytecodeCompiler child(zone_, tree_, moduleData_);
  1122     Local<Function> fun(zone_, child.compileFunction(moduleData_, node));
  1123     if (!fun)
  1124         return;
  1125     
  1126     assert(!moduleData_->module->getFunction(node->fun()->slot()));
  1127     moduleData_->module->setFunction(zone_, node->fun()->slot(), fun);
  1128 }
  1129 
  1130 void
  1131 BytecodeCompiler::visit(FunctionTypeStatement *node)
  1132 {
  1133 }
  1134 
  1135 void
  1136 BytecodeCompiler::visit(EnumStatement *node)
  1137 {
  1138 }
  1139 
  1140 void
  1141 BytecodeCompiler::visit(StructureStatement *node)
  1142 {
  1143 }
  1144 
  1145 Code *
  1146 BytecodeCompiler::compileCode(Scope *scope, unsigned lineno)
  1147 {
  1148     // STOP doubles as RETURNVOID.
  1149     __ stop();
  1150 
  1151     if (__ oom() || zone_->hasPendingException())
  1152         return NULL;
  1153 
  1154     Local<ByteArray> bytes(zone_, ByteArray::New(zone_, __ length() * sizeof(bytecode), Heap::Tenure_Old));
  1155     if (!bytes)
  1156         return NULL;
  1157     memcpy(bytes->raw(), __ buffer(), __ length());
  1158 
  1159     for (size_t i = 0; i < scope->maxContainedLocals(); i++)
  1160         assert(locals_->at(i));
  1161 
  1162     Local<FixedArray> objects(zone_, FixedArray::New(zone_, __ objects()->length(), Heap::Tenure_Old));
  1163     if (!objects)
  1164         return NULL;
  1165 
  1166     for (size_t i = 0; i < __ objects()->length(); i++)
  1167         objects->set(zone_, i, *(__ objects()->at(i)));
  1168 
  1169     Local<ByteArray> safepoints(zone_);
  1170 
  1171     // If any stack slots hold gc pointers at potential failure points in the
  1172     // bytecode, record them now. We do this by building a list of tuples;
  1173     // each tuple contains the pc offset, and a bitset containing which stack
  1174     // slots must be scanned by the gc.
  1175     if (__ oopRecords()->length()) {
  1176         size_t bytesPerSafepoint = Code::BytesPerSafepoint(__ maxStackDepth());
  1177         size_t gcmapSize = bytesPerSafepoint * __ oopRecords()->length();
  1178         safepoints = ByteArray::New(zone_, gcmapSize, Heap::Tenure_Old);
  1179         if (!safepoints)
  1180             return NULL;
  1181 
  1182         Address cursor = safepoints->raw();
  1183         for (size_t i = 0; i < __ oopRecords()->length(); i++) {
  1184             OopRecord *record = __ oopRecords()->at(i);
  1185             assert(record->depth <= __ maxStackDepth());
  1186 
  1187             *reinterpret_cast<unsigned *>(cursor) = record->offset;
  1188 
  1189             unsigned char *bits = reinterpret_cast<unsigned char *>(cursor + sizeof(unsigned));
  1190             for (unsigned i = 0; i < record->depth; i++)
  1191                 bits[i / 8] |= (1 << (i % 8));
  1192 
  1193             cursor += bytesPerSafepoint;
  1194         }
  1195 
  1196         assert(cursor == safepoints->raw() + gcmapSize);
  1197     }
  1198 
  1199     Local<ByteArray> sourcemap(zone_);
  1200     if (__ sourcemapLength()) {
  1201         sourcemap = ByteArray::New(zone_, __ sourcemapLength(), Heap::Tenure_Old);
  1202         if (!sourcemap)
  1203             return NULL;
  1204 
  1205         memcpy(sourcemap->raw(), __ sourcemap(), __ sourcemapLength());
  1206     }
  1207 
  1208     Local<Code> code(zone_);
  1209 
  1210     code = Code::New(zone_,
  1211                      bytes,
  1212                      locals_,
  1213                      objects,
  1214                      __ maxStackDepth(),
  1215                      moduleData_->module,
  1216                      safepoints,
  1217                      sourcemap,
  1218                      lineno);
  1219     return code;
  1220 }
  1221 
  1222 Function *
  1223 BytecodeCompiler::compileFunction(ModuleData *module, FunctionStatement *node)
  1224 {
  1225     // Note: No need to record a life slot here, since it's part of the Frame.
  1226     AutoEnterScope functionScope(this, node->scope());
  1227 
  1228     // Set the initial line, because line mappings are deltas.
  1229     __ setFirstLine(node->pos().line);
  1230     locals_ = FixedArray::New(zone_, node->scope()->maxContainedLocals(), Heap::Tenure_Old);
  1231 
  1232     node->body()->accept(this);
  1233 
  1234     unsigned nargs = node->scope()->numArguments();
  1235     Local<FixedArray> args(zone_, FixedArray::New(zone_, nargs, Heap::Tenure_Old));
  1236     if (!args)
  1237         return NULL;
  1238 
  1239     for (size_t i = 0; i < node->scope()->numArguments(); i++)
  1240         args->set(zone_, i, node->scope()->getArgument(i)->type());
  1241 
  1242 
  1243     Local<Code> code(zone_, compileCode(node->scope(), node->pos().line));
  1244     if (!code)
  1245         return NULL;
  1246 
  1247     Local<Type> type(zone_, node->fun()->type());
  1248     Local<String> name(zone_, node->fun()->name());
  1249     Local<Function> fun(zone_, Function::New(zone_, code, type, name, node->pos()));
  1250     if (!fun)
  1251         return NULL;
  1252 
  1253     // If this function had a forward, export it as a named public.
  1254     if (node->fun()->isPublic()) {
  1255         assert(node->fun()->isPublic());
  1256         ScopedRoot<Function> root(fun);
  1257         if (!root)
  1258             return NULL;
  1259         if (!moduleData_->publics.append(root))
  1260             return NULL;
  1261     }
  1262 
  1263 #ifndef NDEBUG
  1264     Disassemble(code, stdout);
  1265 #endif
  1266     
  1267     return fun;
  1268 }
  1269 
  1270 Module *
  1271 BytecodeCompiler::compile()
  1272 {
  1273     AutoEnterScope scope(this, tree_->scope());
  1274 
  1275     ModuleData moduleData;
  1276 
  1277     moduleData_ = &moduleData;
  1278     moduleData_->module = Module::New(zone_, tree_->scope()->numFunctions());
  1279 
  1280     if (!moduleData_)
  1281         return NULL;
  1282     
  1283     moduleData_->natives = FixedArray::New(zone_, tree_->scope()->numNatives(), Heap::Tenure_Old);
  1284     if (!moduleData_->natives)
  1285         return NULL;
  1286 
  1287     for (size_t i = 0; i < tree_->statements()->length(); i++) {
  1288         Statement *statement = tree_->statements()->at(i);
  1289         statement->accept(this);
  1290     }
  1291 
  1292     if (zone_->hasPendingException())
  1293         return NULL;
  1294 
  1295 #ifndef NDEBUG
  1296     for (size_t i = 0; i < tree_->scope()->numFunctions(); i++)
  1297         assert(moduleData_->module->getFunction(i));
  1298     for (size_t i = 0; i < tree_->scope()->numNatives(); i++)
  1299         assert(moduleData_->natives->at(i));
  1300 #endif
  1301 
  1302     if (moduleData_->publics.length()) {
  1303         Local<Function> fun(zone_);
  1304         Local<FixedArray> list(zone_, FixedArray::New(zone_, moduleData_->publics.length(),
  1305                                Heap::Tenure_Old));
  1306         if (!list)
  1307             return NULL;
  1308 
  1309         for (size_t i = 0; i < moduleData_->publics.length(); i++)
  1310             list->set(zone_, i, moduleData_->publics[i]);
  1311 
  1312         moduleData_->module->setPublics(list);
  1313     }
  1314 
  1315     moduleData_->module->setNatives(moduleData_->natives);
  1316 
  1317     if (scope_->numEnvironmentVars()) {
  1318         Local<EnvironmentMap> globalMap(zone_, scope_->createEnvironmentMap(zone_));
  1319         if (!globalMap)
  1320             return NULL;
  1321 
  1322         Local<Environment> environment(zone_, Environment::New(zone_, globalMap));
  1323         if (!environment)
  1324             return NULL;
  1325 
  1326         moduleData_->module->setEnvironment(environment);
  1327     }
  1328 
  1329     Local<Code> code(zone_, compileCode(tree_->scope(), 1));
  1330     if (!code)
  1331         return NULL;
  1332 
  1333     Disassemble(code, stdout);
  1334 
  1335     moduleData_->module->setCode(code);
  1336 
  1337     return moduleData_->module;
  1338 }