Enable dynamic array declarations.
1 /* vim: set ts=4 sw=4 tw=99 et:
3 * Copyright (C) 2012 David Anderson
5 * This file is part of JITCraft.
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)
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.
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/.
20 #include "BytecodeCompiler.h"
27 #include "Environments.h"
33 typedef BytecodeEmitter::Label Label;
37 BytecodeCompiler::BytecodeCompiler(Zone *zone, ParseTree *tree, ModuleData *module)
40 emitter_(zone->pool()),
48 static inline TokenKind
49 ToCompare(Expression *expr)
51 if (expr->isBinaryExpression()) {
52 BinaryExpression *b = expr->toBinaryExpression();
53 if (b->token() >= TOK_EQUALS && b->token() <= TOK_OR)
55 } else if (expr->isUnaryExpression()) {
56 UnaryExpression *u = expr->toUnaryExpression();
57 if (u->token() == TOK_NOT)
64 CompareTokenToJump(TokenKind kind)
78 assert(kind == TOK_LE);
84 TokenToOpcode(TokenKind kind)
120 assert(kind == TOK_BITXOR);
126 BytecodeCompiler::recordLifoSlot(Scope *scope)
131 if (Variable *var = scope->lifoSlot()) {
132 locals_->set(zone_, var->slot(), var->type());
133 __ savelifo(var->slot());
138 BytecodeCompiler::unwindTo(Scope *scope)
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())
148 __ unwindlifo(var->slot());
152 BytecodeCompiler::visit(NameProxy *name)
154 switch (name->binding()->kind()) {
155 case BoundName::VARIABLE:
157 Variable *var = name->binding()->toVariable();
159 if (var->location() == Variable::STACK) {
161 assert(!name->type()->isReference());
162 } else if (var->location() == Variable::ENVIRONMENT) {
165 assert(var->location() == Variable::PARAMETER);
168 // If this argument is actually a reference, dereference it now.
169 if (var->type()->isReference())
170 __ getref(var->type()->contained());
175 case BoundName::FUNCTION:
177 NamedFunction *fun = name->binding()->toNamedFunction();
179 __ getmodule_fn(fun->slot());
185 NamedConstant *constant = name->binding()->toNamedConstant();
186 __ int_(constant->value().toInt());
193 BytecodeCompiler::visit(ExpressionStatement *node)
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())
203 IsCompositeValueType(Type *type)
205 return type->isStruct() ||
206 (type->isArray() && type->isFixedLength());
210 BytecodeCompiler::visit(Assignment *node)
212 Local<Type> left(zone_, node->type());
213 Local<Type> right(zone_, node->expression()->type());
215 // The first step is three sub-steps:
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.
222 if (node->lvalue()->isNameProxy()) {
223 NameProxy *proxy = node->lvalue()->toNameProxy();
224 Variable *var = proxy->binding()->toVariable();
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()))
233 // Get the value if needed.
234 if (node->token() != TOK_ASSIGN) {
235 // += etc is not allowed on arrays.
236 assert(!var->type()->isArray());
238 if (var->location() == Variable::ENVIRONMENT)
241 if (var->type()->isReference()) {
243 __ getref(var->type()->contained());
244 } else if (var->location() != Variable::ENVIRONMENT) {
248 } else if (node->lvalue()->isFieldExpression()) {
249 FieldExpression *expr = node->lvalue()->toFieldExpression();
250 __ note_position(expr->pos());
252 expr->left()->accept(this);
254 if (node->token() != TOK_ASSIGN)
257 if (node->token() != TOK_ASSIGN || IsCompositeValueType(left))
258 __ getfield(expr->fieldIndex(), left);
260 IndexExpression *index = node->lvalue()->toIndexExpression();
261 __ note_position(index->pos());
263 index->left()->accept(this);
264 index->right()->accept(this);
266 if (node->token() != TOK_ASSIGN)
269 if (node->token() != TOK_ASSIGN || IsCompositeValueType(left))
273 if (node->token() == TOK_ASSIGN) {
274 node->expression()->accept(this);
276 visitForALU(left, node->expression());
278 TokenKind alu = TokenKind(int(node->token()) - (TOK_ASSIGN_ADD - TOK_PLUS));
279 __ note_position(node->pos());
280 __ binary(TokenToOpcode(alu));
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());
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());
296 } else if (node->lvalue()->isNameProxy()) {
297 NameProxy *proxy = node->lvalue()->toNameProxy();
298 Variable *var = proxy->binding()->toVariable();
300 if (var->type()->isReference())
301 __ setref(var->type()->contained());
302 else if (var->location() == Variable::ENVIRONMENT)
306 } else if (node->lvalue()->isFieldExpression()) {
307 FieldExpression *expr = node->lvalue()->toFieldExpression();
308 __ setfield(expr->fieldIndex(), left);
315 BytecodeCompiler::visit(IncDecExpression *node)
317 // In the postfix case, the logic looks like:
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
327 // In the prefix case, the logic looks like:
329 // (2) Dup -> REF REF
330 // (3) Fetch -> REF VAL
333 // (6) Add -> REF VAL+1
334 // (7) Store -> VAL+1
337 // This is squirrely enough such that we don't bother sharing too much
340 // Note: We simulate a "Pick" operation with a dup2+pop.
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();
349 if (var->location() == Variable::ENVIRONMENT)
351 else if (var->type()->isReference() || var->type()->isArray())
355 if (var->type()->isReference()) {
357 __ getref(node->type());
358 if (node->postfix()) {
363 assert(!var->type()->isArray());
364 if (var->location() != Variable::ENVIRONMENT)
369 } else if (expr->isFieldExpression()) {
370 FieldExpression *field = expr->toFieldExpression();
372 field->left()->accept(this);
374 __ getfield(field->fieldIndex(), field->type());
376 if (node->postfix()) {
377 // The stack looks like this now:
379 __ swap(); // VALUE OBJECT
380 __ pick2(); // VALUE OBJECT VALUE
383 IndexExpression *index = expr->toIndexExpression();
384 __ note_position(index->pos());
386 index->left()->accept(this);
387 index->right()->accept(this);
389 assert(!node->type()->isArray());
391 __ getelem(node->type());
393 if (node->postfix()) {
394 // The stack looks like this now:
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
405 if (node->type()->isFloat()) {
408 assert(node->type()->isInt32());
412 __ note_position(node->pos());
413 if (node->token() == TOK_INCREMENT)
419 if (expr->isNameProxy()) {
420 NameProxy *proxy = expr->toNameProxy();
421 Variable *var = proxy->binding()->toVariable();
423 if (var->type()->isReference())
424 __ setref(node->type());
425 else if (var->location() == Variable::ENVIRONMENT)
429 } else if (expr->isFieldExpression()) {
430 FieldExpression *field = expr->toFieldExpression();
431 __ setfield(field->fieldIndex(), field->type());
433 assert(expr->isIndexExpression());
434 __ setelem(node->type());
443 BytecodeCompiler::visitForALU(Type *needed, Expression *node)
446 if (needed->isFloat() && !node->type()->isFloat())
449 assert(needed->primitive() == node->type()->primitive());
453 GetCoercionType(TokenKind tok, Type *left, Type *right)
461 BytecodeCompiler::visit(UnaryExpression *node)
463 Local<Type> out(zone_, ((Expression *)node)->type());
465 switch (node->token()) {
468 Local<Type> type(zone_, node->expression()->type());
469 node->expression()->accept(this);
480 Local<Type> type(zone_, node->expression()->type());
481 node->expression()->accept(this);
492 Local<Type> from(zone_, node->expression()->type());
494 node->expression()->accept(this);
495 if (!from->isFloat() && out->isFloat())
497 else if (from->isFloat() && !out->isFloat())
503 assert(node->token() == TOK_TILDE);
504 node->expression()->accept(this);
511 BytecodeCompiler::visit(BinaryExpression *node)
513 if (node->token() == TOK_AND || node->token() == TOK_OR) {
514 Label success, failure, done;
515 visitForTest(node, &success, &failure, &success);
518 __ drop(1); // Otherwise, the stack depth will be +1 too much.
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));
530 visitForALU(coerce, node->left());
531 visitForALU(coerce, node->right());
533 Opcode op = TokenToOpcode(node->token());
534 if (node->type()->isFloat())
535 op = (Opcode)(int(op) + (OP_ADD_F - OP_ADD));
537 __ note_position(node->pos());
542 BytecodeCompiler::visit(IndexExpression *node)
544 node->left()->accept(this);
545 node->right()->accept(this);
546 __ note_position(node->pos());
547 __ getelem(node->type());
551 BytecodeCompiler::visit(FieldExpression *node)
553 node->left()->accept(this);
554 __ getfield(node->fieldIndex(), node->type());
558 BytecodeCompiler::visit(ReturnStatement *node)
560 if (node->expression()) {
561 node->expression()->accept(this);
569 BytecodeCompiler::visitForTest(Expression *expression,
574 TokenKind token = ToCompare(expression);
575 if (token == TOK_EOF || token == TOK_NOT) {
576 if (token == TOK_EOF)
577 expression->accept(this);
579 expression->toUnaryExpression()->expression()->accept(this);
581 bool jumpOnTrue = (fallthrough == falseBranch) ^ (token == TOK_NOT);
583 Opcode op = jumpOnTrue ? OP_JT : OP_JF;
584 if (expression->type()->isFloat())
585 op = (Opcode)(int(op) + (OP_JL_F - OP_JL));
587 if (fallthrough == falseBranch)
588 __ j(op, trueBranch);
590 __ j(op, falseBranch);
594 BinaryExpression *binary = expression->toBinaryExpression();
596 if (token == TOK_AND || token == TOK_OR) {
598 if (token == TOK_AND)
599 visitForTest(binary->left(), &next, falseBranch, &next);
601 visitForTest(binary->left(), trueBranch, &next, &next);
603 visitForTest(binary->right(), trueBranch, falseBranch, fallthrough);
607 Opcode op = CompareTokenToJump(token);
608 if (fallthrough == trueBranch)
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));
615 visitForALU(coerce, binary->left());
616 visitForALU(coerce, binary->right());
617 if (coerce->isFloat())
618 op = (Opcode)(int(op) + (OP_JL_F - OP_JL));
620 if (fallthrough == trueBranch)
621 __ j(op, falseBranch);
623 __ j(op, trueBranch);
627 BytecodeCompiler::visit(ForStatement *node)
629 AutoEnterScope forScope(this, node->scope());
631 recordLifoSlot(node->scope());
634 LoopScope loop(scope_, &join, &update, &loop_);
636 if (node->initialization())
637 node->initialization()->accept(this);
640 if (node->condition())
644 node->body()->accept(this);
648 node->update()->accept(this);
650 if (node->condition()) {
652 visitForTest(node->condition(), &header, &join, &join);
660 unwindTo(node->scope()->enclosing());
661 assert(__ stackDepth() == 0);
665 BytecodeCompiler::visit(WhileStatement *node)
671 LoopScope loop(scope_, &join, &header, &loop_);
673 if (node->token() == TOK_WHILE) {
676 visitForTest(node->condition(), &body, &join, &body);
678 node->body()->accept(this);
681 node->body()->accept(this);
682 visitForTest(node->condition(), &header, &join, &join);
689 BytecodeCompiler::visit(BreakStatement *node)
691 unwindTo(loop_->scope());
692 __ jump(loop_->break_());
696 BytecodeCompiler::visit(ContinueStatement *node)
698 unwindTo(loop_->scope());
699 __ jump(loop_->continue_());
703 BytecodeCompiler::visit(BlockStatement *node)
705 AutoEnterScope blockScope(this, node->scope());
707 recordLifoSlot(node->scope());
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);
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());
722 BytecodeCompiler::visit(IntegerLiteral *node)
724 __ int_(node->value());
728 BytecodeCompiler::visit(BooleanLiteral *node)
730 if (node->token() == TOK_TRUE)
737 BytecodeCompiler::visit(FloatLiteral *node)
739 __ float_((float)node->value());
742 static inline Array *
743 StringLiteralToArray(Zone *zone, StringLiteral *node)
745 Local<Type> type(zone, node->type());
746 Local<ArrayMap> map(zone, ArrayMap::Attach(zone, type));
750 return Array::NewString(zone,
752 node->string()->raw(),
753 node->string()->length(),
758 BytecodeCompiler::visit(StringLiteral *node)
760 Local<Array> array(zone_, StringLiteralToArray(zone_, node));
764 __ note_position(node->pos());
769 BytecodeCompiler::getEnvSlot(Variable *var)
771 assert(var->scope()->kind() == Scope::GLOBAL);
776 BytecodeCompiler::setEnvSlot(Variable *var)
778 assert(var->scope()->kind() == Scope::GLOBAL);
783 FillArrayLiteral_String(Zone *zone, Handle<Array> array, ArrayLiteral *literal, unsigned *maxsize)
785 Local<Array> string(zone);
786 for (size_t i = 0; i < literal->expressions()->length(); i++) {
787 Expression *expr = literal->expressions()->at(i);
788 StringLiteral *lit = expr->toStringLiteral();
789 if ((string = StringLiteralToArray(zone, lit)) == NULL)
792 array->writeObject(zone, i, string);
794 if (string->length() > *maxsize)
795 *maxsize = string->length();
797 assert(!array->type()->contained()->isFixedLength() ||
798 array->type()->contained()->fixedLength() >= string->length());
805 FillArrayLiteral_Primitive(Zone *zone, Handle<Array> array, ArrayLiteral *literal)
807 assert(array->type()->fixedLength() == literal->expressions()->length());
809 for (size_t i = 0; i < literal->expressions()->length(); i++) {
810 Expression *expr = literal->expressions()->at(i);
811 if (IntegerLiteral *lit = expr->asIntegerLiteral()) {
812 array->writeInt32(i, lit->value());
815 if (BooleanLiteral *lit = expr->asBooleanLiteral()) {
816 if (lit->token() == TOK_TRUE)
817 array->writeInt32(i, 1);
819 array->writeInt32(i, 0);
822 if (FloatLiteral *lit = expr->asFloatLiteral()) {
823 array->writeFloat(i, lit->value());
827 // Unrecognized literal type.
835 TraverseArrayLiteral(Zone *zone, ArrayLiteral *literal, Handle<Array> array, Handle<Type> type,
838 assert(type->fixedLength() == literal->expressions()->length());
840 Local<Type> contained(zone, type->contained());
841 if (contained->isCharArray())
842 return FillArrayLiteral_String(zone, array, literal, maxsize);
844 if (!contained->isArray())
845 return FillArrayLiteral_Primitive(zone, array, literal);
847 Local<Array> subarray(zone);
848 for (size_t i = 0; i < literal->expressions()->length(); i++) {
849 Expression *expr = literal->expressions()->at(i);
850 subarray = Array::cast(array->readObject(i));
851 if (!TraverseArrayLiteral(zone, expr->toArrayLiteral(), subarray, contained, maxsize))
859 BuildArrayLiteral(Zone *zone, ArrayLiteral *literal, Handle<ArrayMap> map, unsigned *maxsize)
861 Local<Array> root(zone, Array::NewFixed(zone, map, Heap::Tenure_Old));
865 // This should have allocated everything in the array, so all we need to
866 // do is traverse down to the lowest levels and copy things.
867 Local<Type> type(zone, map->type());
868 if (!TraverseArrayLiteral(zone, literal, root, type, maxsize))
875 ArrayContainsCharBuffers(Type *type)
877 if (type->contained()->isArray())
878 return ArrayContainsCharBuffers(type->contained());
879 return type->isCharArray();
883 BytecodeCompiler::visit(VariableDeclaration *node)
885 Variable *var = node->variable();
887 Local<Type> type(zone_, var->type());
888 if (type->isArray()) {
889 Local<ArrayMap> map(zone_, ArrayMap::Attach(zone_, type));
890 __ note_position(node->pos());
892 Local<Type> right(zone_);
893 if (node->initialization())
894 right = node->initialization()->type();
896 // There are a few methods for allocating, here:
897 // (1) If the array is fixed,
898 // (a) Initializer not present,
900 // (b) Left is const non-string:
905 // (2) If the array is not fixed,
906 // (a) Initializer is not present,
908 // (b) Initializer is not a string literal,
911 // (c) Initializer is a string literal,
916 Heap::Tenure tenure = var->scope()->kind() == Scope::GLOBAL
918 : Heap::Tenure_Default;
920 if (Expression *init = node->initialization()) {
921 if (init->isArrayLiteral()) {
922 unsigned maxsize = 0;
923 Local<Array> array(zone_, BuildArrayLiteral(zone_, init->toArrayLiteral(), map, &maxsize));
927 assert(type->isFixedLength());
929 if (type->isConst()) {
931 } else if (ArrayContainsCharBuffers(type)) {
932 // This array contains mutable char buffers, so
933 // unfortunately this gets a little more complicated. We
934 // compute the maximum size needed for the innermost
935 // string, which is similar to SP1. This means we can use
936 // CopyArray rather than individually emit opcodes to clone
938 Local<Type> child(zone_, type);
939 for (size_t i = 0; i < type->levels() - 1; i++) {
940 __ int_(child->fixedLength());
941 child = child->contained();
944 __ newarray(OP_NEWSIZED, map, tenure);
948 __ newarray(OP_NEWFIXED, map, tenure);
952 } else if (type->isFixedLength()) {
953 // Note in the case of:
954 // const String:buffer[50] = "hello";
956 // We want to preserve sizeof(buffer) == 50.
957 if (type->isConst() && !type->isCharArray()) {
960 __ newarray(OP_NEWFIXED, map, tenure);
964 } else if (!type->isConst() && init->isStringLiteral()) {
965 // This is a degenerate case of ArrayLiteral.
966 __ int_(right->fixedLength());
967 __ newarray(OP_NEWSIZED, map, tenure);
970 } else if (type->isConst()) {
973 } else if (type->isFixedLength()) {
974 __ newarray(OP_NEWFIXED, map, tenure);
976 if (node->postDimensions()) {
977 for (size_t i = 0; i < node->postDimensions()->length(); i++) {
978 Expression *expr = node->postDimensions()->at(i);
984 __ newarray(OP_NEWSIZED, map, tenure);
986 __ newarray(OP_NEWEMPTY, map, tenure);
989 } else if (type->isStruct()) {
990 Local<Map> map(zone_, type->newMap());
991 if (var->scope()->kind() == Scope::GLOBAL)
992 __ newstruct(map, Heap::Tenure_Old);
993 else if (var->needsHeapAllocation())
994 __ newstruct(map, Heap::Tenure_Default);
996 __ newstruct(map, Heap::Tenure_Stack);
998 if (node->initialization()) {
999 node->initialization()->accept(this);
1001 if (type->isInt32OrEnum() || type->isBool()) {
1004 assert(type->isFloat());
1010 if (var->location() == Variable::STACK) {
1012 locals_->set(zone_, var->slot(), var->type());
1014 assert(var->location() == Variable::ENVIRONMENT);
1022 BytecodeCompiler::visit(CallExpression *node)
1024 Local<Type> funType(zone_, node->callee()->type());
1026 // Sniff out natives, which have a specific opcode and are guaranteed to
1027 // be called via name proxy.
1028 NamedFunction *native = NULL;
1029 if (funType->isNative())
1030 native = node->callee()->toNameProxy()->binding()->toNamedFunction();
1032 Local<Type> given(zone_);
1033 for (size_t i = node->arguments()->length() - 1; i < node->arguments()->length(); i--) {
1034 Expression *arg = node->arguments()->at(i);
1036 given = arg->type();
1038 // We need to compute a reference if the parameter was in the form:
1040 // Note this form does not allow: f({})
1042 // We also need to compute references for all variadic native
1043 // arguments, but arrays and references are already in the
1044 // appropriate form.
1045 bool mustPushReference = false;
1046 if (i >= funType->parameters()->length()) {
1047 assert(funType->isNative() && funType->isNativeVariadic());
1048 mustPushReference = !given->isArray() && !given->isReference();
1049 } else if (funType->parameterAt(i)->isReference()) {
1050 mustPushReference = !given->isReference();
1053 // If a native is passed to a native, it must only be one level deep.
1054 assert(!funType->isNative() || !given->isArray() || given->levels() == 1);
1056 if (mustPushReference) {
1057 if (arg->isNameProxy()) {
1058 // :TODO: test with functions and globals
1059 // Compute a reference to the name.
1060 Variable *var = arg->toNameProxy()->binding()->toVariable();
1061 __ note_position(node->pos());
1063 } else if (arg->isFieldExpression()) {
1064 FieldExpression *expr = arg->toFieldExpression();
1065 expr->left()->accept(this);
1066 __ note_position(expr->pos());
1067 __ fieldref_lifo(expr->fieldIndex());
1069 // We don't know how to, or can't, build a direct reference to
1070 // this type. Make an indirect one, by taking the top of the
1071 // stack and boxing it up.
1073 __ note_position(node->pos());
1081 unsigned argc = node->arguments()->length();
1083 // If there are missing arguments, then we're not done and have to push
1084 // default parameters.
1085 Local<Box> box(zone_);
1086 Local<Array> array(zone_);
1087 Local<ArrayMap> map(zone_);
1088 for (size_t i = node->arguments()->length(); i < funType->parameters()->length(); i++) {
1089 box = Box::cast(funType->defaults()->at(i));
1091 if (box->type()->isPod()) {
1092 if (box->type()->pod() == PrimitiveType_Int32)
1093 __ int_(box->toInt32());
1094 else if (box->type()->pod() == PrimitiveType_Float)
1095 __ float_(box->toFloat());
1099 if (funType->parameterAt(i)->isReference()) {
1100 __ note_position(node->pos());
1104 assert(box->type()->isArray());
1106 array = Array::cast(box->toObject());
1107 if (funType->parameterAt(i)->isConst()) {
1110 // We need to copy the array since it's mutable. Note that
1111 // although COPYARRAY returns its left-hand side, this may
1112 // change in the future, we do the same thing and dupe the
1113 // newly allocated array.
1114 map = ArrayMap::cast(array->map());
1116 // Natives cannot escape array references, so we can allocate
1117 // them on the LIFO stack.
1118 if (funType->isNative())
1119 __ newarray(OP_NEWFIXED, map, Heap::Tenure_Stack);
1121 __ newarray(OP_NEWFIXED, map, Heap::Tenure_Default);
1132 __ note_position(node->pos());
1134 __ callnative(native->slot(), argc);
1137 node->callee()->accept(this);
1144 BytecodeCompiler::visit(TernaryExpression *node)
1146 Label success, failure, join;
1148 visitForTest(node->condition(), &success, &failure, &success);
1150 node->left()->accept(this);
1154 node->right()->accept(this);
1159 BytecodeCompiler::visit(IfStatement *node)
1162 if (!node->ifFalse()) {
1165 visitForTest(node->condition(), &success, &join, &success);
1167 node->ifTrue()->accept(this);
1169 Label success, next;
1171 visitForTest(node->condition(), &success, &next, &success);
1173 node->ifTrue()->accept(this);
1176 node->ifFalse()->accept(this);
1183 BytecodeCompiler::tableswitch(SwitchStatement *node)
1185 CaseValueList *values = node->caseValueList();
1187 if (values->length() < 3)
1190 // Find the delta between the largest and smallest value.
1191 int hi = values->at(values->length() - 1).box.toInt();
1192 int lo = values->at(0).box.toInt();
1195 unsigned tablesize = TableSwitchEntries(lo, hi);
1196 if (tablesize > MAX_TABLESWITCH_ENTRIES)
1201 // Create the list of labels that each statement will bind to.
1202 Label *labels = new Label[node->cases()->length()];
1204 // Create the table of labels we'll use for each case.
1205 Label **table = new Label *[tablesize];
1207 // Link all cases, by default, to the default label.
1208 for (size_t i = 0; i < tablesize; i++)
1211 // Now patch actual cases to their correct labels.
1212 for (size_t i = 0; i < values->length(); i++) {
1213 CaseValue &v = values->at(i);
1214 assert(v.statement < node->cases()->length());
1216 unsigned index = unsigned(v.box.toInt() - lo);
1217 assert(index < tablesize);
1219 table[index] = &labels[v.statement];
1222 // Emit the tableswitch opcode and the jump table.
1223 __ tableswitch(lo, hi, &def, table);
1225 // We're done with the jump table now.
1228 // Emit each statement.
1229 for (size_t i = 0; i < node->cases()->length(); i++) {
1230 Statement *stmt = node->cases()->at(i)->statement();
1232 __ bind(&labels[i]);
1237 // We're done with the statement labels.
1240 // Emit the default case.
1242 if (node->defaultCase())
1243 node->defaultCase()->accept(this);
1251 BytecodeCompiler::visit(SwitchStatement *node)
1253 node->expression()->accept(this);
1255 if (tableswitch(node))
1260 for (size_t i = 0; i < node->cases()->length(); i++) {
1261 Case *c = node->cases()->at(i);
1263 Label success, fail;
1265 for (size_t j = 0; j < c->others()->length(); j++) {
1266 Expression *expr = c->others()->at(j);
1270 __ j(OP_JEQ, &success);
1276 c->expression()->accept(this);
1277 __ j(OP_JNE, &fail);
1279 c->statement()->accept(this);
1284 if (node->defaultCase())
1285 node->defaultCase()->accept(this);
1292 BytecodeCompiler::visit(FunctionStatement *node)
1294 if (!node->fun()->used())
1297 if (node->fun()->isNative()) {
1298 assert(!moduleData_->natives->at(node->fun()->slot()));
1300 Local<Type> type(zone_, node->fun()->type());
1301 Local<String> name(zone_, node->fun()->name());
1302 Local<Native> native(zone_, Native::New(zone_, type, name));
1306 moduleData_->natives->set(zone_, node->fun()->slot(), native);
1310 // If the function has no body, then it's just a declaration.
1311 if (!node->body()) {
1312 assert(node->fun()->isForward() || node->fun()->isPublic());
1316 BytecodeCompiler child(zone_, tree_, moduleData_);
1317 Local<Function> fun(zone_, child.compileFunction(moduleData_, node));
1321 assert(!moduleData_->module->getFunction(node->fun()->slot()));
1322 moduleData_->module->setFunction(zone_, node->fun()->slot(), fun);
1326 BytecodeCompiler::visit(FunctionTypeStatement *node)
1331 BytecodeCompiler::visit(EnumStatement *node)
1336 BytecodeCompiler::visit(StructureStatement *node)
1341 BytecodeCompiler::visit(ArrayLiteral *node)
1343 // We shouldn't reach these; they're handled manually when initializing
1349 BytecodeCompiler::compileCode(Scope *scope, unsigned lineno)
1351 // STOP doubles as RETURNVOID.
1354 if (__ oom() || zone_->hasPendingException())
1357 Local<ByteArray> bytes(zone_, ByteArray::New(zone_, __ length() * sizeof(bytecode), Heap::Tenure_Old));
1360 memcpy(bytes->raw(), __ buffer(), __ length());
1362 for (size_t i = 0; i < scope->maxContainedLocals(); i++)
1363 assert(locals_->at(i));
1365 Local<FixedArray> objects(zone_, FixedArray::New(zone_, __ objects()->length(), Heap::Tenure_Old));
1369 for (size_t i = 0; i < __ objects()->length(); i++)
1370 objects->set(zone_, i, *(__ objects()->at(i)));
1372 Local<ByteArray> safepoints(zone_);
1374 // If any stack slots hold gc pointers at potential failure points in the
1375 // bytecode, record them now. We do this by building a list of tuples;
1376 // each tuple contains the pc offset, and a bitset containing which stack
1377 // slots must be scanned by the gc.
1378 if (__ oopRecords()->length()) {
1379 size_t bytesPerSafepoint = Code::BytesPerSafepoint(__ maxStackDepth());
1380 size_t gcmapSize = bytesPerSafepoint * __ oopRecords()->length();
1381 safepoints = ByteArray::New(zone_, gcmapSize, Heap::Tenure_Old);
1385 Address cursor = safepoints->raw();
1386 for (size_t i = 0; i < __ oopRecords()->length(); i++) {
1387 OopRecord *record = __ oopRecords()->at(i);
1388 assert(record->depth <= __ maxStackDepth());
1390 *reinterpret_cast<unsigned *>(cursor) = record->offset;
1392 unsigned char *bits = reinterpret_cast<unsigned char *>(cursor + sizeof(unsigned));
1393 for (unsigned i = 0; i < record->depth; i++)
1394 bits[i / 8] |= (1 << (i % 8));
1396 cursor += bytesPerSafepoint;
1399 assert(cursor == safepoints->raw() + gcmapSize);
1402 Local<ByteArray> sourcemap(zone_);
1403 if (__ sourcemapLength()) {
1404 sourcemap = ByteArray::New(zone_, __ sourcemapLength(), Heap::Tenure_Old);
1408 memcpy(sourcemap->raw(), __ sourcemap(), __ sourcemapLength());
1411 Local<Code> code(zone_);
1413 code = Code::New(zone_,
1418 moduleData_->module,
1426 BytecodeCompiler::compileFunction(ModuleData *module, FunctionStatement *node)
1428 // Note: No need to record a life slot here, since it's part of the Frame.
1429 AutoEnterScope functionScope(this, node->scope());
1431 // Set the initial line, because line mappings are deltas.
1432 __ setFirstLine(node->pos().line);
1433 locals_ = FixedArray::New(zone_, node->scope()->maxContainedLocals(), Heap::Tenure_Old);
1435 node->body()->accept(this);
1437 unsigned nargs = node->scope()->numArguments();
1438 Local<FixedArray> args(zone_, FixedArray::New(zone_, nargs, Heap::Tenure_Old));
1442 for (size_t i = 0; i < node->scope()->numArguments(); i++)
1443 args->set(zone_, i, node->scope()->getArgument(i)->type());
1446 Local<Code> code(zone_, compileCode(node->scope(), node->pos().line));
1450 Local<Type> type(zone_, node->fun()->type());
1451 Local<String> name(zone_, node->fun()->name());
1452 Local<Function> fun(zone_, Function::New(zone_, code, type, name, node->pos()));
1456 // If this function had a forward, export it as a named public.
1457 if (node->fun()->isPublic()) {
1458 assert(node->fun()->isPublic());
1459 ScopedRoot<Function> root(fun);
1462 if (!moduleData_->publics.append(root))
1467 Disassemble(code, stdout);
1474 BytecodeCompiler::compile()
1476 AutoEnterScope scope(this, tree_->scope());
1478 ModuleData moduleData;
1480 moduleData_ = &moduleData;
1481 moduleData_->module = Module::New(zone_, tree_->scope()->numFunctions());
1486 moduleData_->natives = FixedArray::New(zone_, tree_->scope()->numNatives(), Heap::Tenure_Old);
1487 if (!moduleData_->natives)
1490 for (size_t i = 0; i < tree_->statements()->length(); i++) {
1491 Statement *statement = tree_->statements()->at(i);
1492 statement->accept(this);
1495 if (zone_->hasPendingException())
1499 for (size_t i = 0; i < tree_->scope()->numFunctions(); i++)
1500 assert(moduleData_->module->getFunction(i));
1501 for (size_t i = 0; i < tree_->scope()->numNatives(); i++)
1502 assert(moduleData_->natives->at(i));
1505 if (moduleData_->publics.length()) {
1506 Local<Function> fun(zone_);
1507 Local<FixedArray> list(zone_, FixedArray::New(zone_, moduleData_->publics.length(),
1512 for (size_t i = 0; i < moduleData_->publics.length(); i++)
1513 list->set(zone_, i, moduleData_->publics[i]);
1515 moduleData_->module->setPublics(list);
1518 moduleData_->module->setNatives(moduleData_->natives);
1520 if (scope_->numEnvironmentVars()) {
1521 Local<EnvironmentMap> globalMap(zone_, scope_->createEnvironmentMap(zone_));
1525 Local<Environment> environment(zone_, Environment::New(zone_, globalMap));
1529 moduleData_->module->setEnvironment(environment);
1532 Local<Code> code(zone_, compileCode(tree_->scope(), 1));
1536 Disassemble(code, stdout);
1538 moduleData_->module->setCode(code);
1540 return moduleData_->module;