Added support for declaring empty-length arrays.
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());
743 BytecodeCompiler::visit(StringLiteral *node)
745 Local<Type> type(zone_, node->type());
746 Local<ArrayMap> map(zone_, ArrayMap::Attach(zone_, type));
750 Local<Array> array(zone_,
751 Array::NewString(zone_,
753 node->string()->raw(),
754 node->string()->length(),
759 __ note_position(node->pos());
764 BytecodeCompiler::getEnvSlot(Variable *var)
766 assert(var->scope()->kind() == Scope::GLOBAL);
771 BytecodeCompiler::setEnvSlot(Variable *var)
773 assert(var->scope()->kind() == Scope::GLOBAL);
778 BytecodeCompiler::visit(VariableDeclaration *node)
780 Variable *var = node->variable();
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());
788 if (type->isFixedLength())
793 if (var->scope()->kind() == Scope::GLOBAL)
794 __ newarray(op, map, Heap::Tenure_Old);
796 __ newarray(op, map, Heap::Tenure_Default);
798 if (node->initialization()) {
799 node->initialization()->accept(this);
800 __ note_position(node->pos());
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);
810 __ newstruct(map, Heap::Tenure_Stack);
812 if (node->initialization()) {
813 node->initialization()->accept(this);
815 if (type->isInt32OrEnum() || type->isBool()) {
818 assert(type->isFloat());
824 if (var->location() == Variable::STACK) {
826 locals_->set(zone_, var->slot(), var->type());
828 assert(var->location() == Variable::ENVIRONMENT);
836 BytecodeCompiler::visit(CallExpression *node)
838 Local<Type> funType(zone_, node->callee()->type());
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();
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);
852 // We need to compute a reference if the parameter was in the form:
854 // Note this form does not allow: f({})
856 // We also need to compute references for all variadic native
857 // arguments, but arrays and references are already in the
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();
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);
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());
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());
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());
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.
893 __ note_position(node->pos());
901 unsigned argc = node->arguments()->length();
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));
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());
919 if (funType->parameterAt(i)->isReference()) {
920 __ note_position(node->pos());
924 assert(box->type()->isArray());
926 array = Array::cast(box->toObject());
927 if (funType->parameterAt(i)->isConst()) {
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());
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);
941 __ newarray(OP_NEWFIXED, map, Heap::Tenure_Default);
952 __ note_position(node->pos());
954 __ callnative(native->slot(), argc);
957 node->callee()->accept(this);
964 BytecodeCompiler::visit(TernaryExpression *node)
966 Label success, failure, join;
968 visitForTest(node->condition(), &success, &failure, &success);
970 node->left()->accept(this);
974 node->right()->accept(this);
979 BytecodeCompiler::visit(IfStatement *node)
982 if (!node->ifFalse()) {
985 visitForTest(node->condition(), &success, &join, &success);
987 node->ifTrue()->accept(this);
991 visitForTest(node->condition(), &success, &next, &success);
993 node->ifTrue()->accept(this);
996 node->ifFalse()->accept(this);
1003 BytecodeCompiler::tableswitch(SwitchStatement *node)
1005 CaseValueList *values = node->caseValueList();
1007 if (values->length() < 3)
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();
1015 unsigned tablesize = TableSwitchEntries(lo, hi);
1016 if (tablesize > MAX_TABLESWITCH_ENTRIES)
1021 // Create the list of labels that each statement will bind to.
1022 Label *labels = new Label[node->cases()->length()];
1024 // Create the table of labels we'll use for each case.
1025 Label **table = new Label *[tablesize];
1027 // Link all cases, by default, to the default label.
1028 for (size_t i = 0; i < tablesize; i++)
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());
1036 unsigned index = unsigned(v.box.toInt() - lo);
1037 assert(index < tablesize);
1039 table[index] = &labels[v.statement];
1042 // Emit the tableswitch opcode and the jump table.
1043 __ tableswitch(lo, hi, &def, table);
1045 // We're done with the jump table now.
1048 // Emit each statement.
1049 for (size_t i = 0; i < node->cases()->length(); i++) {
1050 Statement *stmt = node->cases()->at(i)->statement();
1052 __ bind(&labels[i]);
1057 // We're done with the statement labels.
1060 // Emit the default case.
1062 if (node->defaultCase())
1063 node->defaultCase()->accept(this);
1071 BytecodeCompiler::visit(SwitchStatement *node)
1073 node->expression()->accept(this);
1075 if (tableswitch(node))
1080 for (size_t i = 0; i < node->cases()->length(); i++) {
1081 Case *c = node->cases()->at(i);
1083 Label success, fail;
1085 for (size_t j = 0; j < c->others()->length(); j++) {
1086 Expression *expr = c->others()->at(j);
1090 __ j(OP_JEQ, &success);
1096 c->expression()->accept(this);
1097 __ j(OP_JNE, &fail);
1099 c->statement()->accept(this);
1104 if (node->defaultCase())
1105 node->defaultCase()->accept(this);
1112 BytecodeCompiler::visit(FunctionStatement *node)
1114 if (!node->fun()->used())
1117 if (node->fun()->isNative()) {
1118 assert(!moduleData_->natives->at(node->fun()->slot()));
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));
1126 moduleData_->natives->set(zone_, node->fun()->slot(), native);
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());
1136 BytecodeCompiler child(zone_, tree_, moduleData_);
1137 Local<Function> fun(zone_, child.compileFunction(moduleData_, node));
1141 assert(!moduleData_->module->getFunction(node->fun()->slot()));
1142 moduleData_->module->setFunction(zone_, node->fun()->slot(), fun);
1146 BytecodeCompiler::visit(FunctionTypeStatement *node)
1151 BytecodeCompiler::visit(EnumStatement *node)
1156 BytecodeCompiler::visit(StructureStatement *node)
1161 BytecodeCompiler::compileCode(Scope *scope, unsigned lineno)
1163 // STOP doubles as RETURNVOID.
1166 if (__ oom() || zone_->hasPendingException())
1169 Local<ByteArray> bytes(zone_, ByteArray::New(zone_, __ length() * sizeof(bytecode), Heap::Tenure_Old));
1172 memcpy(bytes->raw(), __ buffer(), __ length());
1174 for (size_t i = 0; i < scope->maxContainedLocals(); i++)
1175 assert(locals_->at(i));
1177 Local<FixedArray> objects(zone_, FixedArray::New(zone_, __ objects()->length(), Heap::Tenure_Old));
1181 for (size_t i = 0; i < __ objects()->length(); i++)
1182 objects->set(zone_, i, *(__ objects()->at(i)));
1184 Local<ByteArray> safepoints(zone_);
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);
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());
1202 *reinterpret_cast<unsigned *>(cursor) = record->offset;
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));
1208 cursor += bytesPerSafepoint;
1211 assert(cursor == safepoints->raw() + gcmapSize);
1214 Local<ByteArray> sourcemap(zone_);
1215 if (__ sourcemapLength()) {
1216 sourcemap = ByteArray::New(zone_, __ sourcemapLength(), Heap::Tenure_Old);
1220 memcpy(sourcemap->raw(), __ sourcemap(), __ sourcemapLength());
1223 Local<Code> code(zone_);
1225 code = Code::New(zone_,
1230 moduleData_->module,
1238 BytecodeCompiler::compileFunction(ModuleData *module, FunctionStatement *node)
1240 // Note: No need to record a life slot here, since it's part of the Frame.
1241 AutoEnterScope functionScope(this, node->scope());
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);
1247 node->body()->accept(this);
1249 unsigned nargs = node->scope()->numArguments();
1250 Local<FixedArray> args(zone_, FixedArray::New(zone_, nargs, Heap::Tenure_Old));
1254 for (size_t i = 0; i < node->scope()->numArguments(); i++)
1255 args->set(zone_, i, node->scope()->getArgument(i)->type());
1258 Local<Code> code(zone_, compileCode(node->scope(), node->pos().line));
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()));
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);
1274 if (!moduleData_->publics.append(root))
1279 Disassemble(code, stdout);
1286 BytecodeCompiler::compile()
1288 AutoEnterScope scope(this, tree_->scope());
1290 ModuleData moduleData;
1292 moduleData_ = &moduleData;
1293 moduleData_->module = Module::New(zone_, tree_->scope()->numFunctions());
1298 moduleData_->natives = FixedArray::New(zone_, tree_->scope()->numNatives(), Heap::Tenure_Old);
1299 if (!moduleData_->natives)
1302 for (size_t i = 0; i < tree_->statements()->length(); i++) {
1303 Statement *statement = tree_->statements()->at(i);
1304 statement->accept(this);
1307 if (zone_->hasPendingException())
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));
1317 if (moduleData_->publics.length()) {
1318 Local<Function> fun(zone_);
1319 Local<FixedArray> list(zone_, FixedArray::New(zone_, moduleData_->publics.length(),
1324 for (size_t i = 0; i < moduleData_->publics.length(); i++)
1325 list->set(zone_, i, moduleData_->publics[i]);
1327 moduleData_->module->setPublics(list);
1330 moduleData_->module->setNatives(moduleData_->natives);
1332 if (scope_->numEnvironmentVars()) {
1333 Local<EnvironmentMap> globalMap(zone_, scope_->createEnvironmentMap(zone_));
1337 Local<Environment> environment(zone_, Environment::New(zone_, globalMap));
1341 moduleData_->module->setEnvironment(environment);
1344 Local<Code> code(zone_, compileCode(tree_->scope(), 1));
1348 Disassemble(code, stdout);
1350 moduleData_->module->setCode(code);
1352 return moduleData_->module;