Implemented gcmaps and stack frame tracing.
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/.
19 #include "BytecodeCompiler.h"
29 typedef BytecodeEmitter::Label Label;
33 BytecodeCompiler::BytecodeCompiler(Zone *zone, ParseTree *tree, Module *module)
36 emitter_(zone->pool()),
44 static inline TokenKind
45 ToCompare(Expression *expr)
47 if (expr->isBinaryExpression()) {
48 BinaryExpression *b = expr->toBinaryExpression();
49 if (b->token() >= TOK_EQUALS && b->token() <= TOK_GE)
56 CompareTokenToJump(TokenKind kind)
70 assert(kind == TOK_LE);
76 TokenToOpcode(TokenKind kind)
98 assert(kind == TOK_BITXOR);
104 BytecodeCompiler::recordLifoSlot(Scope *scope)
109 if (Variable *var = scope->lifoSlot()) {
110 locals_->set(zone_, var->slot(), var->type());
111 __ savelifo(var->slot());
116 BytecodeCompiler::unwindTo(Scope *scope)
118 // Note: we only need to unwind to the outermost scope's LIFO slot.
119 Variable *var = NULL;
120 for (Scope *current = scope_; current != scope; current = current->enclosing()) {
121 if (Variable *slot = current->lifoSlot())
126 __ unwindlifo(var->slot());
130 BytecodeCompiler::visit(NameProxy *name)
132 switch (name->binding()->kind()) {
133 case BoundName::VARIABLE:
135 Variable *var = name->binding()->toVariable();
137 if (var->location() == Variable::STACK) {
139 assert(!name->type()->isReference());
141 assert(var->location() == Variable::PARAMETER);
144 // If this argument is actually a reference, dereference it now.
145 if (var->type()->isReference())
146 __ getref(var->type()->contained()->primitive());
153 NamedConstant *constant = name->binding()->toNamedConstant();
154 __ int_(constant->value().toInt());
161 BytecodeCompiler::visit(ExpressionStatement *node)
163 // Expressions leave their value on the top of the stack, so we make sure
164 // to balance the stack if they're used as a statement.
165 node->expression()->accept(this);
170 BytecodeCompiler::visit(Assignment *node)
172 // The first step is three sub-steps:
174 // (1) Bind the left-hand side.
175 // -- If a cumulative operation (+=, etc):
176 // (2) Save a copy of the binding on the stack.
177 // (3) Dereference the binding to get a value.
179 if (node->lvalue()->isNameProxy()) {
180 NameProxy *proxy = node->lvalue()->toNameProxy();
181 Variable *var = proxy->binding()->toVariable();
184 if (var->type()->isReference() || var->type()->isArray())
187 // Get the value if needed.
188 if (node->token() != TOK_ASSIGN) {
189 // += etc is not allowed on arrays.
190 assert(!var->type()->isArray());
192 if (var->type()->isReference()) {
194 __ getref(var->type()->contained()->primitive());
200 IndexExpression *index = node->lvalue()->toIndexExpression();
202 // Note: Eventually, watch out for a whole here. An expression like:
204 // (a[4] = (5, a = []))
206 // Could shrink array, so we need to either bind a[i] to a Reference,
207 // or keep the bounds check near the set. This is just a semantic
209 index->left()->accept(this);
210 index->right()->accept(this);
212 if (node->token() != TOK_ASSIGN) {
215 if (node->type()->isArray())
218 __ getarray(node->type()->primitive());
222 if (node->token() == TOK_ASSIGN) {
223 node->expression()->accept(this);
225 visitForALU(node->type(), node->expression());
227 TokenKind alu = TokenKind(int(node->token()) - (TOK_ASSIGN_ADD - TOK_PLUS));
228 __ binary(TokenToOpcode(alu));
232 if (node->expression()->type()->isArray()) {
233 // Unlike references, which can only be computed from a NamePRoxy,
234 // arrays can be computed from multiple lvalue types.
236 } else if (node->lvalue()->isNameProxy()) {
237 NameProxy *proxy = node->lvalue()->toNameProxy();
238 Variable *var = proxy->binding()->toVariable();
240 if (var->type()->isReference())
241 __ setref(var->type()->contained()->primitive());
245 IndexExpression *index = node->lvalue()->toIndexExpression();
246 // :TODO: get rid of the BOUNDS instruction, embed it in g/setarray*?
247 // We can't emit it here because the stack is slightly out of position.
249 __ setarray(index->left()->type()->contained()->primitive());
254 BytecodeCompiler::visit(IncDecExpression *node)
256 // In the postfix case, the logic looks like:
258 // (2) Dup -> REF REF
259 // (3) Fetch -> REF VAL
260 // (4) Swap -> VAL REF
261 // (5) Pick -> VAL REF VAL
262 // (6) Add -> VAL REF VAL+1
263 // (7) Store -> VAL VAL+1
266 // In the prefix case, the logic looks like:
268 // (2) Dup -> REF REF
269 // (3) Fetch -> REF VAL
272 // (6) Add -> REF VAL+1
273 // (7) Store -> VAL+1
276 // This is squirrely enough such that we don't bother sharing too much
279 // Note: We simulate a "Pick" operation with a dup2+pop.
281 // This is steps (1) to (5).
282 Expression *expr = node->expression();
283 if (expr->isNameProxy()) {
284 NameProxy *proxy = expr->toNameProxy();
285 Variable *var = proxy->binding()->toVariable();
288 if (var->type()->isReference() || var->type()->isArray())
292 if (var->type()->isReference()) {
294 __ getref(node->type()->primitive());
295 if (node->postfix()) {
300 assert(!var->type()->isArray());
306 IndexExpression *index = expr->toIndexExpression();
307 index->left()->accept(this);
308 index->right()->accept(this);
310 assert(!node->type()->isArray());
313 __ getarray(node->type()->primitive());
315 if (node->postfix()) {
316 // The stack looks like this now:
319 // So we must use a PICK operation to rotate the stack into position.
320 __ roll3(); // INDEX VALUE ARRAY
321 __ roll3(); // VALUE ARRAY INDEX
322 __ pick3(); // VALUE ARRAY INDEX VALUE
327 if (node->type()->isFloat()) {
330 assert(node->type()->isInt32());
334 if (node->token() == TOK_INCREMENT)
340 if (expr->isNameProxy()) {
341 NameProxy *proxy = expr->toNameProxy();
342 Variable *var = proxy->binding()->toVariable();
344 if (var->type()->isReference())
345 __ setref(node->type()->primitive());
349 __ setarray(node->type()->primitive());
358 BytecodeCompiler::visitForALU(Type *needed, Expression *node)
361 if (needed->isFloat() && !node->type()->isFloat())
364 assert(needed->primitive() == node->type()->primitive());
368 BytecodeCompiler::visit(BinaryExpression *node)
370 visitForALU(node->type(), node->left());
371 visitForALU(node->type(), node->right());
373 Opcode op = TokenToOpcode(node->token());
374 if (node->type()->isFloat())
375 op = (Opcode)(int(op) + (OP_ADD_F - OP_ADD));
380 BytecodeCompiler::visit(IndexExpression *node)
382 node->left()->accept(this);
383 node->right()->accept(this);
386 if (node->type()->isArray())
389 __ getarray(node->type()->primitive());
393 BytecodeCompiler::visit(ReturnStatement *node)
395 if (node->expression())
396 node->expression()->accept(this);
404 BytecodeCompiler::visitForTest(Expression *expression, Label *label, bool onTrue)
406 TokenKind token = ToCompare(expression);
407 if (token == TOK_EOF) {
408 expression->accept(this);
416 Opcode op = CompareTokenToJump(token);
420 assert(expression->isBinaryExpression());
421 BinaryExpression *binary = expression->toBinaryExpression();
422 binary->left()->accept(this);
423 binary->right()->accept(this);
428 BytecodeCompiler::visit(ForStatement *node)
430 AutoEnterScope forScope(this, node->scope());
432 recordLifoSlot(node->scope());
435 LoopScope loop(scope_, &join, &update, &loop_);
437 if (node->initialization())
438 node->initialization()->accept(this);
441 if (node->condition())
445 node->body()->accept(this);
449 node->update()->accept(this);
451 if (node->condition()) {
453 visitForTest(node->condition(), &header, true);
461 unwindTo(node->scope()->enclosing());
462 assert(__ stackDepth() == 0);
466 BytecodeCompiler::visit(WhileStatement *node)
472 LoopScope loop(scope_, &join, &header, &loop_);
474 if (node->token() == TOK_WHILE) {
475 visitForTest(node->condition(), &join, false);
476 node->body()->accept(this);
479 node->body()->accept(this);
480 visitForTest(node->condition(), &header, true);
487 BytecodeCompiler::visit(BreakStatement *node)
489 unwindTo(loop_->scope());
490 __ jump(loop_->break_());
494 BytecodeCompiler::visit(ContinueStatement *node)
496 unwindTo(loop_->scope());
497 __ jump(loop_->continue_());
501 BytecodeCompiler::visit(BlockStatement *node)
503 AutoEnterScope blockScope(this, node->scope());
505 recordLifoSlot(node->scope());
507 for (size_t i = 0; i < node->statements()->length(); i++) {
508 Statement *statement = node->statements()->at(i);
509 statement->accept(this);
510 assert(__ stackDepth() == 0);
513 // We don't bother emitting an "unwind" instruction for function scopes,
514 // since this is taken care of by the calling convention.
515 if (node->scope() && node->scope()->enclosing()->kind() != Scope::FUNCTION)
516 unwindTo(node->scope()->enclosing());
520 BytecodeCompiler::visit(IntegerLiteral *node)
522 __ int_(node->value());
526 BytecodeCompiler::visit(FloatLiteral *node)
528 __ float_((float)node->value());
531 static inline ArrayMap *
532 BuildArrayMap(Zone *zone, Handle<Type> type)
534 Local<ArrayMap> contained(zone);
535 if (type->levels() > 1) {
536 Local<Type> containedType(zone, type->contained());
537 contained = BuildArrayMap(zone, containedType);
542 return ArrayMap::New(zone, type, contained);
546 BytecodeCompiler::visit(StringLiteral *node)
548 Local<Type> type(zone_, node->type());
549 Local<ArrayMap> map(zone_, BuildArrayMap(zone_, type));
553 Local<Array> array(zone_, Array::New(zone_, map, node->string()->length(), Heap::Tenure_Old));
557 assert(array->nelements() >= node->string()->length());
558 memcpy(array->chars(), node->string()->raw(), node->string()->length() * sizeof(char));
564 BytecodeCompiler::visit(VariableDeclaration *node)
566 Variable *var = node->variable();
567 assert(var->location() == Variable::STACK);
569 Local<Type> type(zone_, var->type());
570 if (type->isArray()) {
571 Local<ArrayMap> map(zone_, BuildArrayMap(zone_, type));
572 __ newarray_lifo(map);
574 if (node->initialization()) {
575 node->initialization()->accept(this);
579 if (node->initialization()) {
580 node->initialization()->accept(this);
582 if (!node->postDimensions())
589 locals_->set(zone_, var->slot(), var->type());
593 BytecodeCompiler::visit(CallExpression *node)
595 Local<Type> funType(zone_, node->callee()->type());
597 for (size_t i = 0; i < node->arguments()->size(); i++) {
598 Expression *arg = node->arguments()->at(i);
600 Local<Type> given(zone_, arg->type());
601 Local<Type> actual(zone_, Type::cast(funType->parameters()->at(i)));
602 if (actual->isReference()) {
603 if (given->isReference()) {
604 // The input type is already a reference, so we're just passing
605 // it on to the callee.
607 } else if (arg->isNameProxy()) {
608 // :TODO: test with functions and globals
609 // Compute a reference to the name.
610 Variable *var = arg->toNameProxy()->binding()->toVariable();
612 } else if (arg->isIndexExpression()) {
613 IndexExpression *expr = arg->toIndexExpression();
614 expr->left()->accept(this);
615 expr->right()->accept(this);
619 // We don't know how to, or can't, build a direct reference to
620 // this type. Make an indirect one, by taking the top of the
621 // stack and boxing it up.
630 __ callglobal(node->callee()->toNameProxy()->binding()->toNamedFunction()->slot());
631 __ drop(node->arguments()->size());
635 BytecodeCompiler::visit(IfStatement *node)
637 if (!node->ifFalse()) {
639 visitForTest(node->condition(), &fail, false);
640 node->ifTrue()->accept(this);
644 visitForTest(node->condition(), &fail, false);
645 node->ifTrue()->accept(this);
648 node->ifFalse()->accept(this);
654 BytecodeCompiler::visit(FunctionStatement *node)
656 BytecodeCompiler child(zone_, tree_, module_);
657 Local<Function> fun(zone_, child.compileFunction(module_, node));
661 assert(!module_->getFunction(node->fun()->slot()));
662 module_->setFunction(zone_, node->fun()->slot(), fun);
666 BytecodeCompiler::visit(EnumStatement *node)
668 // :TODO: eventually, we'll export these.
672 BytecodeCompiler::compileFunction(Module *module, FunctionStatement *node)
674 // Note: No need to record a life slot here, since it's part of the Frame.
675 AutoEnterScope functionScope(this, node->scope());
677 locals_ = FixedArray::New(zone_, node->scope()->maxContainedLocals(), Heap::Tenure_Old);
679 node->body()->accept(this);
686 Local<ByteArray> bytes(zone_, ByteArray::New(zone_, __ length() * sizeof(bytecode), Heap::Tenure_Old));
689 memcpy(bytes->raw(), __ buffer(), __ length());
691 unsigned nargs = node->scope()->numArguments();
692 Local<FixedArray> args(zone_, FixedArray::New(zone_, nargs, Heap::Tenure_Old));
696 for (size_t i = 0; i < node->scope()->numArguments(); i++)
697 args->set(zone_, i, node->scope()->getArgument(i)->type());
699 for (size_t i = 0; i < node->scope()->maxContainedLocals(); i++)
700 assert(locals_->at(i));
702 Local<FixedArray> objects(zone_, FixedArray::New(zone_, __ objects()->size(), Heap::Tenure_Old));
706 for (size_t i = 0; i < __ objects()->size(); i++)
707 objects->set(zone_, i, *(__ objects()->at(i)));
709 Local<ByteArray> safepoints(zone_);
711 // If any stack slots hold gc pointers at potential failure points in the
712 // bytecode, record them now. We do this by building a list of tuples;
713 // each tuple contains the pc offset, and a bitset containing which stack
714 // slots must be scanned by the gc.
715 if (__ oopRecords()->size()) {
716 size_t bytesPerSafepoint = Code::BytesPerSafepoint(__ maxStackDepth());
717 size_t gcmapSize = bytesPerSafepoint * __ oopRecords()->size();
718 safepoints = ByteArray::New(zone_, gcmapSize, Heap::Tenure_Old);
722 Address cursor = safepoints->raw();
723 for (size_t i = 0; i < __ oopRecords()->size(); i++) {
724 OopRecord *record = __ oopRecords()->at(i);
725 assert(record->depth <= __ maxStackDepth());
727 *reinterpret_cast<unsigned *>(cursor) = record->offset;
729 unsigned char *bits = reinterpret_cast<unsigned char *>(cursor + sizeof(unsigned));
730 for (unsigned i = 0; i < record->depth; i++)
731 bits[i / 8] |= (1 << (i % 8));
733 cursor += bytesPerSafepoint;
736 assert(cursor == safepoints->raw() + gcmapSize);
739 Local<Code> code(zone_, Code::New(zone_, bytes, locals_, objects, __ maxStackDepth(), module_,
744 Local<Function> fun(zone_, Function::New(zone_, module_, code, node->fun()->type(), node->pos()));
752 BytecodeCompiler::compile()
754 module_ = Module::New(zone_, tree_->scope()->numFunctions());
758 for (size_t i = 0; i < tree_->statements()->length(); i++) {
759 Statement *statement = tree_->statements()->at(i);
760 statement->accept(this);
764 for (size_t i = 0; i < tree_->scope()->numFunctions(); i++)
765 assert(module_->getFunction(i));