Fix bug in bytecode resizing.
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 BytecodeCompiler::visit(Assignment *node)
205 Local<Type> type(zone_, node->expression()->type());
207 // The first step is three sub-steps:
209 // (1) Bind the left-hand side.
210 // -- If a cumulative operation (+=, etc):
211 // (2) Save a copy of the binding on the stack.
212 // (3) Dereference the binding to get a value.
214 if (node->lvalue()->isNameProxy()) {
215 NameProxy *proxy = node->lvalue()->toNameProxy();
216 Variable *var = proxy->binding()->toVariable();
219 if (var->type()->isReference() ||
220 var->type()->isArray() ||
221 var->type()->isStruct())
226 // Get the value if needed.
227 if (node->token() != TOK_ASSIGN) {
228 // += etc is not allowed on arrays.
229 assert(!var->type()->isArray());
231 if (var->location() == Variable::ENVIRONMENT)
234 if (var->type()->isReference()) {
236 __ getref(var->type()->contained());
237 } else if (var->location() != Variable::ENVIRONMENT) {
241 } else if (node->lvalue()->isFieldExpression()) {
242 FieldExpression *expr = node->lvalue()->toFieldExpression();
243 __ note_position(expr->pos());
245 expr->left()->accept(this);
247 if (node->token() != TOK_ASSIGN)
250 if (node->token() != TOK_ASSIGN || (type->isStruct() || type->isArray()))
251 __ getfield(expr->fieldIndex(), expr->type());
253 IndexExpression *index = node->lvalue()->toIndexExpression();
254 __ note_position(index->pos());
256 index->left()->accept(this);
257 index->right()->accept(this);
259 if (node->token() != TOK_ASSIGN)
262 if (node->token() != TOK_ASSIGN || (type->isStruct() || type->isArray()))
263 __ getelem(index->type());
266 if (node->token() == TOK_ASSIGN) {
267 node->expression()->accept(this);
269 visitForALU(node->type(), node->expression());
271 TokenKind alu = TokenKind(int(node->token()) - (TOK_ASSIGN_ADD - TOK_PLUS));
272 __ note_position(node->pos());
273 __ binary(TokenToOpcode(alu));
277 if (type->isArray()) {
278 // Unlike references, which can only be computed from a NamePRoxy,
279 // arrays can be computed from multiple lvalue types.
280 __ note_position(node->pos());
282 } else if (type->isStruct()) {
283 // Structs have value semantics, so emit a full copy. We don't break
284 // this down into u-ops, to avoid unnecessary bytecode explosion.
285 __ note_position(node->pos());
287 } else if (node->lvalue()->isNameProxy()) {
288 NameProxy *proxy = node->lvalue()->toNameProxy();
289 Variable *var = proxy->binding()->toVariable();
291 if (var->type()->isReference())
292 __ setref(var->type()->contained());
293 else if (var->location() == Variable::ENVIRONMENT)
297 } else if (node->lvalue()->isFieldExpression()) {
298 FieldExpression *expr = node->lvalue()->toFieldExpression();
299 __ setfield(expr->fieldIndex(), expr->type());
301 IndexExpression *index = node->lvalue()->toIndexExpression();
302 __ setelem(index->type());
307 BytecodeCompiler::visit(IncDecExpression *node)
309 // In the postfix case, the logic looks like:
311 // (2) Dup -> REF REF
312 // (3) Fetch -> REF VAL
313 // (4) Swap -> VAL REF
314 // (5) Pick -> VAL REF VAL
315 // (6) Add -> VAL REF VAL+1
316 // (7) Store -> VAL VAL+1
319 // In the prefix case, the logic looks like:
321 // (2) Dup -> REF REF
322 // (3) Fetch -> REF VAL
325 // (6) Add -> REF VAL+1
326 // (7) Store -> VAL+1
329 // This is squirrely enough such that we don't bother sharing too much
332 // Note: We simulate a "Pick" operation with a dup2+pop.
334 // This is steps (1) to (5).
335 Expression *expr = node->expression();
336 if (expr->isNameProxy()) {
337 NameProxy *proxy = expr->toNameProxy();
338 Variable *var = proxy->binding()->toVariable();
341 if (var->location() == Variable::ENVIRONMENT)
343 else if (var->type()->isReference() || var->type()->isArray())
347 if (var->type()->isReference()) {
349 __ getref(node->type());
350 if (node->postfix()) {
355 assert(!var->type()->isArray());
356 if (var->location() != Variable::ENVIRONMENT)
361 } else if (expr->isFieldExpression()) {
362 FieldExpression *field = expr->toFieldExpression();
364 field->left()->accept(this);
366 __ getfield(field->fieldIndex(), field->type());
368 if (node->postfix()) {
369 // The stack looks like this now:
371 __ swap(); // VALUE OBJECT
372 __ pick2(); // VALUE OBJECT VALUE
375 IndexExpression *index = expr->toIndexExpression();
376 __ note_position(index->pos());
378 index->left()->accept(this);
379 index->right()->accept(this);
381 assert(!node->type()->isArray());
383 __ getelem(node->type());
385 if (node->postfix()) {
386 // The stack looks like this now:
389 // So we must use a PICK operation to rotate the stack into position.
390 __ roll3(); // INDEX VALUE ARRAY
391 __ roll3(); // VALUE ARRAY INDEX
392 __ pick3(); // VALUE ARRAY INDEX VALUE
397 if (node->type()->isFloat()) {
400 assert(node->type()->isInt32());
404 __ note_position(node->pos());
405 if (node->token() == TOK_INCREMENT)
411 if (expr->isNameProxy()) {
412 NameProxy *proxy = expr->toNameProxy();
413 Variable *var = proxy->binding()->toVariable();
415 if (var->type()->isReference())
416 __ setref(node->type());
417 else if (var->location() == Variable::ENVIRONMENT)
421 } else if (expr->isFieldExpression()) {
422 FieldExpression *field = expr->toFieldExpression();
423 __ setfield(field->fieldIndex(), field->type());
425 assert(expr->isIndexExpression());
426 __ setelem(node->type());
435 BytecodeCompiler::visitForALU(Type *needed, Expression *node)
438 if (needed->isFloat() && !node->type()->isFloat())
441 assert(needed->primitive() == node->type()->primitive());
445 GetCoercionType(TokenKind tok, Type *left, Type *right)
453 BytecodeCompiler::visit(UnaryExpression *node)
455 Local<Type> out(zone_, ((Expression *)node)->type());
457 switch (node->token()) {
460 Local<Type> type(zone_, node->expression()->type());
461 node->expression()->accept(this);
472 Local<Type> type(zone_, node->expression()->type());
473 node->expression()->accept(this);
484 Local<Type> from(zone_, node->expression()->type());
486 node->expression()->accept(this);
487 if (!from->isFloat() && out->isFloat())
489 else if (from->isFloat() && !out->isFloat())
495 assert(node->token() == TOK_TILDE);
496 node->expression()->accept(this);
503 BytecodeCompiler::visit(BinaryExpression *node)
505 if (node->token() == TOK_AND || node->token() == TOK_OR) {
506 Label success, failure, done;
507 visitForTest(node, &success, &failure, &success);
510 __ drop(1); // Otherwise, the stack depth will be +1 too much.
518 Local<Type> leftType(zone_, node->left()->type());
519 Local<Type> rightType(zone_, node->right()->type());
520 Local<Type> coerce(zone_, GetCoercionType(node->token(), leftType, rightType));
522 visitForALU(coerce, node->left());
523 visitForALU(coerce, node->right());
525 Opcode op = TokenToOpcode(node->token());
526 if (node->type()->isFloat())
527 op = (Opcode)(int(op) + (OP_ADD_F - OP_ADD));
529 __ note_position(node->pos());
534 BytecodeCompiler::visit(IndexExpression *node)
536 node->left()->accept(this);
537 node->right()->accept(this);
538 __ note_position(node->pos());
539 __ getelem(node->type());
543 BytecodeCompiler::visit(FieldExpression *node)
545 node->left()->accept(this);
546 __ getfield(node->fieldIndex(), node->type());
550 BytecodeCompiler::visit(ReturnStatement *node)
552 if (node->expression()) {
553 node->expression()->accept(this);
561 BytecodeCompiler::visitForTest(Expression *expression,
566 TokenKind token = ToCompare(expression);
567 if (token == TOK_EOF || token == TOK_NOT) {
568 if (token == TOK_EOF)
569 expression->accept(this);
571 expression->toUnaryExpression()->expression()->accept(this);
573 bool jumpOnTrue = (fallthrough == falseBranch) ^ (token == TOK_NOT);
575 Opcode op = jumpOnTrue ? OP_JT : OP_JF;
576 if (expression->type()->isFloat())
577 op = (Opcode)(int(op) + (OP_JL_F - OP_JL));
579 if (fallthrough == falseBranch)
580 __ j(op, trueBranch);
582 __ j(op, falseBranch);
586 BinaryExpression *binary = expression->toBinaryExpression();
588 if (token == TOK_AND || token == TOK_OR) {
590 if (token == TOK_AND)
591 visitForTest(binary->left(), &next, falseBranch, &next);
593 visitForTest(binary->left(), trueBranch, &next, &next);
595 visitForTest(binary->right(), trueBranch, falseBranch, fallthrough);
599 Opcode op = CompareTokenToJump(token);
600 if (fallthrough == trueBranch)
603 Local<Type> leftType(zone_, binary->left()->type());
604 Local<Type> rightType(zone_, binary->right()->type());
605 Local<Type> coerce(zone_, GetCoercionType(binary->token(), leftType, rightType));
607 visitForALU(coerce, binary->left());
608 visitForALU(coerce, binary->right());
609 if (coerce->isFloat())
610 op = (Opcode)(int(op) + (OP_JL_F - OP_JL));
612 if (fallthrough == trueBranch)
613 __ j(op, falseBranch);
615 __ j(op, trueBranch);
619 BytecodeCompiler::visit(ForStatement *node)
621 AutoEnterScope forScope(this, node->scope());
623 recordLifoSlot(node->scope());
626 LoopScope loop(scope_, &join, &update, &loop_);
628 if (node->initialization())
629 node->initialization()->accept(this);
632 if (node->condition())
636 node->body()->accept(this);
640 node->update()->accept(this);
642 if (node->condition()) {
644 visitForTest(node->condition(), &header, &join, &join);
652 unwindTo(node->scope()->enclosing());
653 assert(__ stackDepth() == 0);
657 BytecodeCompiler::visit(WhileStatement *node)
663 LoopScope loop(scope_, &join, &header, &loop_);
665 if (node->token() == TOK_WHILE) {
668 visitForTest(node->condition(), &body, &join, &body);
670 node->body()->accept(this);
673 node->body()->accept(this);
674 visitForTest(node->condition(), &header, &join, &join);
681 BytecodeCompiler::visit(BreakStatement *node)
683 unwindTo(loop_->scope());
684 __ jump(loop_->break_());
688 BytecodeCompiler::visit(ContinueStatement *node)
690 unwindTo(loop_->scope());
691 __ jump(loop_->continue_());
695 BytecodeCompiler::visit(BlockStatement *node)
697 AutoEnterScope blockScope(this, node->scope());
699 recordLifoSlot(node->scope());
701 for (size_t i = 0; i < node->statements()->length(); i++) {
702 Statement *statement = node->statements()->at(i);
703 statement->accept(this);
704 assert(__ stackDepth() == 0);
707 // We don't bother emitting an "unwind" instruction for function scopes,
708 // since this is taken care of by the calling convention.
709 if (node->scope() && node->scope()->enclosing()->kind() != Scope::FUNCTION)
710 unwindTo(node->scope()->enclosing());
714 BytecodeCompiler::visit(IntegerLiteral *node)
716 __ int_(node->value());
720 BytecodeCompiler::visit(BooleanLiteral *node)
722 if (node->token() == TOK_TRUE)
729 BytecodeCompiler::visit(FloatLiteral *node)
731 __ float_((float)node->value());
735 BytecodeCompiler::visit(StringLiteral *node)
737 Local<Type> type(zone_, node->type());
738 Local<ArrayMap> map(zone_, ArrayMap::Attach(zone_, type));
742 Local<Array> array(zone_,
743 Array::NewString(zone_,
745 node->string()->raw(),
746 node->string()->length(),
751 __ note_position(node->pos());
756 BytecodeCompiler::getEnvSlot(Variable *var)
758 assert(var->scope()->kind() == Scope::GLOBAL);
763 BytecodeCompiler::setEnvSlot(Variable *var)
765 assert(var->scope()->kind() == Scope::GLOBAL);
770 BytecodeCompiler::visit(VariableDeclaration *node)
772 Variable *var = node->variable();
774 Local<Type> type(zone_, var->type());
775 if (type->isArray()) {
776 Local<ArrayMap> map(zone_, ArrayMap::Attach(zone_, type));
777 __ note_position(node->pos());
778 if (var->scope()->kind() == Scope::GLOBAL)
779 __ newarray(map, Heap::Tenure_Old);
780 else if (var->needsHeapAllocation())
781 __ newarray(map, Heap::Tenure_Default);
783 __ newarray(map, Heap::Tenure_Stack);
785 if (node->initialization()) {
786 node->initialization()->accept(this);
787 __ note_position(node->pos());
790 } else if (type->isStruct()) {
791 Local<Map> map(zone_, type->newMap());
792 if (var->scope()->kind() == Scope::GLOBAL)
793 __ newstruct(map, Heap::Tenure_Old);
794 else if (var->needsHeapAllocation())
795 __ newstruct(map, Heap::Tenure_Default);
797 __ newstruct(map, Heap::Tenure_Stack);
799 if (node->initialization()) {
800 node->initialization()->accept(this);
802 if (type->isInt32OrEnum() || type->isBool()) {
805 assert(type->isFloat());
811 if (var->location() == Variable::STACK) {
813 locals_->set(zone_, var->slot(), var->type());
815 assert(var->location() == Variable::ENVIRONMENT);
823 BytecodeCompiler::visit(CallExpression *node)
825 Local<Type> funType(zone_, node->callee()->type());
827 // Sniff out natives, which have a specific opcode and are guaranteed to
828 // be called via name proxy.
829 NamedFunction *native = NULL;
830 if (funType->isNative()) {
831 native = node->callee()->toNameProxy()->binding()->toNamedFunction();
834 Local<Type> given(zone_);
835 for (size_t i = node->arguments()->length() - 1; i < node->arguments()->length(); i--) {
836 Expression *arg = node->arguments()->at(i);
840 // We need to compute a reference if the parameter was in the form:
842 // Note this form does not allow: f({})
844 // We also need to compute references for all variadic native
845 // arguments, but arrays and references are already in the
847 bool mustPushReference = false;
848 if (i >= funType->parameters()->length()) {
849 assert(funType->isNative() && funType->isNativeVariadic());
850 mustPushReference = !given->isArray() && !given->isReference();
851 } else if (funType->parameterAt(i)->isReference()) {
852 mustPushReference = !given->isReference();
855 // If a native is passed to a native, it must only be one level deep.
856 assert(!funType->isNative() || !given->isArray() || given->levels() == 1);
858 if (mustPushReference) {
859 if (arg->isNameProxy()) {
860 // :TODO: test with functions and globals
861 // Compute a reference to the name.
862 Variable *var = arg->toNameProxy()->binding()->toVariable();
863 __ note_position(node->pos());
865 } else if (arg->isIndexExpression()) {
866 IndexExpression *expr = arg->toIndexExpression();
867 expr->left()->accept(this);
868 expr->right()->accept(this);
869 __ note_position(expr->pos());
871 } else if (arg->isFieldExpression()) {
872 FieldExpression *expr = arg->toFieldExpression();
873 expr->left()->accept(this);
874 __ note_position(expr->pos());
875 __ fieldref_lifo(expr->fieldIndex());
877 // We don't know how to, or can't, build a direct reference to
878 // this type. Make an indirect one, by taking the top of the
879 // stack and boxing it up.
881 __ note_position(node->pos());
889 unsigned argc = node->arguments()->length();
891 // If there are missing arguments, then we're not done and have to push
892 // default parameters.
893 Local<Box> box(zone_);
894 Local<Array> array(zone_);
895 Local<ArrayMap> map(zone_);
896 for (size_t i = node->arguments()->length(); i < funType->parameters()->length(); i++) {
897 box = Box::cast(funType->defaults()->at(i));
899 if (box->type()->isPod()) {
900 if (box->type()->pod() == PrimitiveType_Int32)
901 __ int_(box->toInt32());
902 else if (box->type()->pod() == PrimitiveType_Float)
903 __ float_(box->toFloat());
907 if (funType->parameterAt(i)->isReference()) {
908 __ note_position(node->pos());
912 assert(box->type()->isArray());
914 array = Array::cast(box->toObject());
915 if (funType->parameterAt(i)->isConst()) {
918 // We need to copy the array since it's mutable. Note that
919 // although COPYARRAY returns its left-hand side, this may
920 // change in the future, we do the same thing and dupe the
921 // newly allocated array.
922 map = ArrayMap::cast(array->map());
923 __ newarray(map, Heap::Tenure_Stack);
934 __ note_position(node->pos());
936 __ callnative(native->slot(), argc);
939 node->callee()->accept(this);
946 BytecodeCompiler::visit(TernaryExpression *node)
948 Label success, failure, join;
950 visitForTest(node->condition(), &success, &failure, &success);
952 node->left()->accept(this);
956 node->right()->accept(this);
961 BytecodeCompiler::visit(IfStatement *node)
964 if (!node->ifFalse()) {
967 visitForTest(node->condition(), &success, &join, &success);
969 node->ifTrue()->accept(this);
973 visitForTest(node->condition(), &success, &next, &success);
975 node->ifTrue()->accept(this);
978 node->ifFalse()->accept(this);
985 BytecodeCompiler::tableswitch(SwitchStatement *node)
987 CaseValueList *values = node->caseValueList();
989 if (values->length() < 3)
992 // Find the delta between the largest and smallest value.
993 int hi = values->at(values->length() - 1).box.toInt();
994 int lo = values->at(0).box.toInt();
997 unsigned tablesize = TableSwitchEntries(lo, hi);
998 if (tablesize > MAX_TABLESWITCH_ENTRIES)
1003 // Create the list of labels that each statement will bind to.
1004 Label *labels = new Label[node->cases()->length()];
1006 // Create the table of labels we'll use for each case.
1007 Label **table = new Label *[tablesize];
1009 // Link all cases, by default, to the default label.
1010 for (size_t i = 0; i < tablesize; i++)
1013 // Now patch actual cases to their correct labels.
1014 for (size_t i = 0; i < values->length(); i++) {
1015 CaseValue &v = values->at(i);
1016 assert(v.statement < node->cases()->length());
1018 unsigned index = unsigned(v.box.toInt() - lo);
1019 assert(index < tablesize);
1021 table[index] = &labels[v.statement];
1024 // Emit the tableswitch opcode and the jump table.
1025 __ tableswitch(lo, hi, &def, table);
1027 // We're done with the jump table now.
1030 // Emit each statement.
1031 for (size_t i = 0; i < node->cases()->length(); i++) {
1032 Statement *stmt = node->cases()->at(i)->statement();
1034 __ bind(&labels[i]);
1039 // We're done with the statement labels.
1042 // Emit the default case.
1044 if (node->defaultCase())
1045 node->defaultCase()->accept(this);
1053 BytecodeCompiler::visit(SwitchStatement *node)
1055 node->expression()->accept(this);
1057 if (tableswitch(node))
1062 for (size_t i = 0; i < node->cases()->length(); i++) {
1063 Case *c = node->cases()->at(i);
1065 Label success, fail;
1067 for (size_t j = 0; j < c->others()->length(); j++) {
1068 Expression *expr = c->others()->at(j);
1072 __ j(OP_JEQ, &success);
1078 c->expression()->accept(this);
1079 __ j(OP_JNE, &fail);
1081 c->statement()->accept(this);
1086 if (node->defaultCase())
1087 node->defaultCase()->accept(this);
1094 BytecodeCompiler::visit(FunctionStatement *node)
1096 if (!node->fun()->used())
1099 if (node->fun()->isNative()) {
1100 assert(!moduleData_->natives->at(node->fun()->slot()));
1102 Local<Type> type(zone_, node->fun()->type());
1103 Local<String> name(zone_, node->fun()->name());
1104 Local<Native> native(zone_, Native::New(zone_, type, name));
1108 moduleData_->natives->set(zone_, node->fun()->slot(), native);
1112 // If the function has no body, then it's just a declaration.
1113 if (!node->body()) {
1114 assert(node->fun()->isForward() || node->fun()->isPublic());
1118 BytecodeCompiler child(zone_, tree_, moduleData_);
1119 Local<Function> fun(zone_, child.compileFunction(moduleData_, node));
1123 assert(!moduleData_->module->getFunction(node->fun()->slot()));
1124 moduleData_->module->setFunction(zone_, node->fun()->slot(), fun);
1128 BytecodeCompiler::visit(FunctionTypeStatement *node)
1133 BytecodeCompiler::visit(EnumStatement *node)
1138 BytecodeCompiler::visit(StructureStatement *node)
1143 BytecodeCompiler::compileCode(Scope *scope, unsigned lineno)
1145 // STOP doubles as RETURNVOID.
1148 if (__ oom() || zone_->hasPendingException())
1151 Local<ByteArray> bytes(zone_, ByteArray::New(zone_, __ length() * sizeof(bytecode), Heap::Tenure_Old));
1154 memcpy(bytes->raw(), __ buffer(), __ length());
1156 for (size_t i = 0; i < scope->maxContainedLocals(); i++)
1157 assert(locals_->at(i));
1159 Local<FixedArray> objects(zone_, FixedArray::New(zone_, __ objects()->length(), Heap::Tenure_Old));
1163 for (size_t i = 0; i < __ objects()->length(); i++)
1164 objects->set(zone_, i, *(__ objects()->at(i)));
1166 Local<ByteArray> safepoints(zone_);
1168 // If any stack slots hold gc pointers at potential failure points in the
1169 // bytecode, record them now. We do this by building a list of tuples;
1170 // each tuple contains the pc offset, and a bitset containing which stack
1171 // slots must be scanned by the gc.
1172 if (__ oopRecords()->length()) {
1173 size_t bytesPerSafepoint = Code::BytesPerSafepoint(__ maxStackDepth());
1174 size_t gcmapSize = bytesPerSafepoint * __ oopRecords()->length();
1175 safepoints = ByteArray::New(zone_, gcmapSize, Heap::Tenure_Old);
1179 Address cursor = safepoints->raw();
1180 for (size_t i = 0; i < __ oopRecords()->length(); i++) {
1181 OopRecord *record = __ oopRecords()->at(i);
1182 assert(record->depth <= __ maxStackDepth());
1184 *reinterpret_cast<unsigned *>(cursor) = record->offset;
1186 unsigned char *bits = reinterpret_cast<unsigned char *>(cursor + sizeof(unsigned));
1187 for (unsigned i = 0; i < record->depth; i++)
1188 bits[i / 8] |= (1 << (i % 8));
1190 cursor += bytesPerSafepoint;
1193 assert(cursor == safepoints->raw() + gcmapSize);
1196 Local<ByteArray> sourcemap(zone_);
1197 if (__ sourcemapLength()) {
1198 sourcemap = ByteArray::New(zone_, __ sourcemapLength(), Heap::Tenure_Old);
1202 memcpy(sourcemap->raw(), __ sourcemap(), __ sourcemapLength());
1205 Local<Code> code(zone_);
1207 code = Code::New(zone_,
1212 moduleData_->module,
1220 BytecodeCompiler::compileFunction(ModuleData *module, FunctionStatement *node)
1222 // Note: No need to record a life slot here, since it's part of the Frame.
1223 AutoEnterScope functionScope(this, node->scope());
1225 // Set the initial line, because line mappings are deltas.
1226 __ setFirstLine(node->pos().line);
1227 locals_ = FixedArray::New(zone_, node->scope()->maxContainedLocals(), Heap::Tenure_Old);
1229 node->body()->accept(this);
1231 unsigned nargs = node->scope()->numArguments();
1232 Local<FixedArray> args(zone_, FixedArray::New(zone_, nargs, Heap::Tenure_Old));
1236 for (size_t i = 0; i < node->scope()->numArguments(); i++)
1237 args->set(zone_, i, node->scope()->getArgument(i)->type());
1240 Local<Code> code(zone_, compileCode(node->scope(), node->pos().line));
1244 Local<Type> type(zone_, node->fun()->type());
1245 Local<String> name(zone_, node->fun()->name());
1246 Local<Function> fun(zone_, Function::New(zone_, code, type, name, node->pos()));
1250 // If this function had a forward, export it as a named public.
1251 if (node->fun()->isPublic()) {
1252 assert(node->fun()->isPublic());
1253 ScopedRoot<Function> root(fun);
1256 if (!moduleData_->publics.append(root))
1261 Disassemble(code, stdout);
1268 BytecodeCompiler::compile()
1270 AutoEnterScope scope(this, tree_->scope());
1272 ModuleData moduleData;
1274 moduleData_ = &moduleData;
1275 moduleData_->module = Module::New(zone_, tree_->scope()->numFunctions());
1280 moduleData_->natives = FixedArray::New(zone_, tree_->scope()->numNatives(), Heap::Tenure_Old);
1281 if (!moduleData_->natives)
1284 for (size_t i = 0; i < tree_->statements()->length(); i++) {
1285 Statement *statement = tree_->statements()->at(i);
1286 statement->accept(this);
1289 if (zone_->hasPendingException())
1293 for (size_t i = 0; i < tree_->scope()->numFunctions(); i++)
1294 assert(moduleData_->module->getFunction(i));
1295 for (size_t i = 0; i < tree_->scope()->numNatives(); i++)
1296 assert(moduleData_->natives->at(i));
1299 if (moduleData_->publics.length()) {
1300 Local<Function> fun(zone_);
1301 Local<FixedArray> list(zone_, FixedArray::New(zone_, moduleData_->publics.length(),
1306 for (size_t i = 0; i < moduleData_->publics.length(); i++)
1307 list->set(zone_, i, moduleData_->publics[i]);
1309 moduleData_->module->setPublics(list);
1312 moduleData_->module->setNatives(moduleData_->natives);
1314 if (scope_->numEnvironmentVars()) {
1315 Local<EnvironmentMap> globalMap(zone_, scope_->createEnvironmentMap(zone_));
1319 Local<Environment> environment(zone_, Environment::New(zone_, globalMap));
1323 moduleData_->module->setEnvironment(environment);
1326 Local<Code> code(zone_, compileCode(tree_->scope(), 1));
1330 Disassemble(code, stdout);
1332 moduleData_->module->setCode(code);
1334 return moduleData_->module;