LCOV - app.info - gfx/graphite2/src/Code.cpp

LCOV - code coverage report
| Current view: | directory - gfx/graphite2/src - Code.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 249 | 0 | 0.0 %
| Date: | 2012-06-02 | Functions: | 20 | 0 | 0.0 %

           1                 : /*  GRAPHITE2 LICENSING
           2                 :
           3                 :     Copyright 2010, SIL International
           4                 :     All rights reserved.
           5                 :
           6                 :     This library is free software; you can redistribute it and/or modify
           7                 :     it under the terms of the GNU Lesser General Public License as published
           8                 :     by the Free Software Foundation; either version 2.1 of License, or
           9                 :     (at your option) any later version.
          10                 :
          11                 :     This program is distributed in the hope that it will be useful,
          12                 :     but WITHOUT ANY WARRANTY; without even the implied warranty of
          13                 :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
          14                 :     Lesser General Public License for more details.
          15                 :
          16                 :     You should also have received a copy of the GNU Lesser General Public
          17                 :     License along with this library in the file named "LICENSE".
          18                 :     If not, write to the Free Software Foundation, 51 Franklin Street,
          19                 :     Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
          20                 :     internet at http://www.fsf.org/licenses/lgpl.html.
          21                 :
          22                 : Alternatively, the contents of this file may be used under the terms of the
          23                 : Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
          24                 : License, as published by the Free Software Foundation, either version 2
          25                 : of the License or (at your option) any later version.
          26                 : */
          27                 : // This class represents loaded graphite stack machine code.  It performs
          28                 : // basic sanity checks, on the incoming code to prevent more obvious problems
          29                 : // from crashing graphite.
          30                 : // Author: Tim Eves
          31                 :
          32                 : #include <cassert>
          33                 : #include <cstddef>
          34                 : #include <cstdlib>
          35                 : #include <cstring>
          36                 : #include "graphite2/Segment.h"
          37                 : #include "inc/Code.h"
          38                 : #include "inc/Machine.h"
          39                 : #include "inc/Silf.h"
          40                 : #include "inc/Face.h"
          41                 : #include "inc/Rule.h"
          42                 :
          43                 : #include <cstdio>
          44                 :
          45                 : #ifdef NDEBUG
          46                 : #ifdef __GNUC__
          47                 : #pragma GCC diagnostic ignored "-Wunused-parameter"
          48                 : #endif
          49                 : #endif
          50                 :
          51                 :
          52                 : using namespace graphite2;
          53                 : using namespace vm;
          54                 :
          55                 : namespace {
          56                 :
          57               0 : inline bool is_return(const instr i) {
          58               0 :     const opcode_t * opmap = Machine::getOpcodeTable();
          59               0 :     const instr pop_ret  = *opmap[POP_RET].impl,
          60               0 :                 ret_zero = *opmap[RET_ZERO].impl,
          61               0 :                 ret_true = *opmap[RET_TRUE].impl;
          62               0 :     return i == pop_ret || i == ret_zero || i == ret_true;
          63                 : }
          64                 :
          65                 : struct context
          66                 : {
          67               0 :     context(uint8 ref=0) : codeRef(ref) {flags.changed=false; flags.referenced=false; flags.inserted=false;}
          68                 :     struct {
          69                 :         uint8   changed:1,
          70                 :                 referenced:1,
          71                 :                 inserted:1;
          72                 :     } flags;
          73                 :     uint8       codeRef;
          74                 : };
          75                 :
          76                 : } // end namespace
          77                 :
          78                 :
          79                 : class Machine::Code::decoder
          80                 : {
          81                 : public:
          82                 :     struct limits;
          83                 :     struct analysis
          84                 :     {
          85                 :         uint8     slotref;
          86                 :         context   contexts[256];
          87                 :         byte      max_ref;
          88                 :
          89               0 :         analysis() : slotref(0), max_ref(0) {};
          90                 :         void set_ref(int index) throw();
          91                 :         void set_changed(int index) throw();
          92                 :
          93                 :     };
          94                 :
          95                 :     decoder(const limits & lims, Code &code) throw();
          96                 :
          97                 :     bool        load(const byte * bc_begin, const byte * bc_end);
          98                 :     void        apply_analysis(instr * const code, instr * code_end);
          99               0 :     byte        max_ref() { return _analysis.max_ref; }
         100                 :     int         pre_context() const { return _pre_context; }
         101                 :
         102                 : private:
         103                 :     opcode      fetch_opcode(const byte * bc);
         104                 :     void        analyse_opcode(const opcode, const int8 * const dp) throw();
         105                 :     bool        emit_opcode(opcode opc, const byte * & bc);
         106                 :     bool                validate_opcode(const opcode opc, const byte * const bc);
         107                 :     bool        valid_upto(const uint16 limit, const uint16 x) const throw();
         108               0 :     void        failure(const status_t s) const throw() { _code.failure(s); }
         109                 :
         110                 :     Code              & _code;
         111                 :     int                 _pre_context;
         112                 :     uint16              _rule_length;
         113                 :     instr             * _instr;
         114                 :     byte              * _data;
         115                 :     const limits      & _max;
         116                 :     analysis            _analysis;
         117                 : };
         118                 :
         119                 :
         120                 : struct Machine::Code::decoder::limits
         121                 : {
         122                 :   const byte * const bytecode;
         123                 :   const uint8        pre_context;
         124                 :   const uint16       rule_length,
         125                 :                      classes,
         126                 :                      glyf_attrs,
         127                 :                      features;
         128                 :   const byte         attrid[gr_slatMax];
         129                 : };
         130                 :
         131               0 : inline Machine::Code::decoder::decoder(const limits & lims, Code &code) throw()
         132                 : : _code(code),
         133                 :   _pre_context(code._constraint ? 0 : lims.pre_context),
         134                 :   _rule_length(code._constraint ? 1 : lims.rule_length),
         135               0 :   _instr(code._code), _data(code._data), _max(lims)
         136               0 : { }
         137                 :
         138                 :
         139                 :
         140               0 : Machine::Code::Code(bool is_constraint, const byte * bytecode_begin, const byte * const bytecode_end,
         141                 :            uint8 pre_context, uint16 rule_length, const Silf & silf, const Face & face)
         142                 :  :  _code(0), _data_size(0), _instr_count(0), _status(loaded),
         143               0 :     _constraint(is_constraint), _modify(false), _delete(false), _own(true)
         144                 : {
         145               0 :     assert(bytecode_begin != 0);
         146               0 :     if (bytecode_begin == bytecode_end)
         147                 :     {
         148               0 :       ::new (this) Code();
         149               0 :       return;
         150                 :     }
         151               0 :     assert(bytecode_end > bytecode_begin);
         152               0 :     const opcode_t *    op_to_fn = Machine::getOpcodeTable();
         153                 :
         154                 :     // Allocate code and dat target buffers, these sizes are a worst case
         155                 :     // estimate.  Once we know their real sizes the we'll shrink them.
         156                 :     _code = static_cast<instr *>(malloc((bytecode_end - bytecode_begin)
         157               0 :                                              * sizeof(instr)));
         158                 :     _data = static_cast<byte *>(malloc((bytecode_end - bytecode_begin)
         159               0 :                                              * sizeof(byte)));
         160                 :
         161               0 :     if (!_code || !_data) {
         162               0 :         failure(alloc_failed);
         163               0 :         return;
         164                 :     }
         165                 :
         166                 :     const decoder::limits lims = {
         167                 :         bytecode_end,
         168                 :         pre_context,
         169                 :         rule_length,
         170               0 :         silf.numClasses(),
         171               0 :         face.getGlyphFaceCache()->numAttrs(),
         172               0 :         face.numFeatures(),
         173                 :         {1,1,1,1,1,1,1,1,
         174                 :          1,1,1,1,1,1,1,255,
         175                 :          1,1,1,1,1,1,1,1,
         176                 :          1,1,1,1,1,1,0,0,
         177                 :          0,0,0,0,0,0,0,0,
         178                 :          0,0,0,0,0,0,0,0,
         179               0 :          0,0,0,0,0,0,0, silf.numUser()}
         180               0 :     };
         181                 :
         182               0 :     decoder dec(lims, *this);
         183               0 :     if(!dec.load(bytecode_begin, bytecode_end))
         184               0 :        return;
         185                 :
         186                 :     // Is this an empty program?
         187               0 :     if (_instr_count == 0)
         188                 :     {
         189               0 :       release_buffers();
         190               0 :       ::new (this) Code();
         191               0 :       return;
         192                 :     }
         193                 :
         194                 :     // When we reach the end check we've terminated it correctly
         195               0 :     if (!is_return(_code[_instr_count-1])) {
         196               0 :         failure(missing_return);
         197               0 :         return;
         198                 :     }
         199                 :
         200               0 :     assert((_constraint && immutable()) || !_constraint);
         201               0 :     dec.apply_analysis(_code, _code + _instr_count);
         202               0 :     _max_ref = dec.max_ref();
         203                 :
         204                 :     // Now we know exactly how much code and data the program really needs
         205                 :     // realloc the buffers to exactly the right size so we don't waste any
         206                 :     // memory.
         207               0 :     assert((bytecode_end - bytecode_begin) >= std::ptrdiff_t(_instr_count));
         208               0 :     assert((bytecode_end - bytecode_begin) >= std::ptrdiff_t(_data_size));
         209               0 :     _code = static_cast<instr *>(realloc(_code, (_instr_count+1)*sizeof(instr)));
         210               0 :     _data = static_cast<byte *>(realloc(_data, _data_size*sizeof(byte)));
         211                 :
         212                 :     // Make this RET_ZERO, we should never reach this but just in case ...
         213               0 :     _code[_instr_count] = op_to_fn[RET_ZERO].impl[_constraint];
         214                 :
         215               0 :     if (!_code)
         216               0 :         failure(alloc_failed);
         217                 : }
         218                 :
         219               0 : Machine::Code::~Code() throw ()
         220                 : {
         221               0 :     if (_own)
         222               0 :         release_buffers();
         223               0 : }
         224                 :
         225                 :
         226               0 : bool Machine::Code::decoder::load(const byte * bc, const byte * bc_end)
         227                 : {
         228               0 :     while (bc < bc_end)
         229                 :     {
         230               0 :         const opcode opc = fetch_opcode(bc++);
         231               0 :         if (opc == vm::MAX_OPCODE)
         232               0 :             return false;
         233                 :
         234               0 :         analyse_opcode(opc, reinterpret_cast<const int8 *>(bc));
         235                 :
         236               0 :         if (!emit_opcode(opc, bc))
         237               0 :             return false;
         238                 :     }
         239                 :
         240               0 :     return bool(_code);
         241                 : }
         242                 :
         243                 : // Validation check and fixups.
         244                 : //
         245                 :
         246               0 : opcode Machine::Code::decoder::fetch_opcode(const byte * bc)
         247                 : {
         248               0 :     const opcode opc = opcode(*bc++);
         249                 :
         250                 :     // Do some basic sanity checks based on what we know about the opcode
         251               0 :     if (!validate_opcode(opc, bc))      return MAX_OPCODE;
         252                 :
         253                 :     // And check it's arguments as far as possible
         254               0 :     switch (opc)
         255                 :     {
         256                 :         case NOP :
         257                 :         case PUSH_BYTE :
         258                 :         case PUSH_BYTEU :
         259                 :         case PUSH_SHORT :
         260                 :         case PUSH_SHORTU :
         261                 :         case PUSH_LONG :
         262                 :         case ADD :
         263                 :         case SUB :
         264                 :         case MUL :
         265                 :         case DIV :
         266                 :         case MIN_ :
         267                 :         case MAX_ :
         268                 :         case NEG :
         269                 :         case TRUNC8 :
         270                 :         case TRUNC16 :
         271                 :         case COND :
         272                 :         case AND :
         273                 :         case OR :
         274                 :         case NOT :
         275                 :         case EQUAL :
         276                 :         case NOT_EQ :
         277                 :         case LESS :
         278                 :         case GTR :
         279                 :         case LESS_EQ :
         280                 :         case GTR_EQ :
         281               0 :             break;
         282                 :         case NEXT :
         283                 :         case NEXT_N :           // runtime checked
         284                 :         case COPY_NEXT :
         285               0 :             ++_pre_context;
         286               0 :             break;
         287                 :         case PUT_GLYPH_8BIT_OBS :
         288               0 :             valid_upto(_max.classes, bc[0]);
         289               0 :             break;
         290                 :         case PUT_SUBS_8BIT_OBS :
         291               0 :             valid_upto(_rule_length, _pre_context + int8(bc[0]));
         292               0 :             valid_upto(_max.classes, bc[1]);
         293               0 :             valid_upto(_max.classes, bc[2]);
         294               0 :             break;
         295                 :         case PUT_COPY :
         296               0 :             valid_upto(_rule_length, _pre_context + int8(bc[0]));
         297               0 :             break;
         298                 :         case INSERT :
         299               0 :             --_pre_context;
         300               0 :             break;
         301                 :         case DELETE :
         302               0 :             break;
         303                 :         case ASSOC :
         304               0 :             for (uint8 num = bc[0]; num; --num)
         305               0 :                 valid_upto(_rule_length, _pre_context + int8(bc[num]));
         306               0 :             break;
         307                 :         case CNTXT_ITEM :
         308               0 :             valid_upto(_max.rule_length, _max.pre_context + int8(bc[0]));
         309               0 :             if (bc + 2 + bc[1] >= _max.bytecode)  failure(jump_past_end);
         310               0 :             break;
         311                 :         case ATTR_SET :
         312                 :         case ATTR_ADD :
         313                 :         case ATTR_SUB :
         314                 :         case ATTR_SET_SLOT :
         315               0 :                 valid_upto(gr_slatMax, bc[0]);
         316               0 :             break;
         317                 :         case IATTR_SET_SLOT :
         318               0 :             if (valid_upto(gr_slatMax, bc[0]))
         319               0 :                 valid_upto(_max.attrid[bc[0]], bc[1]);
         320               0 :             break;
         321                 :         case PUSH_SLOT_ATTR :
         322               0 :             valid_upto(gr_slatMax, bc[0]);
         323               0 :             valid_upto(_rule_length, _pre_context + int8(bc[1]));
         324               0 :             break;
         325                 :         case PUSH_GLYPH_ATTR_OBS :
         326               0 :             valid_upto(_max.glyf_attrs, bc[0]);
         327               0 :             valid_upto(_rule_length, _pre_context + int8(bc[1]));
         328               0 :             break;
         329                 :         case PUSH_GLYPH_METRIC :
         330               0 :             valid_upto(kgmetDescent, bc[0]);
         331               0 :             valid_upto(_rule_length, _pre_context + int8(bc[1]));
         332                 :             // level: dp[2] no check necessary
         333               0 :             break;
         334                 :         case PUSH_FEAT :
         335               0 :             valid_upto(_max.features, bc[0]);
         336               0 :             valid_upto(_rule_length, _pre_context + int8(bc[1]));
         337               0 :             break;
         338                 :         case PUSH_ATT_TO_GATTR_OBS :
         339               0 :             valid_upto(_max.glyf_attrs, bc[0]);
         340               0 :             valid_upto(_rule_length, _pre_context + int8(bc[1]));
         341               0 :             break;
         342                 :         case PUSH_ATT_TO_GLYPH_METRIC :
         343               0 :             valid_upto(kgmetDescent, bc[0]);
         344               0 :             valid_upto(_rule_length, _pre_context + int8(bc[1]));
         345                 :             // level: dp[2] no check necessary
         346               0 :             break;
         347                 :         case PUSH_ISLOT_ATTR :
         348               0 :             if (valid_upto(gr_slatMax, bc[0]))
         349                 :             {
         350               0 :                 valid_upto(_rule_length, _pre_context + int8(bc[1]));
         351               0 :                 valid_upto(_max.attrid[bc[0]], bc[2]);
         352                 :             }
         353               0 :             break;
         354                 :         case PUSH_IGLYPH_ATTR :// not implemented
         355                 :         case POP_RET :
         356                 :         case RET_ZERO :
         357                 :         case RET_TRUE :
         358               0 :             break;
         359                 :         case IATTR_SET :
         360                 :         case IATTR_ADD :
         361                 :         case IATTR_SUB :
         362               0 :             if (valid_upto(gr_slatMax, bc[0]))
         363               0 :                 valid_upto(_max.attrid[bc[0]], bc[1]);
         364               0 :             break;
         365                 :         case PUSH_PROC_STATE :  // dummy: dp[0] no check necessary
         366                 :         case PUSH_VERSION :
         367               0 :             break;
         368                 :         case PUT_SUBS :
         369               0 :             valid_upto(_rule_length, _pre_context + int8(bc[0]));
         370               0 :             valid_upto(_max.classes, uint16(bc[1]<< 8) | bc[2]);
         371               0 :             valid_upto(_max.classes, uint16(bc[3]<< 8) | bc[4]);
         372               0 :             break;
         373                 :         case PUT_SUBS2 :        // not implemented
         374                 :         case PUT_SUBS3 :        // not implemented
         375               0 :             break;
         376                 :         case PUT_GLYPH :
         377               0 :             valid_upto(_max.classes, uint16(bc[0]<< 8) | bc[1]);
         378               0 :             break;
         379                 :         case PUSH_GLYPH_ATTR :
         380                 :         case PUSH_ATT_TO_GLYPH_ATTR :
         381               0 :             valid_upto(_max.glyf_attrs, uint16(bc[0]<< 8) | bc[1]);
         382               0 :             valid_upto(_rule_length, _pre_context + int8(bc[2]));
         383               0 :             break;
         384                 :         default:
         385               0 :             failure(invalid_opcode);
         386               0 :             break;
         387                 :     }
         388                 :
         389               0 :     return bool(_code) ? opc : MAX_OPCODE;
         390                 : }
         391                 :
         392                 :
         393               0 : void Machine::Code::decoder::analyse_opcode(const opcode opc, const int8  * arg) throw()
         394                 : {
         395               0 :   if (_code._constraint) return;
         396                 :
         397               0 :   switch (opc)
         398                 :   {
         399                 :     case DELETE :
         400               0 :       _code._delete = true;
         401               0 :       break;
         402                 :     case PUT_GLYPH_8BIT_OBS :
         403                 :     case PUT_GLYPH :
         404               0 :       _code._modify = true;
         405               0 :       _analysis.set_changed(_analysis.slotref);
         406               0 :       break;
         407                 :     case NEXT :
         408                 :     case COPY_NEXT :
         409               0 :       if (!_analysis.contexts[_analysis.slotref].flags.inserted)
         410               0 :         ++_analysis.slotref;
         411               0 :       _analysis.contexts[_analysis.slotref] = context(_code._instr_count+1);
         412               0 :       if (_analysis.slotref > _analysis.max_ref) _analysis.max_ref = _analysis.slotref;
         413               0 :       break;
         414                 :     case INSERT :
         415               0 :       _analysis.contexts[_analysis.slotref].flags.inserted = true;
         416               0 :       _code._modify = true;
         417               0 :       break;
         418                 :     case PUT_SUBS_8BIT_OBS :    // slotref on 1st parameter
         419                 :     case PUT_SUBS :
         420               0 :       _code._modify = true;
         421               0 :       _analysis.set_changed(_analysis.slotref);
         422                 :       // no break here;
         423                 :     case PUT_COPY :
         424                 :     {
         425               0 :       if (arg[0] != 0) { _analysis.set_changed(_analysis.slotref); _code._modify = true; }
         426               0 :       if (arg[0] <= 0 && -arg[0] <= _analysis.slotref - _analysis.contexts[_analysis.slotref].flags.inserted)
         427               0 :         _analysis.set_ref(_analysis.slotref + arg[0] - _analysis.contexts[_analysis.slotref].flags.inserted);
         428               0 :       else if (_analysis.slotref + arg[0] > _analysis.max_ref) _analysis.max_ref = _analysis.slotref + arg[0];
         429               0 :       break;
         430                 :     }
         431                 :     case PUSH_ATT_TO_GATTR_OBS : // slotref on 2nd parameter
         432               0 :         if (_code._constraint) return;
         433                 :     case PUSH_GLYPH_ATTR_OBS :
         434                 :     case PUSH_SLOT_ATTR :
         435                 :     case PUSH_GLYPH_METRIC :
         436                 :     case PUSH_ATT_TO_GLYPH_METRIC :
         437                 :     case PUSH_ISLOT_ATTR :
         438                 :     case PUSH_FEAT :
         439               0 :       if (arg[1] <= 0 && -arg[1] <= _analysis.slotref - _analysis.contexts[_analysis.slotref].flags.inserted)
         440               0 :         _analysis.set_ref(_analysis.slotref + arg[1] - _analysis.contexts[_analysis.slotref].flags.inserted);
         441               0 :       else if (_analysis.slotref + arg[1] > _analysis.max_ref) _analysis.max_ref = _analysis.slotref + arg[1];
         442               0 :       break;
         443                 :     case PUSH_ATT_TO_GLYPH_ATTR :
         444               0 :         if (_code._constraint) return;
         445                 :     case PUSH_GLYPH_ATTR :
         446               0 :       if (arg[2] <= 0 && -arg[2] <= _analysis.slotref - _analysis.contexts[_analysis.slotref].flags.inserted)
         447               0 :         _analysis.set_ref(_analysis.slotref + arg[2] - _analysis.contexts[_analysis.slotref].flags.inserted);
         448               0 :       else if (_analysis.slotref + arg[2] > _analysis.max_ref) _analysis.max_ref = _analysis.slotref + arg[2];
         449               0 :       break;
         450                 :     case ASSOC :                // slotrefs in varargs
         451               0 :       break;
         452                 :     default:
         453               0 :         break;
         454                 :   }
         455                 : }
         456                 :
         457                 :
         458               0 : bool Machine::Code::decoder::emit_opcode(opcode opc, const byte * & bc)
         459                 : {
         460               0 :     const opcode_t * op_to_fn = Machine::getOpcodeTable();
         461               0 :     const opcode_t & op       = op_to_fn[opc];
         462               0 :     if (op.impl[_code._constraint] == 0)
         463                 :     {
         464               0 :         failure(unimplemented_opcode_used);
         465               0 :         return false;
         466                 :     }
         467                 :
         468               0 :     const size_t     param_sz = op.param_sz == VARARGS ? bc[0] + 1 : op.param_sz;
         469                 :
         470                 :     // Add this instruction
         471               0 :     *_instr++ = op.impl[_code._constraint];
         472               0 :     ++_code._instr_count;
         473                 :
         474                 :     // Grab the parameters
         475               0 :     if (param_sz) {
         476               0 :         memcpy(_data, bc, param_sz * sizeof(byte));
         477               0 :         bc               += param_sz;
         478               0 :         _data            += param_sz;
         479               0 :         _code._data_size += param_sz;
         480                 :     }
         481                 :
         482                 :     // recursively decode a context item so we can split the skip into
         483                 :     // instruction and data portions.
         484               0 :     if (opc == CNTXT_ITEM)
         485                 :     {
         486               0 :         assert(_pre_context == 0);
         487               0 :         _pre_context = _max.pre_context + int8(_data[-2]);
         488               0 :         _rule_length = _max.rule_length;
         489                 :
         490               0 :         const size_t ctxt_start = _code._instr_count;
         491               0 :         byte & instr_skip = _data[-1];
         492               0 :         byte & data_skip  = *_data++;
         493               0 :         ++_code._data_size;
         494                 :
         495               0 :         if (load(bc, bc + instr_skip))
         496                 :         {
         497               0 :             bc += instr_skip;
         498               0 :             data_skip  = instr_skip - (_code._instr_count - ctxt_start);
         499               0 :             instr_skip = _code._instr_count - ctxt_start;
         500                 :
         501               0 :             _rule_length = 1;
         502               0 :             _pre_context = 0;
         503                 :         }
         504                 :     }
         505                 :
         506               0 :     return bool(_code);
         507                 : }
         508                 :
         509                 :
         510               0 : void Machine::Code::decoder::apply_analysis(instr * const code, instr * code_end)
         511                 : {
         512                 :     // insert TEMP_COPY commands for slots that need them (that change and are referenced later)
         513               0 :     int tempcount = 0;
         514               0 :     if (_code._constraint) return;
         515                 :
         516               0 :     const instr temp_copy = Machine::getOpcodeTable()[TEMP_COPY].impl[0];
         517               0 :     for (const context * c = _analysis.contexts, * const ce = c + _analysis.slotref; c != ce; ++c)
         518                 :     {
         519               0 :         if (!c->flags.referenced || !c->flags.changed) continue;
         520                 :
         521               0 :         instr * const tip = code + c->codeRef + tempcount;
         522               0 :         memmove(tip+1, tip, (code_end - tip) * sizeof(instr));
         523               0 :         *tip = temp_copy;
         524               0 :         ++code_end;
         525               0 :         ++tempcount;
         526                 :     }
         527                 :
         528               0 :     _code._instr_count = code_end - code;
         529                 : }
         530                 :
         531                 :
         532                 : inline
         533               0 : bool Machine::Code::decoder::validate_opcode(const opcode opc, const byte * const bc)
         534                 : {
         535               0 :         if (opc >= MAX_OPCODE)
         536                 :         {
         537               0 :                 failure(invalid_opcode);
         538               0 :                 return false;
         539                 :         }
         540               0 :         const opcode_t & op = Machine::getOpcodeTable()[opc];
         541               0 :         const size_t param_sz = op.param_sz == VARARGS ? bc[0] + 1 : op.param_sz;
         542               0 :         if (bc + param_sz > _max.bytecode)
         543                 :         {
         544               0 :                 failure(arguments_exhausted);
         545               0 :                 return false;
         546                 :         }
         547               0 :         return true;
         548                 : }
         549                 :
         550                 :
         551               0 : bool Machine::Code::decoder::valid_upto(const uint16 limit, const uint16 x) const throw()
         552                 : {
         553               0 :         const bool t = x < limit;
         554               0 :     if (!t)     failure(out_of_range_data);
         555               0 :     return t;
         556                 : }
         557                 :
         558                 :
         559                 : inline
         560               0 : void Machine::Code::failure(const status_t s) throw() {
         561               0 :     release_buffers();
         562               0 :     _status = s;
         563               0 : }
         564                 :
         565                 :
         566                 : inline
         567               0 : void Machine::Code::decoder::analysis::set_ref(const int index) throw() {
         568               0 :     contexts[index].flags.referenced = true;
         569               0 :     if (index > max_ref) max_ref = index;
         570               0 : }
         571                 :
         572                 :
         573                 : inline
         574               0 : void Machine::Code::decoder::analysis::set_changed(const int index) throw() {
         575               0 :     contexts[index].flags.changed = true;
         576               0 :     if (index > max_ref) max_ref = index;
         577               0 : }
         578                 :
         579                 :
         580               0 : void Machine::Code::release_buffers() throw()
         581                 : {
         582               0 :     free(_code);
         583               0 :     free(_data);
         584               0 :     _code = 0;
         585               0 :     _data = 0;
         586               0 :     _own  = false;
         587               0 : }
         588                 :
         589                 :
         590               0 : int32 Machine::Code::run(Machine & m, slotref * & map) const
         591                 : {
         592               0 :     assert(_own);
         593               0 :     assert(*this);          // Check we are actually runnable
         594                 :
         595               0 :     if (m.slotMap().size() <= _max_ref + m.slotMap().context())
         596                 :     {
         597               0 :         m._status = Machine::slot_offset_out_bounds;
         598                 : //        return (m.slotMap().end() - map);
         599               0 :         return 1;
         600                 :     }
         601                 :
         602               0 :     return  m.run(_code, _data, map);
         603                 : }
         604                 :

Generated by: LCOV version 1.7