Preparatory refactoring for const types.
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 "../Modules.h"
23 #include "../Strings.h"
25 #include "../Environments.h"
27 #include "../Heap-inl.h"
28 #include "BytecodeCompiler.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());
209 static inline Array *
210 StringLiteralToArray(Zone *zone, StringLiteral *node)
212 Local<Type> type(zone, node->type());
213 Local<ArrayMap> map(zone, ArrayMap::Attach(zone, type));
217 return Array::NewString(zone,
219 node->string()->raw(),
220 node->string()->length(),
225 BytecodeCompiler::visit(Assignment *node)
227 Local<Type> left(zone_, node->type());
228 Local<Type> right(zone_, node->expression()->type());
230 // The first step is three sub-steps:
232 // (1) Bind the left-hand side.
233 // -- If a cumulative operation (+=, etc):
234 // (2) Save a copy of the binding on the stack.
235 // (3) Dereference the binding to get a value.
237 if (node->lvalue()->isNameProxy()) {
238 NameProxy *proxy = node->lvalue()->toNameProxy();
239 Variable *var = proxy->binding()->toVariable();
241 // We need to fetch the variable under the following circumstances:
242 // (1) The variable is a reference, since we'll store into the ref.
243 // (2) The variable is a fixed array, since we need to copy into it.
244 // (3) The variable is a struct, since we need to copy into it.
245 if (var->type()->isReference() || IsCompositeValueType(var->type()))
248 // Get the value if needed.
249 if (node->token() != TOK_ASSIGN) {
250 // += etc is not allowed on arrays.
251 assert(!var->type()->isArray());
253 if (var->location() == Variable::ENVIRONMENT)
256 if (var->type()->isReference()) {
258 __ getref(var->type()->contained());
259 } else if (var->location() != Variable::ENVIRONMENT) {
263 } else if (node->lvalue()->isFieldExpression()) {
264 FieldExpression *expr = node->lvalue()->toFieldExpression();
265 __ note_position(expr->pos());
267 expr->left()->accept(this);
269 if (node->token() != TOK_ASSIGN)
272 if (node->token() != TOK_ASSIGN || IsCompositeValueType(left))
273 __ getfield(expr->fieldIndex(), left);
275 IndexExpression *index = node->lvalue()->toIndexExpression();
276 __ note_position(index->pos());
278 index->left()->accept(this);
279 index->right()->accept(this);
281 if (node->token() != TOK_ASSIGN)
284 if (node->token() != TOK_ASSIGN || IsCompositeValueType(left))
288 if (node->token() == TOK_ASSIGN) {
289 // Special case: if the left-hand side is a string literal, we must
290 // spawn a new copy (:TODO: something about const?)
291 if (node->expression()->isStringLiteral() && !left->isFixedLength()) {
292 Local<Array> string(zone_,
293 StringLiteralToArray(zone_, node->expression()->toStringLiteral()));
297 Local<ArrayMap> arrayMap(zone_, ArrayMap::cast(string->map()));
298 __ note_position(node->expression()->pos());
299 __ int_(string->length());
300 __ newarray(OP_NEWSIZED, arrayMap, Heap::Tenure_Default);
304 node->expression()->accept(this);
307 visitForALU(left, node->expression());
309 TokenKind alu = TokenKind(int(node->token()) - (TOK_ASSIGN_ADD - TOK_PLUS));
310 __ note_position(node->pos());
311 __ binary(TokenToOpcode(alu));
315 if (left->isArray() && left->isFixedLength()) {
316 // (x = y) returns the left-hand side; if |x| is a fixed-length array,
317 // then |y| is as well, and we perform a deep copy.
318 assert(right->isFixedLength());
319 __ note_position(node->pos());
321 } else if (left->isStruct()) {
322 // Structs have value semantics, so emit a full copy. We don't break
323 // this down into u-ops, to avoid unnecessary bytecode explosion.
324 assert(right->isStruct());
325 __ note_position(node->pos());
327 } else if (node->lvalue()->isNameProxy()) {
328 NameProxy *proxy = node->lvalue()->toNameProxy();
329 Variable *var = proxy->binding()->toVariable();
331 if (var->type()->isReference())
332 __ setref(var->type()->contained());
333 else if (var->location() == Variable::ENVIRONMENT)
337 } else if (node->lvalue()->isFieldExpression()) {
338 FieldExpression *expr = node->lvalue()->toFieldExpression();
339 __ setfield(expr->fieldIndex(), left);
346 BytecodeCompiler::visit(IncDecExpression *node)
348 // In the postfix case, the logic looks like:
350 // (2) Dup -> REF REF
351 // (3) Fetch -> REF VAL
352 // (4) Swap -> VAL REF
353 // (5) Pick -> VAL REF VAL
354 // (6) Add -> VAL REF VAL+1
355 // (7) Store -> VAL VAL+1
358 // In the prefix case, the logic looks like:
360 // (2) Dup -> REF REF
361 // (3) Fetch -> REF VAL
364 // (6) Add -> REF VAL+1
365 // (7) Store -> VAL+1
368 // This is squirrely enough such that we don't bother sharing too much
371 // Note: We simulate a "Pick" operation with a dup2+pop.
373 // This is steps (1) to (5).
374 Expression *expr = node->expression();
375 if (expr->isNameProxy()) {
376 NameProxy *proxy = expr->toNameProxy();
377 Variable *var = proxy->binding()->toVariable();
380 if (var->location() == Variable::ENVIRONMENT)
382 else if (var->type()->isReference() || var->type()->isArray())
386 if (var->type()->isReference()) {
388 __ getref(node->type());
389 if (node->postfix()) {
394 assert(!var->type()->isArray());
395 if (var->location() != Variable::ENVIRONMENT)
400 } else if (expr->isFieldExpression()) {
401 FieldExpression *field = expr->toFieldExpression();
403 field->left()->accept(this);
405 __ getfield(field->fieldIndex(), field->type());
407 if (node->postfix()) {
408 // The stack looks like this now:
410 __ swap(); // VALUE OBJECT
411 __ pick2(); // VALUE OBJECT VALUE
414 IndexExpression *index = expr->toIndexExpression();
415 __ note_position(index->pos());
417 index->left()->accept(this);
418 index->right()->accept(this);
420 assert(!node->type()->isArray());
422 __ getelem(node->type());
424 if (node->postfix()) {
425 // The stack looks like this now:
428 // So we must use a PICK operation to rotate the stack into position.
429 __ roll3(); // INDEX VALUE ARRAY
430 __ roll3(); // VALUE ARRAY INDEX
431 __ pick3(); // VALUE ARRAY INDEX VALUE
436 if (node->type()->isFloat()) {
439 assert(node->type()->isInt32());
443 __ note_position(node->pos());
444 if (node->token() == TOK_INCREMENT)
450 if (expr->isNameProxy()) {
451 NameProxy *proxy = expr->toNameProxy();
452 Variable *var = proxy->binding()->toVariable();
454 if (var->type()->isReference())
455 __ setref(node->type());
456 else if (var->location() == Variable::ENVIRONMENT)
460 } else if (expr->isFieldExpression()) {
461 FieldExpression *field = expr->toFieldExpression();
462 __ setfield(field->fieldIndex(), field->type());
464 assert(expr->isIndexExpression());
465 __ setelem(node->type());
474 BytecodeCompiler::visitForALU(Type *needed, Expression *node)
477 if (needed->isFloat() && !node->type()->isFloat())
480 assert(needed->primitive() == node->type()->primitive());
484 GetCoercionType(TokenKind tok, Type *left, Type *right)
492 BytecodeCompiler::visit(UnaryExpression *node)
494 Local<Type> out(zone_, ((Expression *)node)->type());
496 switch (node->token()) {
499 Local<Type> type(zone_, node->expression()->type());
500 node->expression()->accept(this);
511 Local<Type> type(zone_, node->expression()->type());
512 node->expression()->accept(this);
523 Local<Type> from(zone_, node->expression()->type());
525 node->expression()->accept(this);
526 if (!from->isFloat() && out->isFloat())
528 else if (from->isFloat() && !out->isFloat())
535 Local<Type> type(zone_, node->expression()->type());
536 if (type->isFixedLength()) {
537 __ int_(type->fixedLength());
539 node->expression()->accept(this);
546 assert(node->token() == TOK_TILDE);
547 node->expression()->accept(this);
554 BytecodeCompiler::visit(BinaryExpression *node)
556 if (node->token() == TOK_AND || node->token() == TOK_OR) {
557 Label success, failure, done;
558 visitForTest(node, &success, &failure, &success);
561 __ drop(1); // Otherwise, the stack depth will be +1 too much.
569 Local<Type> leftType(zone_, node->left()->type());
570 Local<Type> rightType(zone_, node->right()->type());
571 Local<Type> coerce(zone_, GetCoercionType(node->token(), leftType, rightType));
573 visitForALU(coerce, node->left());
574 visitForALU(coerce, node->right());
576 Opcode op = TokenToOpcode(node->token());
577 if (node->type()->isFloat())
578 op = (Opcode)(int(op) + (OP_ADD_F - OP_ADD));
580 __ note_position(node->pos());
585 BytecodeCompiler::visit(IndexExpression *node)
587 node->left()->accept(this);
588 node->right()->accept(this);
589 __ note_position(node->pos());
590 __ getelem(node->type());
594 BytecodeCompiler::visit(FieldExpression *node)
596 node->left()->accept(this);
597 __ getfield(node->fieldIndex(), node->type());
601 BytecodeCompiler::visit(ReturnStatement *node)
603 if (node->expression()) {
604 node->expression()->accept(this);
612 BytecodeCompiler::visitForTest(Expression *expression,
617 TokenKind token = ToCompare(expression);
618 if (token == TOK_EOF || token == TOK_NOT) {
619 if (token == TOK_EOF)
620 expression->accept(this);
622 expression->toUnaryExpression()->expression()->accept(this);
624 bool jumpOnTrue = (fallthrough == falseBranch) ^ (token == TOK_NOT);
626 Opcode op = jumpOnTrue ? OP_JT : OP_JF;
627 if (expression->type()->isFloat())
628 op = (Opcode)(int(op) + (OP_JL_F - OP_JL));
630 if (fallthrough == falseBranch)
631 __ j(op, trueBranch);
633 __ j(op, falseBranch);
637 BinaryExpression *binary = expression->toBinaryExpression();
639 if (token == TOK_AND || token == TOK_OR) {
641 if (token == TOK_AND)
642 visitForTest(binary->left(), &next, falseBranch, &next);
644 visitForTest(binary->left(), trueBranch, &next, &next);
646 visitForTest(binary->right(), trueBranch, falseBranch, fallthrough);
650 Opcode op = CompareTokenToJump(token);
651 if (fallthrough == trueBranch)
654 Local<Type> leftType(zone_, binary->left()->type());
655 Local<Type> rightType(zone_, binary->right()->type());
656 Local<Type> coerce(zone_, GetCoercionType(binary->token(), leftType, rightType));
658 visitForALU(coerce, binary->left());
659 visitForALU(coerce, binary->right());
660 if (coerce->isFloat())
661 op = (Opcode)(int(op) + (OP_JL_F - OP_JL));
663 if (fallthrough == trueBranch)
664 __ j(op, falseBranch);
666 __ j(op, trueBranch);
670 BytecodeCompiler::visit(ForStatement *node)
672 AutoEnterScope forScope(this, node->scope());
674 recordLifoSlot(node->scope());
677 LoopScope loop(scope_, &join, &update, &loop_);
679 if (node->initialization())
680 node->initialization()->accept(this);
683 if (node->condition())
687 node->body()->accept(this);
691 node->update()->accept(this);
693 if (node->condition()) {
695 visitForTest(node->condition(), &header, &join, &join);
703 unwindTo(node->scope()->enclosing());
704 assert(__ stackDepth() == 0);
708 BytecodeCompiler::visit(WhileStatement *node)
714 LoopScope loop(scope_, &join, &header, &loop_);
716 if (node->token() == TOK_WHILE) {
719 visitForTest(node->condition(), &body, &join, &body);
721 node->body()->accept(this);
724 node->body()->accept(this);
725 visitForTest(node->condition(), &header, &join, &join);
732 BytecodeCompiler::visit(BreakStatement *node)
734 unwindTo(loop_->scope());
735 __ jump(loop_->break_());
739 BytecodeCompiler::visit(ContinueStatement *node)
741 unwindTo(loop_->scope());
742 __ jump(loop_->continue_());
746 BytecodeCompiler::visit(BlockStatement *node)
748 AutoEnterScope blockScope(this, node->scope());
750 recordLifoSlot(node->scope());
752 for (size_t i = 0; i < node->statements()->length(); i++) {
753 Statement *statement = node->statements()->at(i);
754 statement->accept(this);
755 assert(__ stackDepth() == 0);
758 // We don't bother emitting an "unwind" instruction for function scopes,
759 // since this is taken care of by the calling convention.
760 if (node->scope() && node->scope()->enclosing()->kind() != Scope::FUNCTION)
761 unwindTo(node->scope()->enclosing());
765 BytecodeCompiler::visit(IntegerLiteral *node)
767 __ int_(node->value());
771 BytecodeCompiler::visit(BooleanLiteral *node)
773 if (node->token() == TOK_TRUE)
780 BytecodeCompiler::visit(FloatLiteral *node)
782 __ float_((float)node->value());
786 BytecodeCompiler::visit(StringLiteral *node)
788 Local<Array> array(zone_, StringLiteralToArray(zone_, node));
792 __ note_position(node->pos());
797 BytecodeCompiler::getEnvSlot(Variable *var)
799 assert(var->scope()->kind() == Scope::GLOBAL);
804 BytecodeCompiler::setEnvSlot(Variable *var)
806 assert(var->scope()->kind() == Scope::GLOBAL);
811 FillArrayLiteral_String(Zone *zone, Handle<Array> array, ArrayLiteral *literal, unsigned *maxsize)
813 Local<Array> string(zone);
814 for (size_t i = 0; i < literal->expressions()->length(); i++) {
815 Expression *expr = literal->expressions()->at(i);
816 StringLiteral *lit = expr->toStringLiteral();
817 if ((string = StringLiteralToArray(zone, lit)) == NULL)
820 array->writeObject(zone, i, string);
822 if (string->length() > *maxsize)
823 *maxsize = string->length();
825 assert(!array->type()->contained()->isFixedLength() ||
826 array->type()->contained()->fixedLength() >= string->length());
833 FillArrayLiteral_Primitive(Zone *zone, Handle<Array> array, ArrayLiteral *literal)
835 assert(array->type()->fixedLength() == literal->expressions()->length());
837 for (size_t i = 0; i < literal->expressions()->length(); i++) {
838 Expression *expr = literal->expressions()->at(i);
839 if (IntegerLiteral *lit = expr->asIntegerLiteral()) {
840 array->writeInt32(i, lit->value());
843 if (BooleanLiteral *lit = expr->asBooleanLiteral()) {
844 if (lit->token() == TOK_TRUE)
845 array->writeInt32(i, 1);
847 array->writeInt32(i, 0);
850 if (FloatLiteral *lit = expr->asFloatLiteral()) {
851 array->writeFloat(i, (float)lit->value());
855 // Unrecognized literal type.
863 TraverseArrayLiteral(Zone *zone, ArrayLiteral *literal, Handle<Array> array, Handle<Type> type,
866 assert(type->fixedLength() == literal->expressions()->length());
868 Local<Type> contained(zone, type->contained());
869 if (contained->isCharArray())
870 return FillArrayLiteral_String(zone, array, literal, maxsize);
872 if (!contained->isArray())
873 return FillArrayLiteral_Primitive(zone, array, literal);
875 Local<Array> subarray(zone);
876 for (size_t i = 0; i < literal->expressions()->length(); i++) {
877 Expression *expr = literal->expressions()->at(i);
878 subarray = Array::cast(array->readObject(i));
879 if (!TraverseArrayLiteral(zone, expr->toArrayLiteral(), subarray, contained, maxsize))
887 BuildArrayLiteral(Zone *zone, ArrayLiteral *literal, Handle<ArrayMap> map, unsigned *maxsize)
889 Local<Array> root(zone, Array::NewFixed(zone, map, Heap::Tenure_Old));
893 // This should have allocated everything in the array, so all we need to
894 // do is traverse down to the lowest levels and copy things.
895 Local<Type> type(zone, map->type());
896 if (!TraverseArrayLiteral(zone, literal, root, type, maxsize))
903 ArrayContainsCharBuffers(Type *type)
905 if (type->contained()->isArray())
906 return ArrayContainsCharBuffers(type->contained());
907 return type->isCharArray();
911 BytecodeCompiler::visit(VariableDeclaration *node)
913 Variable *var = node->variable();
915 Local<Type> type(zone_, var->type());
916 if (type->isArray()) {
917 Local<ArrayMap> map(zone_, ArrayMap::Attach(zone_, type));
918 __ note_position(node->pos());
920 Local<Type> right(zone_);
921 if (node->initialization())
922 right = node->initialization()->type();
924 // There are a few methods for allocating, here:
925 // (1) If the array is fixed,
926 // (a) Initializer not present,
928 // (b) Left is const non-string:
933 // (2) If the array is not fixed,
934 // (a) Initializer is not present,
936 // (b) Initializer is not a string literal,
939 // (c) Initializer is a string literal,
944 Heap::Tenure tenure = var->scope()->kind() == Scope::GLOBAL
946 : Heap::Tenure_Default;
948 if (Expression *init = node->initialization()) {
949 if (init->isArrayLiteral()) {
950 unsigned maxsize = 0;
951 Local<Array> array(zone_, BuildArrayLiteral(zone_, init->toArrayLiteral(), map, &maxsize));
955 assert(type->isFixedLength());
957 if (type->isConst()) {
959 } else if (ArrayContainsCharBuffers(type)) {
960 // This array contains mutable char buffers, so
961 // unfortunately this gets a little more complicated. We
962 // compute the maximum size needed for the innermost
963 // string, which is similar to SP1. This means we can use
964 // CopyArray rather than individually emit opcodes to clone
966 Local<Type> child(zone_, type);
967 for (size_t i = 0; i < type->levels() - 1; i++) {
968 __ int_(child->fixedLength());
969 child = child->contained();
972 __ newarray(OP_NEWSIZED, map, tenure);
976 __ newarray(OP_NEWFIXED, map, tenure);
980 } else if (type->isFixedLength()) {
981 // Note in the case of:
982 // const String:buffer[50] = "hello";
984 // We want to preserve sizeof(buffer) == 50.
985 if (type->isConst() && !type->isCharArray()) {
988 __ newarray(OP_NEWFIXED, map, tenure);
992 } else if (!type->isConst() && init->isStringLiteral()) {
993 // This is a degenerate case of ArrayLiteral.
994 __ int_(right->fixedLength());
995 __ newarray(OP_NEWSIZED, map, tenure);
998 } else if (type->isConst()) {
1001 } else if (type->isFixedLength()) {
1002 __ newarray(OP_NEWFIXED, map, tenure);
1005 if (node->postDimensions()) {
1006 for (size_t i = 0; i < node->postDimensions()->length(); i++) {
1007 Expression *expr = node->postDimensions()->at(i);
1013 __ newarray(OP_NEWSIZED, map, tenure);
1015 __ newarray(OP_NEWEMPTY, map, tenure);
1019 } else if (type->isStruct()) {
1020 Local<StructMap> map(zone_, StructMap::cast(type->newMap()));
1022 // Because structs can contain arrays, any sort of composition
1023 // triggers non-LIFO allocation. This is just for correctness.
1024 // We could do better by:
1025 // (1) Limiting to structs that just (recursively) contain arrays,
1026 // (2) Swap Stack for Default tenure in Struct::New
1028 if (var->scope()->kind() == Scope::GLOBAL)
1029 __ newstruct(map, Heap::Tenure_Old);
1030 else if (var->needsHeapAllocation() || map->composed())
1031 __ newstruct(map, Heap::Tenure_Default);
1033 __ newstruct(map, Heap::Tenure_Stack);
1035 if (node->initialization()) {
1036 node->initialization()->accept(this);
1038 if (type->isInt32OrEnum() || type->isBool()) {
1041 assert(type->isFloat());
1047 if (var->location() == Variable::STACK) {
1049 locals_->set(zone_, var->slot(), var->type());
1051 assert(var->location() == Variable::ENVIRONMENT);
1059 BytecodeCompiler::visit(CallExpression *node)
1062 Local<Type> funType(zone_, node->callee()->type());
1064 // Sniff out natives, which have a specific opcode and are guaranteed to
1065 // be called via name proxy.
1066 NamedFunction *native = NULL;
1067 if (funType->isNative())
1068 native = node->callee()->toNameProxy()->binding()->toNamedFunction();
1070 Local<Type> given(zone_);
1071 for (size_t i = node->arguments()->length() - 1; i < node->arguments()->length(); i--) {
1072 Expression *arg = node->arguments()->at(i);
1074 given = arg->type();
1076 // We need to compute a reference if the parameter was in the form:
1078 // Note this form does not allow: f({})
1080 // We also need to compute references for all variadic native
1081 // arguments, but arrays and references are already in the
1082 // appropriate form.
1083 bool mustPushReference = false;
1084 if (i >= funType->parameters()->length()) {
1085 assert(funType->isNative() && funType->isNativeVariadic());
1086 mustPushReference = !given->isArray() && !given->isReference();
1087 } else if (funType->parameterAt(i)->isReference()) {
1088 mustPushReference = !given->isReference();
1091 // If a native is passed to a native, it must only be one level deep.
1092 assert(!funType->isNative() || !given->isArray() || given->levels() == 1);
1094 if (mustPushReference) {
1095 if (arg->isNameProxy()) {
1096 // :TODO: test with functions and globals
1097 // Compute a reference to the name.
1098 Variable *var = arg->toNameProxy()->binding()->toVariable();
1099 __ note_position(node->pos());
1101 } else if (arg->isFieldExpression()) {
1102 FieldExpression *expr = arg->toFieldExpression();
1103 expr->left()->accept(this);
1104 __ note_position(expr->pos());
1105 __ fieldref_lifo(expr->fieldIndex());
1107 // We don't know how to, or can't, build a direct reference to
1108 // this type. Make an indirect one, by taking the top of the
1109 // stack and boxing it up.
1111 __ note_position(node->pos());
1119 unsigned argc = node->arguments()->length();
1121 // If there are missing arguments, then we're not done and have to push
1122 // default parameters.
1123 Local<Box> box(zone_);
1124 Local<Array> array(zone_);
1125 Local<ArrayMap> map(zone_);
1126 for (size_t i = node->arguments()->length(); i < funType->parameters()->length(); i++) {
1127 box = Box::cast(funType->defaults()->at(i));
1129 if (box->type()->isPod()) {
1130 if (box->type()->pod() == PrimitiveType_Int32)
1131 __ int_(box->toInt32());
1132 else if (box->type()->pod() == PrimitiveType_Float)
1133 __ float_(box->toFloat());
1137 if (funType->parameterAt(i)->isReference()) {
1138 __ note_position(node->pos());
1142 assert(box->type()->isArray());
1144 array = Array::cast(box->toObject());
1145 if (funType->parameterAt(i)->isConst()) {
1148 // We need to copy the array since it's mutable. Note that
1149 // although COPYARRAY returns its left-hand side, this may
1150 // change in the future, we do the same thing and dupe the
1151 // newly allocated array.
1152 map = ArrayMap::cast(array->map());
1154 // Natives cannot escape array references, so we can allocate
1155 // them on the LIFO stack.
1156 if (funType->isNative())
1157 __ newarray(OP_NEWFIXED, map, Heap::Tenure_Stack);
1159 __ newarray(OP_NEWFIXED, map, Heap::Tenure_Default);
1170 __ note_position(node->pos());
1172 __ callnative(native->slot(), argc);
1175 node->callee()->accept(this);
1183 BytecodeCompiler::visit(TernaryExpression *node)
1185 Label success, failure, join;
1187 visitForTest(node->condition(), &success, &failure, &success);
1189 node->left()->accept(this);
1193 node->right()->accept(this);
1198 BytecodeCompiler::visit(IfStatement *node)
1201 if (!node->ifFalse()) {
1204 visitForTest(node->condition(), &success, &join, &success);
1206 node->ifTrue()->accept(this);
1208 Label success, next;
1210 visitForTest(node->condition(), &success, &next, &success);
1212 node->ifTrue()->accept(this);
1215 node->ifFalse()->accept(this);
1222 BytecodeCompiler::tableswitch(SwitchStatement *node)
1224 CaseValueList *values = node->caseValueList();
1226 if (values->length() < 3)
1229 // Find the delta between the largest and smallest value.
1230 int hi = values->at(values->length() - 1).box.toInt();
1231 int lo = values->at(0).box.toInt();
1234 unsigned tablesize = TableSwitchEntries(lo, hi);
1235 if (tablesize > MAX_TABLESWITCH_ENTRIES)
1240 // Create the list of labels that each statement will bind to.
1241 Label *labels = new Label[node->cases()->length()];
1243 // Create the table of labels we'll use for each case.
1244 Label **table = new Label *[tablesize];
1246 // Link all cases, by default, to the default label.
1247 for (size_t i = 0; i < tablesize; i++)
1250 // Now patch actual cases to their correct labels.
1251 for (size_t i = 0; i < values->length(); i++) {
1252 CaseValue &v = values->at(i);
1253 assert(v.statement < node->cases()->length());
1255 unsigned index = unsigned(v.box.toInt() - lo);
1256 assert(index < tablesize);
1258 table[index] = &labels[v.statement];
1261 // Emit the tableswitch opcode and the jump table.
1262 __ tableswitch(lo, hi, &def, table);
1264 // We're done with the jump table now.
1267 // Emit each statement.
1268 for (size_t i = 0; i < node->cases()->length(); i++) {
1269 Statement *stmt = node->cases()->at(i)->statement();
1271 __ bind(&labels[i]);
1276 // We're done with the statement labels.
1279 // Emit the default case.
1281 if (node->defaultCase())
1282 node->defaultCase()->accept(this);
1290 BytecodeCompiler::visit(SwitchStatement *node)
1292 node->expression()->accept(this);
1294 if (tableswitch(node))
1299 for (size_t i = 0; i < node->cases()->length(); i++) {
1300 Case *c = node->cases()->at(i);
1302 Label success, fail;
1304 for (size_t j = 0; j < c->others()->length(); j++) {
1305 Expression *expr = c->others()->at(j);
1309 __ j(OP_JEQ, &success);
1315 c->expression()->accept(this);
1316 __ j(OP_JNE, &fail);
1318 c->statement()->accept(this);
1323 if (node->defaultCase())
1324 node->defaultCase()->accept(this);
1331 BytecodeCompiler::visit(FunctionStatement *node)
1333 if (!node->fun()->used())
1336 if (node->fun()->isNative()) {
1337 assert(!moduleData_->natives->at(node->fun()->slot()));
1339 Local<FunctionType> type(zone_, FunctionType::cast(node->fun()->type()));
1340 Local<String> name(zone_, node->fun()->name());
1341 Local<Native> native(zone_, Native::New(zone_, type, name));
1345 moduleData_->natives->set(zone_, node->fun()->slot(), native);
1349 // If the function has no body, then it's just a declaration.
1350 if (!node->body()) {
1351 assert(node->fun()->isForward() || node->fun()->isPublic());
1355 BytecodeCompiler child(zone_, tree_, moduleData_);
1356 Local<Function> fun(zone_, child.compileFunction(moduleData_, node));
1360 assert(!moduleData_->module->getFunction(node->fun()->slot()));
1361 moduleData_->module->setFunction(zone_, node->fun()->slot(), fun);
1365 BytecodeCompiler::visit(FunctionTypeStatement *node)
1370 BytecodeCompiler::visit(EnumStatement *node)
1375 BytecodeCompiler::visit(StructureStatement *node)
1380 BytecodeCompiler::visit(ArrayLiteral *node)
1382 // We shouldn't reach these; they're handled manually when initializing
1388 BytecodeCompiler::visit(ImportStatement *node)
1393 BytecodeCompiler::compileCode(Scope *scope, unsigned lineno)
1395 // STOP doubles as RETURNVOID.
1398 if (__ oom() || zone_->hasPendingException())
1401 Local<ByteArray> bytes(zone_, ByteArray::New(zone_, __ length() * sizeof(bytecode), Heap::Tenure_Old));
1404 memcpy(bytes->raw(), __ buffer(), __ length());
1406 for (size_t i = 0; i < scope->maxContainedLocals(); i++)
1407 assert(locals_->at(i));
1409 Local<FixedArray> objects(zone_, FixedArray::New(zone_, __ objects()->length(), Heap::Tenure_Old));
1413 for (size_t i = 0; i < __ objects()->length(); i++)
1414 objects->set(zone_, i, *(__ objects()->at(i)));
1416 Local<ByteArray> safepoints(zone_);
1418 // If any stack slots hold gc pointers at potential failure points in the
1419 // bytecode, record them now. We do this by building a list of tuples;
1420 // each tuple contains the pc offset, and a bitset containing which stack
1421 // slots must be scanned by the gc.
1422 if (__ oopRecords()->length()) {
1423 size_t bytesPerSafepoint = Code::BytesPerSafepoint(__ maxStackDepth());
1424 size_t gcmapSize = bytesPerSafepoint * __ oopRecords()->length();
1425 safepoints = ByteArray::New(zone_, gcmapSize, Heap::Tenure_Old);
1429 Address cursor = safepoints->raw();
1430 for (size_t i = 0; i < __ oopRecords()->length(); i++) {
1431 OopRecord *record = __ oopRecords()->at(i);
1432 assert(record->depth <= __ maxStackDepth());
1434 *reinterpret_cast<unsigned *>(cursor) = record->offset;
1436 unsigned char *bits = reinterpret_cast<unsigned char *>(cursor + sizeof(unsigned));
1437 for (unsigned i = 0; i < record->depth; i++)
1438 bits[i / 8] |= (1 << (i % 8));
1440 cursor += bytesPerSafepoint;
1443 assert(cursor == safepoints->raw() + gcmapSize);
1446 Local<ByteArray> sourcemap(zone_);
1447 if (__ sourcemapLength()) {
1448 sourcemap = ByteArray::New(zone_, __ sourcemapLength(), Heap::Tenure_Old);
1452 memcpy(sourcemap->raw(), __ sourcemap(), __ sourcemapLength());
1455 Local<Code> code(zone_);
1457 code = Code::New(zone_,
1462 moduleData_->module,
1470 BytecodeCompiler::compileFunction(ModuleData *module, FunctionStatement *node)
1472 // Note: No need to record a life slot here, since it's part of the Frame.
1473 AutoEnterScope functionScope(this, node->scope());
1475 // Set the initial line, because line mappings are deltas.
1476 __ setFirstLine(node->pos().line);
1477 locals_ = FixedArray::New(zone_, node->scope()->maxContainedLocals(), Heap::Tenure_Old);
1479 node->body()->accept(this);
1481 unsigned nargs = node->scope()->numArguments();
1482 Local<FixedArray> args(zone_, FixedArray::New(zone_, nargs, Heap::Tenure_Old));
1486 for (size_t i = 0; i < node->scope()->numArguments(); i++)
1487 args->set(zone_, i, node->scope()->getArgument(i)->type());
1490 Local<Code> code(zone_, compileCode(node->scope(), node->pos().line));
1494 Local<FunctionType> type(zone_, FunctionType::cast(node->fun()->type()));
1495 Local<String> name(zone_, node->fun()->name());
1496 Local<Function> fun(zone_, Function::New(zone_, code, type, name, node->pos()));
1500 // If this function had a forward, export it as a named public.
1501 if (node->fun()->isPublic()) {
1502 assert(node->fun()->isPublic());
1503 ScopedRoot<Function> root(fun);
1506 if (!moduleData_->publics.append(root))
1511 Disassemble(code, stdout);
1518 BytecodeCompiler::compile()
1520 AutoEnterScope scope(this, tree_->globalScope());
1522 ModuleData moduleData;
1524 moduleData_ = &moduleData;
1525 moduleData_->module = Module::New(zone_, tree_->globalScope()->numFunctions());
1530 moduleData_->natives = FixedArray::New(zone_, tree_->globalScope()->numNatives(), Heap::Tenure_Old);
1531 if (!moduleData_->natives)
1534 for (size_t i = 0; i < tree_->statements()->length(); i++) {
1535 Statement *statement = tree_->statements()->at(i);
1536 statement->accept(this);
1539 if (zone_->hasPendingException())
1543 for (size_t i = 0; i < tree_->globalScope()->numFunctions(); i++)
1544 assert(moduleData_->module->getFunction(i));
1545 for (size_t i = 0; i < tree_->globalScope()->numNatives(); i++)
1546 assert(moduleData_->natives->at(i));
1549 if (moduleData_->publics.length()) {
1550 Local<Function> fun(zone_);
1551 Local<FixedArray> list(zone_, FixedArray::New(zone_, moduleData_->publics.length(),
1556 for (size_t i = 0; i < moduleData_->publics.length(); i++)
1557 list->set(zone_, i, moduleData_->publics[i]);
1559 moduleData_->module->setPublics(list);
1562 moduleData_->module->setNatives(moduleData_->natives);
1564 if (scope_->numEnvironmentVars()) {
1565 Local<EnvironmentMap> globalMap(zone_, scope_->createEnvironmentMap(zone_));
1569 Local<Environment> environment(zone_, Environment::New(zone_, globalMap));
1573 moduleData_->module->setEnvironment(environment);
1576 Local<Code> code(zone_, compileCode(tree_->globalScope(), 1));
1580 Disassemble(code, stdout);
1582 moduleData_->module->setCode(code);
1584 return moduleData_->module;