sourcepawn/jit/BaseRuntime.cpp
author David Anderson <danderson@mozilla.com>
Thu Aug 08 09:41:24 2013 -0700 (2013-08-08)
changeset 3977 fca2b54741ca
parent 3651 23b839141e74
child 4013 6201c1180e0e
permissions -rw-r--r--
Refactor the JIT to use a newer, simpler macro assembler. (bug 5827, r=ann)
danderson@3977
     1
// vim: set ts=8 sts=2 sw=2 tw=99 et:
dvander@2193
     2
#include <stdio.h>
dvander@2193
     3
#include <stdlib.h>
dvander@2193
     4
#include <string.h>
dvander@2226
     5
#include <assert.h>
dvander@2193
     6
#include "BaseRuntime.h"
dvander@2193
     7
#include "sp_vm_engine.h"
dvander@2193
     8
#include "x86/jit_x86.h"
dvander@2193
     9
#include "sp_vm_basecontext.h"
dvander@2193
    10
#include "engine2.h"
dvander@2193
    11
asherkin@3601
    12
#include "md5/md5.h"
asherkin@3601
    13
dvander@2193
    14
using namespace SourcePawn;
dvander@2193
    15
danderson@3977
    16
static inline bool
danderson@3977
    17
IsPointerCellAligned(void *p)
dvander@2193
    18
{
danderson@3977
    19
  return uintptr_t(p) % 4 == 0;
danderson@3977
    20
}
dvander@2193
    21
danderson@3977
    22
BaseRuntime::BaseRuntime()
danderson@3977
    23
  : m_Debug(&m_plugin),
danderson@3977
    24
    m_pCtx(NULL), 
danderson@3977
    25
    m_PubFuncs(NULL),
danderson@3977
    26
    m_PubJitFuncs(NULL),
danderson@3977
    27
    co_(NULL),
danderson@3977
    28
    m_CompSerial(0)
danderson@3977
    29
{
danderson@3977
    30
  memset(&m_plugin, 0, sizeof(m_plugin));
danderson@3977
    31
danderson@3977
    32
  m_MaxFuncs = 0;
danderson@3977
    33
  m_NumFuncs = 0;
danderson@3977
    34
  float_table_ = NULL;
danderson@3977
    35
  function_map_ = NULL;
danderson@3977
    36
  alt_pcode_ = NULL;
danderson@3977
    37
  
danderson@3977
    38
  memset(m_CodeHash, 0, sizeof(m_CodeHash));
danderson@3977
    39
  memset(m_DataHash, 0, sizeof(m_DataHash));
dvander@2193
    40
}
dvander@2193
    41
dvander@2193
    42
BaseRuntime::~BaseRuntime()
dvander@2193
    43
{
danderson@3977
    44
  for (uint32_t i = 0; i < m_plugin.num_publics; i++)
danderson@3977
    45
    delete m_PubFuncs[i];
danderson@3977
    46
  delete [] m_PubFuncs;
danderson@3977
    47
  delete [] m_PubJitFuncs;
danderson@3977
    48
  delete [] float_table_;
danderson@3977
    49
  delete [] function_map_;
danderson@3977
    50
  delete [] alt_pcode_;
danderson@3977
    51
danderson@3977
    52
  for (size_t i = 0; i < m_JitFunctions.length(); i++)
danderson@3977
    53
    delete m_JitFunctions[i];
danderson@3977
    54
danderson@3977
    55
  delete m_pCtx;
danderson@3977
    56
  if (co_)
danderson@3977
    57
    co_->Abort();
danderson@3977
    58
danderson@3977
    59
  free(m_plugin.base);
danderson@3977
    60
  delete [] m_plugin.memory;
danderson@3977
    61
  delete [] m_plugin.publics;
danderson@3977
    62
  delete [] m_plugin.pubvars;
danderson@3977
    63
  delete [] m_plugin.natives;
danderson@3977
    64
  free(m_plugin.name);
danderson@3977
    65
}
dvander@2193
    66
danderson@3977
    67
void
danderson@3977
    68
