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