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