BaseRuntime::SetupFloatNativeRemapping()
danderson@3977
    69
{
danderson@3977
    70
  float_table_ = new floattbl_t[m_plugin.num_natives];
danderson@3977
    71
  for (size_t i = 0; i < m_plugin.num_natives; i++) {
danderson@3977
    72
    const char *name = m_plugin.natives[i].name;
danderson@3977
    73
    if (!strcmp(name, "FloatAbs")) {
danderson@3977
    74
      float_table_[i].found = true;
danderson@3977
    75
      float_table_[i].index = OP_FABS;
danderson@3977
    76
    } else if (!strcmp(name, "FloatAdd")) {
danderson@3977
    77
      float_table_[i].found = true;
danderson@3977
    78
      float_table_[i].index = OP_FLOATADD;
danderson@3977
    79
    } else if (!strcmp(name, "FloatSub")) {
danderson@3977
    80
      float_table_[i].found = true;
danderson@3977
    81
      float_table_[i].index = OP_FLOATSUB;
danderson@3977
    82
    } else if (!strcmp(name, "FloatMul")) {
danderson@3977
    83
      float_table_[i].found = true;
danderson@3977
    84
      float_table_[i].index = OP_FLOATMUL;
danderson@3977
    85
    } else if (!strcmp(name, "FloatDiv")) {
danderson@3977
    86
      float_table_[i].found = true;
danderson@3977
    87
      float_table_[i].index = OP_FLOATDIV;
danderson@3977
    88
    } else if (!strcmp(name, "float")) {
danderson@3977
    89
      float_table_[i].found = true;
danderson@3977
    90
      float_table_[i].index = OP_FLOAT;
danderson@3977
    91
    } else if (!strcmp(name, "FloatCompare")) {
danderson@3977
    92
      float_table_[i].found = true;
danderson@3977
    93
      float_table_[i].index = OP_FLOATCMP;
danderson@3977
    94
    } else if (!strcmp(name, "RoundToZero")) {
danderson@3977
    95
      float_table_[i].found = true;
danderson@3977
    96
      float_table_[i].index = OP_RND_TO_ZERO;
danderson@3977
    97
    } else if (!strcmp(name, "RoundToCeil")) {
danderson@3977
    98
      float_table_[i].found = true;
danderson@3977
    99
      float_table_[i].index = OP_RND_TO_CEIL;
danderson@3977
   100
    } else if (!strcmp(name, "RoundToFloor")) {
danderson@3977
   101
      float_table_[i].found = true;
danderson@3977
   102
      float_table_[i].index = OP_RND_TO_FLOOR;
danderson@3977
   103
    } else if (!strcmp(name, "RoundToNearest")) {
danderson@3977
   104
      float_table_[i].found = true;
danderson@3977
   105
      float_table_[i].index = OP_RND_TO_NEAREST;
danderson@3977
   106
    }
danderson@3977
   107
  }
danderson@3977
   108
}
dvander@2226
   109
danderson@3977
   110
unsigned
danderson@3977
   111
BaseRuntime::GetNativeReplacement(size_t index)
danderson@3977
   112
{
danderson@3977
   113
  if (!float_table_[index].found)
danderson@3977
   114
    return OP_NOP;
danderson@3977
   115
  return float_table_[index].index;
danderson@3977
   116
}
dvander@2193
   117
danderson@3977
   118
void
danderson@3977
   119
BaseRuntime::SetName(const char *name)
danderson@3977
   120
{
danderson@3977
   121
  m_plugin.name = strdup(name);
dvander@2226
   122
}
dvander@2226
   123
dvander@2226
   124
static cell_t InvalidNative(IPluginContext *pCtx, const cell_t *params)
dvander@2226
   125
{
danderson@3977
   126
  return pCtx->ThrowNativeErrorEx(SP_ERROR_INVALID_NATIVE, "Invalid native");
dvander@2193
   127
}
dvander@2193
   128
dvander@2226
   129
