jitcraft/Opcodes.cpp
author David Anderson <dvander@alliedmods.net>
Sat Jul 07 21:30:23 2012 -0700 (2012-07-07)
changeset 59 b7d61ddb3c8d
parent 54 8e22792a3921
child 68 b40b0e18a918
permissions -rw-r--r--
Rename jc:: to ke::
     1 /* vim: set ts=4 sw=4 tw=99 et:
     2  *
     3  * Copyright (C) 2012 David Anderson
     4  *
     5  * This file is part of JITCraft.
     6  *
     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)
    10  * any later version.
    11  * 
    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.
    15  *
    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/.
    18  */
    19 #include <stdlib.h>
    20 #include "Opcodes.h"
    21 #include "Utility.h"
    22 #include "Code.h"
    23 #include "Zone.h"
    24 #include "Array.h"
    25 #include "Strings.h"
    26 #include "Heap-inl.h"
    27 
    28 using namespace ke;
    29 
    30 OpInfo ke::OpcodeInfo[] =
    31 {
    32 #define OPDEF(name, number, text, length, uses, defs) \
    33     {text, length, uses, defs},
    34 #include "Opcodes.tbl"
    35 #undef OPDEF
    36 };
    37 
    38 Code *
    39 Code::New(Zone *zone, Handle<ByteArray> bytecode, Handle<FixedArray> locals,
    40           Handle<FixedArray> objects, unsigned maxStackDepth, Handle<Module> module,
    41 	  Handle<ByteArray> safepoints)
    42 {
    43     Local<Code> code(zone, Code::cast(zone->allocate(MapKind_Code, sizeof(Code), Heap::Tenure_Old)));
    44     if (!code)
    45         return NULL;
    46 
    47     code->bytecode_ = bytecode;
    48     code->locals_ = locals;
    49     code->objects_ = objects;
    50     code->maxStackDepth_ = maxStackDepth;
    51     code->module_ = module;
    52     code->safepoints_ = safepoints;
    53     return code;
    54 }
    55 
    56 static int
    57 CompareSafepoints(const void *a, const void *b)
    58 {
    59     const unsigned *sa = reinterpret_cast<const unsigned *>(a);
    60     const unsigned *sb = reinterpret_cast<const unsigned *>(b);
    61     if (*sa > *sb)
    62         return 1;
    63     if (*sa == *sb)
    64         return 0;
    65     return -1;
    66 }
    67 
    68 uint8 *
    69 Code::safepointAt(unsigned pcOffset)
    70 {
    71     // Only specific opcodes may have safepoints. Asking for a safepoint at
    72     // any other position indicates a failure to mark that position as a
    73     // safepoint, which is a bug.
    74     Opcode op = Opcode(*(start() + pcOffset));
    75     assert(op == OP_CALLGLOBAL || op == OP_NEWARRAY_LIFO || op == OP_VARREF_LIFO ||
    76            op == OP_ARGREF_LIFO || op == OP_SLOTREF_LIFO || op == OP_ARRAYREF_LIFO ||
    77            op == OP_ARRAYCOPY);
    78 
    79     if (!safepoints_)
    80         return NULL;
    81 
    82     size_t bytesPerSafepoint = BytesPerSafepoint(maxStackDepth());
    83     assert(!(safepoints_->length() % bytesPerSafepoint));
    84 
    85     size_t count = safepoints_->length() / bytesPerSafepoint;
    86 
    87     void *result = bsearch(&pcOffset,
    88                            safepoints_->raw(),
    89                            count,
    90                            bytesPerSafepoint,
    91                            CompareSafepoints);
    92 
    93     if (!result)
    94         return NULL;
    95 
    96     assert(*reinterpret_cast<unsigned *>(result) == pcOffset);
    97 
    98     return Address(result) + sizeof(unsigned);
    99 }
   100 
   101 // All jumps must be the same length.
   102 STATIC_ASSERT(OP_JL_LENGTH == OP_JUMP_LENGTH);
   103 STATIC_ASSERT(OP_JLE_LENGTH == OP_JUMP_LENGTH);
   104 STATIC_ASSERT(OP_JG_LENGTH == OP_JUMP_LENGTH);
   105 STATIC_ASSERT(OP_JGE_LENGTH == OP_JUMP_LENGTH);
   106 STATIC_ASSERT(OP_JEQ_LENGTH == OP_JUMP_LENGTH);
   107 STATIC_ASSERT(OP_JNE_LENGTH == OP_JUMP_LENGTH);
   108 STATIC_ASSERT(OP_JT_LENGTH == OP_JUMP_LENGTH);
   109 STATIC_ASSERT(OP_JF_LENGTH == OP_JUMP_LENGTH);
   110 
   111 void
   112 ke::Disassemble(Code *code, FILE *fp)
   113 {
   114     bytecode *pc = code->start();
   115     for (;;) {
   116         Opcode op = Opcode(*pc);
   117 
   118         fprintf(fp, "%-4d %s ", int(pc - code->start()), OpcodeInfo[op].name);
   119 
   120         switch (op) {
   121           case OP_NOP:
   122           case OP_RETURN:
   123           case OP_ADD:
   124           case OP_SUB:
   125           case OP_MUL:
   126           case OP_DIV:
   127           case OP_ADD_F:
   128           case OP_SUB_F:
   129           case OP_MUL_F:
   130           case OP_DIV_F:
   131           case OP_CVT_I2F:
   132           case OP_POP:
   133           case OP_GETARRAY_I:
   134           case OP_SETARRAY_I:
   135           case OP_GETARRAY_F:
   136           case OP_SETARRAY_F:
   137           case OP_GETARRAY_C:
   138           case OP_SETARRAY_C:
   139           case OP_GETARRAY_O:
   140           case OP_BOUNDS:
   141           case OP_SHL:
   142           case OP_SHR:
   143           case OP_USHR:
   144           case OP_BITAND:
   145           case OP_BITOR:
   146           case OP_BITXOR:
   147           case OP_GETREF_I:
   148           case OP_SETREF_I:
   149           case OP_GETREF_F:
   150           case OP_SETREF_F:
   151           case OP_SLOTREF_LIFO:
   152           case OP_ARRAYREF_LIFO:
   153           case OP_OBJECT:
   154           case OP_ARRAYCOPY:
   155           case OP_DUP:
   156           case OP_DUP2:
   157           case OP_SWAP:
   158           case OP_ROLL3:
   159           case OP_PICK2:
   160           case OP_PICK3:
   161             break;
   162 
   163           case OP_STOP:
   164             fprintf(fp, "\n");
   165             break;
   166 
   167           case OP_INT:
   168             fprintf(fp, "%d", READ_INT32(pc));
   169             break;
   170 
   171           case OP_FLOAT:
   172             fprintf(fp, "%f", READ_FLOAT(pc));
   173             break;
   174 
   175           case OP_JL:
   176           case OP_JLE:
   177           case OP_JG:
   178           case OP_JGE:
   179           case OP_JEQ:
   180           case OP_JNE:
   181           case OP_JT:
   182           case OP_JF:
   183           case OP_JUMP:
   184             fprintf(fp, "%u (%+d)", unsigned((pc + READ_INT32(pc)) - code->start()), READ_INT32(pc));
   185             break;
   186 
   187           case OP_NEWARRAY_LIFO:
   188           {
   189             ArrayMap *map = ArrayMap::cast(code->map(READ_UINT32(pc)));
   190             fprintf(fp, "%s:", map->type()->innermost()->tag()
   191                                ? map->type()->innermost()->tag()->chars()
   192                                : "_");
   193             for (; map; map = map->contained()) {
   194                 Type *type = map->type();
   195                 fprintf(fp, "[%d]", type->elements());
   196             }
   197             break;
   198           }
   199 
   200           case OP_GETLOCAL:
   201           case OP_SETLOCAL:
   202           case OP_GETARG:
   203           case OP_SETARG:
   204           case OP_SAVELIFO:
   205           case OP_UNWINDLIFO:
   206           case OP_CALLGLOBAL:
   207           case OP_VARREF_LIFO:
   208           case OP_ARGREF_LIFO:
   209             fprintf(fp, "%u", READ_UINT32(pc));
   210             break;
   211 
   212           default:
   213             // Unknown opcode!
   214             assert(false);
   215             return;
   216         }
   217 
   218         if (op == OP_STOP)
   219             break;
   220 
   221         fprintf(fp, "\n");
   222         pc += OpcodeInfo[op].length;
   223         assert(pc < code->start() + code->length());
   224     }
   225 
   226     fprintf(fp, "\nSafepoints:\n");
   227     ByteArray *safepoints = code->safepoints();
   228     if (safepoints) {
   229         size_t nsafepoints = safepoints->length() / Code::BytesPerSafepoint(code->maxStackDepth());
   230         for (size_t i = 0; i < nsafepoints; i++) {
   231             Address address = safepoints->raw() + Code::BytesPerSafepoint(code->maxStackDepth()) * i;
   232             fprintf(fp, "%4d: ", *reinterpret_cast<unsigned *>(address));
   233             unsigned char *bits = (unsigned char *)(address + sizeof(unsigned));
   234             for (unsigned j = 0; j < code->maxStackDepth(); j++) {
   235                 if (bits[j / 8] & (1 << (j % 8)))
   236                     fprintf(fp, "%d ", j);
   237             }
   238             fprintf(fp, "\n");
   239         }
   240     }
   241 }