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