int BaseRuntime::CreateFromMemory(sp_file_hdr_t *hdr, uint8_t *base)
dvander@2193
   130
{
danderson@3977
   131
  char *nameptr;
danderson@3977
   132
  uint8_t sectnum = 0;
danderson@3977
   133
  sp_file_section_t *secptr = (sp_file_section_t *)(base + sizeof(sp_file_hdr_t));
dvander@2226
   134
danderson@3977
   135
  memset(&m_plugin, 0, sizeof(m_plugin));
dvander@2226
   136
danderson@3977
   137
  m_plugin.base = base;
danderson@3977
   138
  m_plugin.base_size = hdr->imagesize;
dvander@2226
   139
danderson@3977
   140
  if (hdr->version == 0x0101)
danderson@3977
   141
    m_plugin.debug.unpacked = true;
dvander@2378
   142
danderson@3977
   143
  /* We have to read the name section first */
danderson@3977
   144
  for (sectnum = 0; sectnum < hdr->sections; sectnum++) {
danderson@3977
   145
    nameptr = (char *)(base + hdr->stringtab + secptr[sectnum].nameoffs);
danderson@3977
   146
    if (strcmp(nameptr, ".names") == 0) {
danderson@3977
   147
      m_plugin.stringbase = (const char *)(base + secptr[sectnum].dataoffs);
danderson@3977
   148
      break;
danderson@3977
   149
    }
danderson@3977
   150
  }
danderson@3977
   151
danderson@3977
   152
  sectnum = 0;
dvander@2226
   153
danderson@3977
   154
  /* Now read the rest of the sections */
danderson@3977
   155
  while (sectnum < hdr->sections) {
danderson@3977
   156
    nameptr = (char *)(base + hdr->stringtab + secptr->nameoffs);
dvander@2226
   157
danderson@3977
   158
    if (!(m_plugin.pcode) && !strcmp(nameptr, ".code")) {
danderson@3977
   159
      sp_file_code_t *cod = (sp_file_code_t *)(base + secptr->dataoffs);
dvander@2226
   160
danderson@3977
   161
      if (cod->codeversion < SP_CODEVERS_JIT1)
danderson@3977
   162
        return SP_ERROR_CODE_TOO_OLD;
danderson@3977
   163
      if (cod->codeversion > SP_CODEVERS_JIT2)
danderson@3977
   164
        return SP_ERROR_CODE_TOO_NEW;
dvander@2226
   165
danderson@3977
   166
      m_plugin.pcode = base + secptr->dataoffs + cod->code;
danderson@3977
   167
      m_plugin.pcode_size = cod->codesize;
danderson@3977
   168
      m_plugin.flags = cod->flags;
danderson@3977
   169
      m_plugin.pcode_version = cod->codeversion;
danderson@3977
   170
      if (!IsPointerCellAligned(m_plugin.pcode)) {
danderson@3977
   171
        // The JIT requires that pcode is cell-aligned, so if it's not, we
danderson@3977
   172
        // remap the code segment to a new address.
danderson@3977
   173
        alt_pcode_ = new uint8_t[m_plugin.pcode_size];
danderson@3977
   174
        memcpy(alt_pcode_, m_plugin.pcode, m_plugin.pcode_size);
danderson@3977
   175
        assert(IsPointerCellAligned(alt_pcode_));
dvander@2226
   176
danderson@3977
   177
        m_plugin.pcode = alt_pcode_;
danderson@3977
   178
      }
danderson@3977
   179
    } else if (!(m_plugin.data) && !strcmp(nameptr, ".data")) {
danderson@3977
   180
      sp_file_data_t *dat = (sp_file_data_t *)(base + secptr->dataoffs);
danderson@3977
   181
      m_plugin.data = base + secptr->dataoffs + dat->data;
danderson@3977
   182
      m_plugin.data_size = dat->datasize;
danderson@3977
   183
      m_plugin.mem_size = dat->memsize;
danderson@3977
   184
      m_plugin.memory = new uint8_t[m_plugin.mem_size];
danderson@3977
   185
      memcpy(m_plugin.memory, m_plugin.data, m_plugin.data_size);
danderson@3977
   186
    } else if ((m_plugin.publics == NULL) && !strcmp(nameptr, ".publics")) {
danderson@3977
   187
      sp_file_publics_t *publics;
dvander@2226
   188
danderson@3977
   189
      publics = (sp_file_publics_t *)(base + secptr->dataoffs);
danderson@3977
   190
      m_plugin.num_publics = secptr->size / sizeof(sp_file_publics_t);
dvander@2226
   191
danderson@3977
   192
      if (m_plugin.num_publics > 0) {
danderson@3977
   193
        m_plugin.publics = new sp_public_t[m_plugin.num_publics];
dvander@2226
   194
danderson@3977
   195
        for (uint32_t i = 0; i < m_plugin.num_publics; i++) {
danderson@3977
   196
          m_plugin.publics[i].code_offs = publics[i].address;
danderson@3977
   197
          m_plugin.publics[i].funcid = (i << 1) | 1;
danderson@3977
   198
          m_plugin.publics[i].name = m_plugin.stringbase + publics[i].name;
danderson@3977
   199
        }
danderson@3977
   200
      }
danderson@3977
   201
    } else if ((m_plugin.pubvars == NULL) && !strcmp(nameptr, ".pubvars")) {
danderson@3977
   202
      sp_file_pubvars_t *pubvars;
dvander@2226
   203
danderson@3977
   204
      pubvars = (sp_file_pubvars_t *)(base + secptr->dataoffs);
danderson@3977
   205
      m_plugin.num_pubvars = secptr->size / sizeof(sp_file_pubvars_t);
dvander@2226
   206
danderson@3977
   207
      if (m_plugin.num_pubvars > 0) {
danderson@3977
   208
        m_plugin.pubvars = new sp_pubvar_t[m_plugin.num_pubvars];
dvander@2226
   209
danderson@3977
   210
        for (uint32_t i = 0; i < m_plugin.num_pubvars; i++) {
danderson@3977
   211
          m_plugin.pubvars[i].name = m_plugin.stringbase + pubvars[i].name;
danderson@3977
   212
          m_plugin.pubvars[i].offs = (cell_t *)(m_plugin.memory + pubvars[i].address);
danderson@3977
   213
        }
danderson@3977
   214
      }
danderson@3977
   215
    } else if ((m_plugin.natives == NULL) && !strcmp(nameptr, ".natives")) {
danderson@3977
   216
      sp_file_natives_t *natives;
danderson@3977
   217
danderson@3977
   218
      natives = (sp_file_natives_t *)(base + secptr->dataoffs);
danderson@3977
   219
      m_plugin.num_natives = secptr->size / sizeof(sp_file_natives_t);
danderson@3977
   220
danderson@3977
   221
      if (m_plugin.num_natives > 0) {
danderson@3977
   222
        m_plugin.natives = new sp_native_t[m_plugin.num_natives];
dvander@2226
   223
danderson@3977
   224
        for (uint32_t i = 0; i < m_plugin.num_natives; i++) {
danderson@3977
   225
          m_plugin.natives[i].flags = 0;
danderson@3977
   226
          m_plugin.natives[i].pfn = InvalidNative;
danderson@3977
   227
          m_plugin.natives[i].status = SP_NATIVE_UNBOUND;
danderson@3977
   228
          m_plugin.natives[i].user = NULL;
danderson@3977
   229
          m_plugin.natives[i].name = m_plugin.stringbase + natives[i].name;
danderson@3977
   230
        }
danderson@3977
   231
      }
danderson@3977
   232
    } else if (!(m_plugin.debug.files) && !strcmp(nameptr, ".dbg.files")) {
danderson@3977
   233
      m_plugin.debug.files = (sp_fdbg_file_t *)(base + secptr->dataoffs);
danderson@3977
   234
    } else if (!(m_plugin.debug.lines) && !strcmp(nameptr, ".dbg.lines")) {
danderson@3977
   235
      m_plugin.debug.lines = (sp_fdbg_line_t *)(base + secptr->dataoffs);
danderson@3977
   236
    } else if (!(m_plugin.debug.symbols) && !strcmp(nameptr, ".dbg.symbols")) {
danderson@3977
   237
      m_plugin.debug.symbols = (sp_fdbg_symbol_t *)(base + secptr->dataoffs);
danderson@3977
   238
    } else if (!(m_plugin.debug.lines_num) && !strcmp(nameptr, ".dbg.info")) {
danderson@3977
   239
      sp_fdbg_info_t *inf = (sp_fdbg_info_t *)(base + secptr->dataoffs);
danderson@3977
   240
      m_plugin.debug.files_num = inf->num_files;
danderson@3977
   241
      m_plugin.debug.lines_num = inf->num_lines;
danderson@3977
   242
      m_plugin.debug.syms_num = inf->num_syms;
danderson@3977
   243
    } else if (!(m_plugin.debug.stringbase) && !strcmp(nameptr, ".dbg.strings")) {
danderson@3977
   244
      m_plugin.debug.stringbase = (const char *)(base + secptr->dataoffs);
danderson@3977
   245
    } else if (strcmp(nameptr, ".dbg.natives") == 0) {
danderson@3977
   246
      m_plugin.debug.unpacked = false;
danderson@3977
   247
    }
dvander@2226
   248
danderson@3977
   249
    secptr++;
danderson@3977
   250
    sectnum++;
danderson@3977
   251
  }
danderson@3977
   252
danderson@3977
   253
  if (m_plugin.pcode == NULL || m_plugin.data == NULL)
danderson@3977
   254
    return SP_ERROR_FILE_FORMAT;
danderson@3977
   255
danderson@3977
   256
  if ((m_plugin.flags & SP_FLAG_DEBUG) && (
danderson@3977
   257
    !(m_plugin.debug.files) || 
danderson@3977
   258
    !(m_plugin.debug.lines) || 
danderson@3977
   259
    !(m_plugin.debug.symbols) || 
danderson@3977
   260
    !(m_plugin.debug.stringbase) ))
danderson@3977
   261
  {
danderson@3977
   262
    return SP_ERROR_FILE_FORMAT;
danderson@3977
   263
  }
dvander@2226
   264
danderson@3977
   265
  if (m_plugin.num_publics > 0) {
danderson@3977
   266
    m_PubFuncs = new CFunction *[m_plugin.num_publics];
danderson@3977
   267
    memset(m_PubFuncs, 0, sizeof(CFunction *) * m_plugin.num_publics);
danderson@3977
   268
    m_PubJitFuncs = new JitFunction *[m_plugin.num_publics];
danderson@3977
   269
    memset(m_PubJitFuncs, 0, sizeof(JitFunction *) * m_plugin.num_publics);
danderson@3977
   270
  }
dvander@2226
   271
danderson@3977
   272
  MD5 md5_pcode;
danderson@3977
   273
  md5_pcode.update(m_plugin.pcode, m_plugin.pcode_size);
danderson@3977
   274
  md5_pcode.finalize();
danderson@3977
   275
  md5_pcode.raw_digest(m_CodeHash);
danderson@3977
   276
  
danderson@3977
   277
  MD5 md5_data;
danderson@3977
   278
  md5_data.update(m_plugin.data, m_plugin.data_size);
danderson@3977
   279
  md5_data.finalize();
danderson@3977
   280
  md5_data.raw_digest(m_DataHash);
dvander@2226
   281
danderson@3977
   282
  m_plugin.profiler = g_engine2.GetProfiler();
danderson@3977
   283
  m_pCtx = new BaseContext(this);
danderson@3977
   284
  co_ = g_Jit.StartCompilation(this);
asherkin@3601
   285
danderson@3977
   286
  SetupFloatNativeRemapping();
danderson@3977
   287
  function_map_size_ = m_plugin.pcode_size / sizeof(cell_t) + 1;
danderson@3977
   288
  function_map_ = new JitFunction *[function_map_size_];
danderson@3977
   289
  memset(function_map_, 0, function_map_size_ * sizeof(JitFunction *));
dvander@2226
   290
danderson@3977
   291
  return SP_ERROR_NONE;
dvander@2193
   292
}
dvander@2193
   293
