src/Opcodes.cpp
author David Anderson <dvander@alliedmods.net>
Sun Jan 06 13:52:21 2013 -0800 (2013-01-06)
changeset 256 3c184218462d
parent 247 7721042bdb67
child 263 ba85a47ee414
permissions -rw-r--r--
Initial implementation of module imports.
     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 "CompactBuffer.h"
    27 #include "Structures.h"
    28 #include "Modules.h"
    29 #include "Heap-inl.h"
    30 
    31 using namespace ke;
    32 
    33 OpInfo ke::OpcodeInfo[] =
    34 {
    35 #define OPDEF(name, text, length, uses, defs) \
    36     {text, length, uses, defs},
    37 #include "Opcodes.tbl"
    38 #undef OPDEF
    39 };
    40 
    41 Code *
    42 Code::New(Zone *zone, Handle<ByteArray> bytecode, Handle<FixedArray> locals,
    43           Handle<FixedArray> objects, Handle<FixedArray> strings, unsigned maxStackDepth,
    44           unsigned maxLoopDepth, Handle<ByteArray> safepoints, Handle<ByteArray> sourcemap)
    45 {
    46     Local<Code> code(zone, Code::cast(zone->allocate(MapKind_Code, sizeof(Code), Heap::Tenure_Old)));
    47     if (!code)
    48         return NULL;
    49 
    50     code->bytecode_ = bytecode;
    51     code->locals_ = locals;
    52     code->objects_ = objects;
    53     code->maxStackDepth_ = maxStackDepth;
    54     code->module_ = NULL;
    55     code->safepoints_ = safepoints;
    56     code->sourcemap_ = sourcemap;
    57     code->lineNumber_ = 0;
    58     code->strings_ = strings;
    59     code->maxLoopDepth_ = maxLoopDepth;
    60     return code;
    61 }
    62 
    63 static int
    64 CompareSafepoints(const void *a, const void *b)
    65 {
    66     const unsigned *sa = reinterpret_cast<const unsigned *>(a);
    67     const unsigned *sb = reinterpret_cast<const unsigned *>(b);
    68     if (*sa > *sb)
    69         return 1;
    70     if (*sa == *sb)
    71         return 0;
    72     return -1;
    73 }
    74 
    75 uint8 *
    76 Code::safepointAt(unsigned pcOffset)
    77 {
    78     // Only specific opcodes may have safepoints. Asking for a safepoint at
    79     // any other position indicates a failure to mark that position as a
    80     // safepoint, which is a bug.
    81 #ifndef NDEBUG
    82     Opcode op = Opcode(*(start() + pcOffset));
    83     assert(op == OP_CALL ||
    84            op == OP_NEWFIXED ||
    85            op == OP_NEWEMPTY ||
    86            op == OP_NEWSIZED ||
    87            op == OP_VARREF_LIFO ||
    88            op == OP_ARGREF_LIFO ||
    89            op == OP_SLOTREF_LIFO ||
    90            op == OP_COPYARRAY ||
    91            op == OP_CALLNATIVE ||
    92            op == OP_PUBLIC);
    93 #endif
    94 
    95     if (!safepoints_)
    96         return NULL;
    97 
    98     size_t bytesPerSafepoint = BytesPerSafepoint(maxStackDepth());
    99     assert(!(safepoints_->length() % bytesPerSafepoint));
   100 
   101     size_t count = safepoints_->length() / bytesPerSafepoint;
   102 
   103     void *result = bsearch(&pcOffset,
   104                            safepoints_->raw(),
   105                            count,
   106                            bytesPerSafepoint,
   107                            CompareSafepoints);
   108 
   109     if (!result)
   110         return NULL;
   111 
   112     assert(*reinterpret_cast<unsigned *>(result) == pcOffset);
   113 
   114     return Address(result) + sizeof(unsigned);
   115 }
   116 
   117 SourcePosition
   118 Code::pcToSource(unsigned pc)
   119 {
   120     assert(pc < bytecode_->length());
   121 
   122     CompactBufferReader reader(sourcemap_->raw(), sourcemap_->raw() + sourcemap_->length());
   123 
   124     unsigned line = 1;
   125     unsigned col = 0;
   126     unsigned curPc = 0;
   127     while (!reader.done()) {
   128         curPc += reader.readUint32();
   129         if (curPc > pc)
   130             break;
   131 
   132         line = reader.readUint32();
   133         col = reader.readUint32();
   134     }
   135 
   136     return SourcePosition(lineNumber_ + line, col);
   137 }
   138 
   139 // All jumps must be the same length.
   140 STATIC_ASSERT(OP_JT_LENGTH == OP_JUMP_LENGTH);
   141 STATIC_ASSERT(OP_JF_LENGTH == OP_JUMP_LENGTH);
   142 
   143 void
   144 ke::Disassemble(Code *code, FILE *fp)
   145 {
   146     bytecode *pc = code->start();
   147     for (;;) {
   148         Opcode op = Opcode(*pc);
   149 
   150         fprintf(fp, "%-4d %s ", int(pc - code->start()), OpcodeInfo[op].name);
   151 
   152         switch (op) {
   153           case OP_NOP:
   154           case OP_RETURN:
   155           case OP_RETURNVOID:
   156           case OP_ADD:
   157           case OP_SUB:
   158           case OP_MUL:
   159           case OP_DIV:
   160           case OP_ADD_F:
   161           case OP_SUB_F:
   162           case OP_MUL_F:
   163           case OP_DIV_F:
   164           case OP_CVT_I2F:
   165           case OP_CVT_I2B:
   166           case OP_POP:
   167           case OP_GETELEM:
   168           case OP_SETELEM:
   169           case OP_SHL:
   170           case OP_SHR:
   171           case OP_USHR:
   172           case OP_BITAND:
   173           case OP_BITOR:
   174           case OP_BITXOR:
   175           case OP_GETREF_I:
   176           case OP_SETREF_I:
   177           case OP_GETREF_F:
   178           case OP_SETREF_F:
   179           case OP_SLOTREF_LIFO:
   180           case OP_COPYARRAY:
   181           case OP_COPYSTRUCT:
   182           case OP_DUP:
   183           case OP_DUP2:
   184           case OP_SWAP:
   185           case OP_ROLL3:
   186           case OP_PICK2:
   187           case OP_PICK3:
   188           case OP_CALL:
   189           case OP_LT:
   190           case OP_LE:
   191           case OP_GE:
   192           case OP_GT:
   193           case OP_EQ:
   194           case OP_NE:
   195           case OP_LT_F:
   196           case OP_LE_F:
   197           case OP_GE_F:
   198           case OP_GT_F:
   199           case OP_EQ_F:
   200           case OP_NE_F:
   201           case OP_BITNOT:
   202           case OP_NOT:
   203           case OP_NOT_F:
   204           case OP_NEG:
   205           case OP_NEG_F:
   206           case OP_MOD:
   207           case OP_BITCAST:
   208           case OP_TRUE:
   209           case OP_FALSE:
   210           case OP_SIZEOF:
   211           case OP_PUBLIC:
   212           case OP_LEAVELOOP:
   213           case OP_DUPARRAY:
   214           case OP_DEPARRAY:
   215             break;
   216 
   217           case OP_ENTERLOOP:
   218             if (pc[1])
   219               fprintf(fp, "; lifo region");
   220             break;
   221 
   222           case OP_STOP:
   223             fprintf(fp, "\n");
   224             break;
   225 
   226           case OP_INT:
   227             fprintf(fp, "%d", READ_INT32(pc));
   228             break;
   229 
   230           case OP_FLOAT:
   231             fprintf(fp, "%f", READ_FLOAT(pc));
   232             break;
   233 
   234           case OP_JT:
   235           case OP_JF:
   236           case OP_JUMP:
   237           case OP_CONTINUE:
   238           case OP_BREAK:
   239             fprintf(fp, "%u (%+d)", unsigned((pc + READ_INT32(pc)) - code->start()), READ_INT32(pc));
   240             break;
   241 
   242           case OP_NEWFIXED:
   243           case OP_NEWEMPTY:
   244           case OP_NEWSIZED:
   245           {
   246             Heap::Tenure tenure = (Heap::Tenure)pc[1];
   247             //ArrayMap *map = ArrayMap::cast(code->map(READ_UINT32(pc + 1)));
   248             if (tenure == Heap::Tenure_Stack)
   249                 fprintf(fp, " ; lifo");
   250             else if (tenure == Heap::Tenure_Old)
   251                 fprintf(fp, " ; pretenured");
   252             else if (tenure == Heap::Tenure_Default)
   253                 fprintf(fp, " ; newborn");
   254             break;
   255           }
   256 
   257           case OP_NEWSTRUCT:
   258           {
   259             Heap::Tenure tenure = (Heap::Tenure)pc[1];
   260             StructMap *map = StructMap::cast(code->map(READ_UINT32(pc + 1)));
   261             fprintf(fp, "%s", StructType::cast(map->type())->name()->chars());
   262             if (tenure == Heap::Tenure_Stack)
   263                 fprintf(fp, " ; lifo");
   264             else if (tenure == Heap::Tenure_Old)
   265                 fprintf(fp, " ; pretenured");
   266             else if (tenure == Heap::Tenure_Default)
   267                 fprintf(fp, " ; newborn");
   268             break;
   269           }
   270 
   271           case OP_GETLOCAL:
   272           case OP_SETLOCAL:
   273           case OP_GETARG:
   274           case OP_SETARG:
   275           case OP_SAVELIFO:
   276           case OP_UNWINDLIFO:
   277           case OP_VARREF_LIFO:
   278           case OP_ARGREF_LIFO:
   279           case OP_OBJECT:
   280           case OP_GETFIELD:
   281           case OP_SETFIELD:
   282             fprintf(fp, "%u", READ_UINT32(pc));
   283             break;
   284 
   285           case OP_CALLNATIVE:
   286           {
   287             unsigned argc = READ_UINT32(pc);
   288             fprintf(fp, " ; %u args", argc);
   289             break;
   290           }
   291 
   292           case OP_TABLESWITCH:
   293           {
   294             int low = READ_TABLESWITCH_LOW(pc);
   295             int high = READ_TABLESWITCH_HIGH(pc);
   296             fprintf(fp, "%d, %d\n", low, high);
   297             break;
   298           }
   299 
   300           case OP_GETGLOBAL:
   301           case OP_SETGLOBAL:
   302           {
   303             unsigned index = READ_UINT32(pc);
   304             fprintf(fp, "%s", String::cast(code->strings()->at(index))->chars());
   305             break;
   306           }
   307 
   308           case OP_IMPORT:
   309           {
   310             unsigned index = READ_UINT32(pc);
   311             FixedArray *path = code->module()->importPathAt(index);
   312             fprintf(fp, " ; ");
   313             for (unsigned i = 0; i < path->length(); i++) {
   314                 fprintf(fp, "%s", String::cast(path->at(i))->chars());
   315                 if (i != path->length() - 1)
   316                     fprintf(fp, ".");
   317             }
   318             break;
   319           }
   320 
   321           default:
   322             // Unknown opcode!
   323             assert(false);
   324             return;
   325         }
   326 
   327         if (op == OP_STOP)
   328             break;
   329 
   330         fprintf(fp, "\n");
   331         pc += OpcodeInfo[op].length;
   332         assert(pc < code->start() + code->length());
   333     }
   334 
   335     fprintf(fp, "\nSafepoints:\n");
   336     ByteArray *safepoints = code->safepoints();
   337     if (safepoints) {
   338         size_t nsafepoints = safepoints->length() / Code::BytesPerSafepoint(code->maxStackDepth());
   339         for (size_t i = 0; i < nsafepoints; i++) {
   340             Address address = safepoints->raw() + Code::BytesPerSafepoint(code->maxStackDepth()) * i;
   341             fprintf(fp, "%4d: ", *reinterpret_cast<unsigned *>(address));
   342             unsigned char *bits = (unsigned char *)(address + sizeof(unsigned));
   343             for (unsigned j = 0; j < code->maxStackDepth(); j++) {
   344                 if (bits[j / 8] & (1 << (j % 8)))
   345                     fprintf(fp, "%d ", j);
   346             }
   347             fprintf(fp, "\n");
   348         }
   349     }
   350 }