danderson@3977
   294
void
danderson@3977
   295
BaseRuntime::AddJittedFunction(JitFunction *fn)
dvander@2193
   296
{
danderson@3977
   297
  m_JitFunctions.append(fn);
dvander@2193
   298
danderson@3977
   299
  cell_t pcode_offset = fn->GetPCodeAddress();
danderson@3977
   300
  assert(pcode_offset % 4 == 0);
danderson@3977
   301
danderson@3977
   302
  uint32_t pcode_index = pcode_offset / 4;
danderson@3977
   303
  assert(pcode_index < function_map_size_);
dvander@2193
   304
danderson@3977
   305
  function_map_[pcode_index] = fn;
danderson@3977
   306
}
dvander@2193
   307
danderson@3977
   308
JitFunction *
danderson@3977
   309
BaseRuntime::GetJittedFunctionByOffset(cell_t pcode_offset)
danderson@3977
   310
{
danderson@3977
   311
  assert(pcode_offset % 4 == 0);
danderson@3977
   312
danderson@3977
   313
  uint32_t pcode_index = pcode_offset / 4;
danderson@3977
   314
  assert(pcode_index < function_map_size_);
danderson@3977
   315
danderson@3977
   316
  return function_map_[pcode_index];
dvander@2193
   317
}
dvander@2193
   318
danderson@3977
   319
int
danderson@3977
   320
BaseRuntime::FindNativeByName(const char *name, uint32_t *index)
dvander@2193
   321
{
danderson@3977
   322
  for (uint32_t i=0; i<m_plugin.num_natives; i++) {
danderson@3977
   323
    if (strcmp(m_plugin.natives[i].name, name) == 0) {
danderson@3977
   324
      if (index)
danderson@3977
   325
        *index = i;
danderson@3977
   326
      return SP_ERROR_NONE;
danderson@3977
   327
    }
danderson@3977
   328
  }
dvander@2193
   329
danderson@3977
   330
  return SP_ERROR_NOT_FOUND;
danderson@3977
   331
}
dvander@2193
   332
danderson@3977
   333
int
danderson@3977
   334
BaseRuntime::GetNativeByIndex(uint32_t index, sp_native_t **native)
danderson@3977
   335
{
danderson@3977
   336
  if (index >= m_plugin.num_natives)
danderson@3977
   337
    return SP_ERROR_INDEX;
danderson@3977
   338
danderson@3977
   339
  if (native)
danderson@3977
   340
    *native = &(m_plugin.natives[index]);
danderson@3977
   341
danderson@3977
   342
  return SP_ERROR_NONE;
dvander@2193
   343
}
dvander@2193
   344
dvander@2193
   345
danderson@3977
   346
uint32_t
danderson@3977
   347
BaseRuntime::GetNativesNum()
dvander@2193
   348
{
danderson@3977
   349
  return m_plugin.num_natives;
dvander@2193
   350
}
dvander@2193
   351
danderson@3977
   352
int
danderson@3977
   353
BaseRuntime::FindPublicByName(const char *name, uint32_t *index)
dvander@2193
   354
{
danderson@3977
   355
  int diff, high, low;
danderson@3977
   356
  uint32_t mid;
danderson@3977
   357
danderson@3977
   358
  high = m_plugin.num_publics - 1;
danderson@3977
   359
  low = 0;
dvander@2193
   360
danderson@3977
   361
  while (low <= high) {
danderson@3977
   362
    mid = (low + high) / 2;
danderson@3977
   363
    diff = strcmp(m_plugin.publics[mid].name, name);
danderson@3977
   364
    if (diff == 0) {
danderson@3977
   365
      if (index)
danderson@3977
   366
        *index = mid;
danderson@3977
   367
      return SP_ERROR_NONE;
danderson@3977
   368
    } else if (diff < 0) {
danderson@3977
   369
      low = mid + 1;
danderson@3977
   370
    } else {
danderson@3977
   371
      high = mid - 1;
danderson@3977
   372
    }
danderson@3977
   373
  }
dvander@2193
   374
danderson@3977
   375
  return SP_ERROR_NOT_FOUND;
dvander@2193
   376
}
dvander@2193
   377
danderson@3977
   378
int
danderson@3977
   379
BaseRuntime::GetPublicByIndex(uint32_t index, sp_public_t **pblic)
dvander@2193
   380
{
danderson@3977
   381
  if (index >= m_plugin.num_publics)
danderson@3977
   382
    return SP_ERROR_INDEX;
danderson@3977
   383
danderson@3977
   384
  if (pblic)
danderson@3977
   385
    *pblic = &(m_plugin.publics[index]);
danderson@3977
   386
danderson@3977
   387
  return SP_ERROR_NONE;
dvander@2193
   388
}
dvander@2193
   389
danderson@3977
   390
uint32_t
danderson@3977
   391
BaseRuntime::GetPublicsNum()
dvander@2193
   392
{
danderson@3977
   393
  return m_plugin.num_publics;
danderson@3977
   394
}
dvander@2193
   395
danderson@3977
   396
int
danderson@3977
   397
BaseRuntime::GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar)
danderson@3977
   398
{
danderson@3977
   399
  if (index >= m_plugin.num_pubvars)
danderson@3977
   400
    return SP_ERROR_INDEX;
dvander@2193
   401
danderson@3977
   402
  if (pubvar)
danderson@3977
   403
    *pubvar = &(m_plugin.pubvars[index]);
danderson@3977
   404
danderson@3977
   405
  return SP_ERROR_NONE;
dvander@2193
   406
}
dvander@2193
   407
danderson@3977
   408
int
danderson@3977
   409
BaseRuntime::FindPubvarByName(const char *name, uint32_t *index)
dvander@2193
   410
{
danderson@3977
   411
  int diff, high, low;
danderson@3977
   412
  uint32_t mid;
dvander@2193
   413
danderson@3977
   414
  high = m_plugin.num_pubvars - 1;
danderson@3977
   415
  low = 0;
dvander@2193
   416
danderson@3977
   417
  while (low <= high) {
danderson@3977
   418
    mid = (low + high) / 2;
danderson@3977
   419
    diff = strcmp(m_plugin.pubvars[mid].name, name);
danderson@3977
   420
    if (diff == 0) {
danderson@3977
   421
      if (index)
danderson@3977
   422
        *index = mid;
danderson@3977
   423
      return SP_ERROR_NONE;
danderson@3977
   424
    } else if (diff < 0) {
danderson@3977
   425
      low = mid + 1;
danderson@3977
   426
    } else {
danderson@3977
   427
      high = mid - 1;
danderson@3977
   428
    }
danderson@3977
   429
  }
dvander@2193
   430
danderson@3977
   431
  return SP_ERROR_NOT_FOUND;
dvander@2193
   432
}
dvander@2193
   433
danderson@3977
   434
int
danderson@3977
   435
BaseRuntime::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr)
dvander@2193
   436
{
danderson@3977
   437
  if (index >= m_plugin.num_pubvars)
danderson@3977
   438
    return SP_ERROR_INDEX;
dvander@2193
   439
danderson@3977
   440
  *local_addr = (uint8_t *)m_plugin.pubvars[index].offs - m_plugin.memory;
danderson@3977
   441
  *phys_addr = m_plugin.pubvars[index].offs;
dvander@2193
   442
danderson@3977
   443
  return SP_ERROR_NONE;
dvander@2193
   444
}
dvander@2193
   445
danderson@3977
   446
uint32_t
danderson@3977
   447
BaseRuntime::GetPubVarsNum()
dvander@2193
   448
{
danderson@3977
   449
  return m_plugin.num_pubvars;
dvander@2193
   450
}
dvander@2193
   451
danderson@3977
   452
IPluginContext *
danderson@3977
   453
BaseRuntime::GetDefaultContext()
dvander@2193
   454
{
danderson@3977
   455
  return m_pCtx;
dvander@2193
   456
}
dvander@2193
   457
danderson@3977
   458
IPluginDebugInfo *
danderson@3977
   459
BaseRuntime::GetDebugInfo()
dvander@2193
   460
{
danderson@3977
   461
  return &m_Debug;
dvander@2193
   462
}
dvander@2193
   463
danderson@3977
   464
IPluginFunction *
danderson@3977
   465
BaseRuntime::GetFunctionById(funcid_t func_id)
dvander@2193
   466
{
danderson@3977
   467
  CFunction *pFunc = NULL;
dvander@2193
   468
danderson@3977
   469
  if (func_id & 1) {
danderson@3977
   470
    func_id >>= 1;
danderson@3977
   471
    if (func_id >= m_plugin.num_publics)
danderson@3977
   472
      return NULL;
danderson@3977
   473
    pFunc = m_PubFuncs[func_id];
danderson@3977
   474
    if (!pFunc) {
danderson@3977
   475
      m_PubFuncs[func_id] = new CFunction(this, 
danderson@3977
   476
        (func_id << 1) | 1,
danderson@3977
   477
        func_id);
danderson@3977
   478
      pFunc = m_PubFuncs[func_id];
danderson@3977
   479
    }
danderson@3977
   480
  }
dvander@2193
   481
danderson@3977
   482
  return pFunc;
dvander@2193
   483
}
dvander@2193
   484
danderson@3977
   485
IPluginFunction *
danderson@3977
   486
BaseRuntime::GetFunctionByName(const char *public_name)
dvander@2193
   487
{
danderson@3977
   488
  uint32_t index;
dvander@2193
   489
danderson@3977
   490
  if (FindPublicByName(public_name, &index) != SP_ERROR_NONE)
danderson@3977
   491
    return NULL;
dvander@2193
   492
danderson@3977
   493
  CFunction *pFunc = m_PubFuncs[index];
danderson@3977
   494
  if (!pFunc) {
danderson@3977
   495
    sp_public_t *pub = NULL;
danderson@3977
   496
    GetPublicByIndex(index, &pub);
danderson@3977
   497
    if (pub)
danderson@3977
   498
      m_PubFuncs[index] = new CFunction(this, (index << 1) | 1, index);
danderson@3977
   499
    pFunc = m_PubFuncs[index];
danderson@3977
   500
  }
dvander@2193
   501
danderson@3977
   502
  return pFunc;
dvander@2193
   503
}
dvander@2193
   504
dvander@2193
   505
bool BaseRuntime::IsDebugging()
dvander@2193
   506
{
danderson@3977
   507
  return true;
dvander@2193
   508
}
dvander@2193
   509
dvander@2193
   510
void BaseRuntime::SetPauseState(bool paused)
dvander@2193
   511
{
danderson@3977
   512
  if (paused)
danderson@3977
   513
  {
danderson@3977
   514
    m_plugin.run_flags |= SPFLAG_PLUGIN_PAUSED;
danderson@3977
   515
  }
danderson@3977
   516
  else
danderson@3977
   517
  {
danderson@3977
   518
    m_plugin.run_flags &= ~SPFLAG_PLUGIN_PAUSED;
danderson@3977
   519
  }
dvander@2193
   520
}
dvander@2193
   521
dvander@2193
   522
bool BaseRuntime::IsPaused()
dvander@2193
   523
{
danderson@3977
   524
  return ((m_plugin.run_flags & SPFLAG_PLUGIN_PAUSED) == SPFLAG_PLUGIN_PAUSED);
dvander@2193
   525
}
dvander@2193
   526
dvander@2193
   527
size_t BaseRuntime::GetMemUsage()
dvander@2193
   528
{
danderson@3977
   529
  size_t mem = 0;
dvander@2193
   530
danderson@3977
   531
  mem += sizeof(this);
danderson@3977
   532
  mem += sizeof(sp_plugin_t);
danderson@3977
   533
  mem += sizeof(BaseContext);
danderson@3977
   534
  mem += m_plugin.base_size;
dvander@2193
   535
danderson@3977
   536
  return mem;
dvander@2193
   537
}
dvander@2193
   538
asherkin@3601
   539
unsigned char *BaseRuntime::GetCodeHash()
asherkin@3601
   540
{
danderson@3977
   541
  return m_CodeHash;
asherkin@3601
   542
}
asherkin@3601
   543
asherkin@3601
   544
unsigned char *BaseRuntime::GetDataHash()
asherkin@3601
   545
{
danderson@3977
   546
  return m_DataHash;
asherkin@3601
   547
}
asherkin@3601
   548
dvander@2193
   549
BaseContext *BaseRuntime::GetBaseContext()
dvander@2193
   550
{
danderson@3977
   551
  return m_pCtx;
dvander@2193
   552
}
dvander@2193
   553
danderson@3977
   554
int
danderson@3977
   555
BaseRuntime::ApplyCompilationOptions(ICompilation *co)
dvander@2226
   556
{
danderson@3977
   557
  if (co == NULL)
danderson@3977
   558
    return SP_ERROR_NONE;
dvander@2226
   559
danderson@3977
   560
  co_ = g_Jit.ApplyOptions(co_, co);
danderson@3977
   561
  m_plugin.prof_flags = ((CompData *)co_)->profile;
dvander@2226
   562
danderson@3977
   563
  return SP_ERROR_NONE;
dvander@2226
   564
}
dvander@2226
   565
danderson@3977
   566
int
danderson@3977
   567
BaseRuntime::CreateBlank(uint32_t heastk)
dvander@2226
   568
{
danderson@3977
   569
  memset(&m_plugin, 0, sizeof(m_plugin));
dvander@2226
   570
danderson@3977
   571
  /* Align to cell_t bytes */
danderson@3977
   572
  heastk += sizeof(cell_t);
danderson@3977
   573
  heastk -= heastk % sizeof(cell_t);
dvander@2226
   574
danderson@3977
   575
  m_plugin.mem_size = heastk;
danderson@3977
   576
  m_plugin.memory = new uint8_t[heastk];
dvander@2545
   577
danderson@3977
   578
  m_plugin.profiler = g_engine2.GetProfiler();
danderson@3977
   579
  m_pCtx = new BaseContext(this);
danderson@3977
   580
  co_ = g_Jit.StartCompilation(this);
dvander@2545
   581
danderson@3977
   582
  return SP_ERROR_NONE;
dvander@2545
   583
}