1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/graphite2/src/Code.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,619 @@ 1.4 +/* GRAPHITE2 LICENSING 1.5 + 1.6 + Copyright 2010, SIL International 1.7 + All rights reserved. 1.8 + 1.9 + This library is free software; you can redistribute it and/or modify 1.10 + it under the terms of the GNU Lesser General Public License as published 1.11 + by the Free Software Foundation; either version 2.1 of License, or 1.12 + (at your option) any later version. 1.13 + 1.14 + This program is distributed in the hope that it will be useful, 1.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of 1.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1.17 + Lesser General Public License for more details. 1.18 + 1.19 + You should also have received a copy of the GNU Lesser General Public 1.20 + License along with this library in the file named "LICENSE". 1.21 + If not, write to the Free Software Foundation, 51 Franklin Street, 1.22 + Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 1.23 + internet at http://www.fsf.org/licenses/lgpl.html. 1.24 + 1.25 +Alternatively, the contents of this file may be used under the terms of the 1.26 +Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public 1.27 +License, as published by the Free Software Foundation, either version 2 1.28 +of the License or (at your option) any later version. 1.29 +*/ 1.30 +// This class represents loaded graphite stack machine code. It performs 1.31 +// basic sanity checks, on the incoming code to prevent more obvious problems 1.32 +// from crashing graphite. 1.33 +// Author: Tim Eves 1.34 + 1.35 +#include <cassert> 1.36 +#include <cstddef> 1.37 +#include <cstdlib> 1.38 +#include <cstring> 1.39 +#include "graphite2/Segment.h" 1.40 +#include "inc/Code.h" 1.41 +#include "inc/Face.h" 1.42 +#include "inc/GlyphFace.h" 1.43 +#include "inc/GlyphCache.h" 1.44 +#include "inc/Machine.h" 1.45 +#include "inc/Rule.h" 1.46 +#include "inc/Silf.h" 1.47 + 1.48 +#include <stdio.h> 1.49 + 1.50 +#ifdef NDEBUG 1.51 +#ifdef __GNUC__ 1.52 +#pragma GCC diagnostic ignored "-Wunused-parameter" 1.53 +#endif 1.54 +#endif 1.55 + 1.56 + 1.57 +using namespace graphite2; 1.58 +using namespace vm; 1.59 + 1.60 +namespace { 1.61 + 1.62 +inline bool is_return(const instr i) { 1.63 + const opcode_t * opmap = Machine::getOpcodeTable(); 1.64 + const instr pop_ret = *opmap[POP_RET].impl, 1.65 + ret_zero = *opmap[RET_ZERO].impl, 1.66 + ret_true = *opmap[RET_TRUE].impl; 1.67 + return i == pop_ret || i == ret_zero || i == ret_true; 1.68 +} 1.69 + 1.70 +struct context 1.71 +{ 1.72 + context(uint8 ref=0) : codeRef(ref) {flags.changed=false; flags.referenced=false; flags.inserted=false;} 1.73 + struct { 1.74 + uint8 changed:1, 1.75 + referenced:1, 1.76 + inserted:1; 1.77 + } flags; 1.78 + uint8 codeRef; 1.79 +}; 1.80 + 1.81 +} // end namespace 1.82 + 1.83 + 1.84 +class Machine::Code::decoder 1.85 +{ 1.86 +public: 1.87 + struct limits; 1.88 + struct analysis 1.89 + { 1.90 + uint8 slotref; 1.91 + context contexts[256]; 1.92 + byte max_ref; 1.93 + 1.94 + analysis() : slotref(0), max_ref(0) {}; 1.95 + void set_ref(int index) throw(); 1.96 + void set_changed(int index) throw(); 1.97 + 1.98 + }; 1.99 + 1.100 + decoder(const limits & lims, Code &code) throw(); 1.101 + 1.102 + bool load(const byte * bc_begin, const byte * bc_end); 1.103 + void apply_analysis(instr * const code, instr * code_end); 1.104 + byte max_ref() { return _analysis.max_ref; } 1.105 + int pre_context() const { return _pre_context; } 1.106 + 1.107 +private: 1.108 + opcode fetch_opcode(const byte * bc); 1.109 + void analyse_opcode(const opcode, const int8 * const dp) throw(); 1.110 + bool emit_opcode(opcode opc, const byte * & bc); 1.111 + bool validate_opcode(const opcode opc, const byte * const bc); 1.112 + bool valid_upto(const uint16 limit, const uint16 x) const throw(); 1.113 + void failure(const status_t s) const throw() { _code.failure(s); } 1.114 + 1.115 + Code & _code; 1.116 + int _pre_context; 1.117 + uint16 _rule_length; 1.118 + instr * _instr; 1.119 + byte * _data; 1.120 + const limits & _max; 1.121 + analysis _analysis; 1.122 +}; 1.123 + 1.124 + 1.125 +struct Machine::Code::decoder::limits 1.126 +{ 1.127 + const byte * const bytecode; 1.128 + const uint8 pre_context; 1.129 + const uint16 rule_length, 1.130 + classes, 1.131 + glyf_attrs, 1.132 + features; 1.133 + const byte attrid[gr_slatMax]; 1.134 +}; 1.135 + 1.136 +inline Machine::Code::decoder::decoder(const limits & lims, Code &code) throw() 1.137 +: _code(code), 1.138 + _pre_context(code._constraint ? 0 : lims.pre_context), 1.139 + _rule_length(code._constraint ? 1 : lims.rule_length), 1.140 + _instr(code._code), _data(code._data), _max(lims) 1.141 +{ } 1.142 + 1.143 + 1.144 + 1.145 +Machine::Code::Code(bool is_constraint, const byte * bytecode_begin, const byte * const bytecode_end, 1.146 + uint8 pre_context, uint16 rule_length, const Silf & silf, const Face & face) 1.147 + : _code(0), _data(0), _data_size(0), _instr_count(0), _max_ref(0), _status(loaded), 1.148 + _constraint(is_constraint), _modify(false), _delete(false), _own(true) 1.149 +{ 1.150 +#ifdef GRAPHITE2_TELEMETRY 1.151 + telemetry::category _code_cat(face.tele.code); 1.152 +#endif 1.153 + assert(bytecode_begin != 0); 1.154 + if (bytecode_begin == bytecode_end) 1.155 + { 1.156 + ::new (this) Code(); 1.157 + return; 1.158 + } 1.159 + assert(bytecode_end > bytecode_begin); 1.160 + const opcode_t * op_to_fn = Machine::getOpcodeTable(); 1.161 + 1.162 + // Allocate code and dat target buffers, these sizes are a worst case 1.163 + // estimate. Once we know their real sizes the we'll shrink them. 1.164 + _code = static_cast<instr *>(malloc((bytecode_end - bytecode_begin) 1.165 + * sizeof(instr))); 1.166 + _data = static_cast<byte *>(malloc((bytecode_end - bytecode_begin) 1.167 + * sizeof(byte))); 1.168 + 1.169 + if (!_code || !_data) { 1.170 + failure(alloc_failed); 1.171 + return; 1.172 + } 1.173 + 1.174 + const decoder::limits lims = { 1.175 + bytecode_end, 1.176 + pre_context, 1.177 + rule_length, 1.178 + silf.numClasses(), 1.179 + face.glyphs().numAttrs(), 1.180 + face.numFeatures(), 1.181 + {1,1,1,1,1,1,1,1, 1.182 + 1,1,1,1,1,1,1,255, 1.183 + 1,1,1,1,1,1,1,1, 1.184 + 1,1,1,1,1,1,0,0, 1.185 + 0,0,0,0,0,0,0,0, 1.186 + 0,0,0,0,0,0,0,0, 1.187 + 0,0,0,0,0,0,0, silf.numUser()} 1.188 + }; 1.189 + 1.190 + decoder dec(lims, *this); 1.191 + if(!dec.load(bytecode_begin, bytecode_end)) 1.192 + return; 1.193 + 1.194 + // Is this an empty program? 1.195 + if (_instr_count == 0) 1.196 + { 1.197 + release_buffers(); 1.198 + ::new (this) Code(); 1.199 + return; 1.200 + } 1.201 + 1.202 + // When we reach the end check we've terminated it correctly 1.203 + if (!is_return(_code[_instr_count-1])) { 1.204 + failure(missing_return); 1.205 + return; 1.206 + } 1.207 + 1.208 + assert((_constraint && immutable()) || !_constraint); 1.209 + dec.apply_analysis(_code, _code + _instr_count); 1.210 + _max_ref = dec.max_ref(); 1.211 + 1.212 + // Now we know exactly how much code and data the program really needs 1.213 + // realloc the buffers to exactly the right size so we don't waste any 1.214 + // memory. 1.215 + assert((bytecode_end - bytecode_begin) >= std::ptrdiff_t(_instr_count)); 1.216 + assert((bytecode_end - bytecode_begin) >= std::ptrdiff_t(_data_size)); 1.217 + _code = static_cast<instr *>(realloc(_code, (_instr_count+1)*sizeof(instr))); 1.218 + _data = static_cast<byte *>(realloc(_data, _data_size*sizeof(byte))); 1.219 + 1.220 + if (!_code) 1.221 + { 1.222 + failure(alloc_failed); 1.223 + return; 1.224 + } 1.225 + 1.226 + // Make this RET_ZERO, we should never reach this but just in case ... 1.227 + _code[_instr_count] = op_to_fn[RET_ZERO].impl[_constraint]; 1.228 + 1.229 +#ifdef GRAPHITE2_TELEMETRY 1.230 + telemetry::count_bytes(_data_size + (_instr_count+1)*sizeof(instr)); 1.231 +#endif 1.232 +} 1.233 + 1.234 +Machine::Code::~Code() throw () 1.235 +{ 1.236 + if (_own) 1.237 + release_buffers(); 1.238 +} 1.239 + 1.240 + 1.241 +bool Machine::Code::decoder::load(const byte * bc, const byte * bc_end) 1.242 +{ 1.243 + while (bc < bc_end) 1.244 + { 1.245 + const opcode opc = fetch_opcode(bc++); 1.246 + if (opc == vm::MAX_OPCODE) 1.247 + return false; 1.248 + 1.249 + analyse_opcode(opc, reinterpret_cast<const int8 *>(bc)); 1.250 + 1.251 + if (!emit_opcode(opc, bc)) 1.252 + return false; 1.253 + } 1.254 + 1.255 + return bool(_code); 1.256 +} 1.257 + 1.258 +// Validation check and fixups. 1.259 +// 1.260 + 1.261 +opcode Machine::Code::decoder::fetch_opcode(const byte * bc) 1.262 +{ 1.263 + const opcode opc = opcode(*bc++); 1.264 + 1.265 + // Do some basic sanity checks based on what we know about the opcode 1.266 + if (!validate_opcode(opc, bc)) return MAX_OPCODE; 1.267 + 1.268 + // And check it's arguments as far as possible 1.269 + switch (opc) 1.270 + { 1.271 + case NOP : 1.272 + case PUSH_BYTE : 1.273 + case PUSH_BYTEU : 1.274 + case PUSH_SHORT : 1.275 + case PUSH_SHORTU : 1.276 + case PUSH_LONG : 1.277 + case ADD : 1.278 + case SUB : 1.279 + case MUL : 1.280 + case DIV : 1.281 + case MIN_ : 1.282 + case MAX_ : 1.283 + case NEG : 1.284 + case TRUNC8 : 1.285 + case TRUNC16 : 1.286 + case COND : 1.287 + case AND : 1.288 + case OR : 1.289 + case NOT : 1.290 + case EQUAL : 1.291 + case NOT_EQ : 1.292 + case LESS : 1.293 + case GTR : 1.294 + case LESS_EQ : 1.295 + case GTR_EQ : 1.296 + break; 1.297 + case NEXT : 1.298 + case NEXT_N : // runtime checked 1.299 + case COPY_NEXT : 1.300 + ++_pre_context; 1.301 + break; 1.302 + case PUT_GLYPH_8BIT_OBS : 1.303 + valid_upto(_max.classes, bc[0]); 1.304 + break; 1.305 + case PUT_SUBS_8BIT_OBS : 1.306 + valid_upto(_rule_length, _pre_context + int8(bc[0])); 1.307 + valid_upto(_max.classes, bc[1]); 1.308 + valid_upto(_max.classes, bc[2]); 1.309 + break; 1.310 + case PUT_COPY : 1.311 + valid_upto(_rule_length, _pre_context + int8(bc[0])); 1.312 + break; 1.313 + case INSERT : 1.314 + --_pre_context; 1.315 + break; 1.316 + case DELETE : 1.317 + break; 1.318 + case ASSOC : 1.319 + for (uint8 num = bc[0]; num; --num) 1.320 + valid_upto(_rule_length, _pre_context + int8(bc[num])); 1.321 + break; 1.322 + case CNTXT_ITEM : 1.323 + valid_upto(_max.rule_length, _max.pre_context + int8(bc[0])); 1.324 + if (bc + 2 + bc[1] >= _max.bytecode) failure(jump_past_end); 1.325 + if (_pre_context != 0) failure(nested_context_item); 1.326 + break; 1.327 + case ATTR_SET : 1.328 + case ATTR_ADD : 1.329 + case ATTR_SUB : 1.330 + case ATTR_SET_SLOT : 1.331 + valid_upto(gr_slatMax, bc[0]); 1.332 + break; 1.333 + case IATTR_SET_SLOT : 1.334 + if (valid_upto(gr_slatMax, bc[0])) 1.335 + valid_upto(_max.attrid[bc[0]], bc[1]); 1.336 + break; 1.337 + case PUSH_SLOT_ATTR : 1.338 + valid_upto(gr_slatMax, bc[0]); 1.339 + valid_upto(_rule_length, _pre_context + int8(bc[1])); 1.340 + break; 1.341 + case PUSH_GLYPH_ATTR_OBS : 1.342 + valid_upto(_max.glyf_attrs, bc[0]); 1.343 + valid_upto(_rule_length, _pre_context + int8(bc[1])); 1.344 + break; 1.345 + case PUSH_GLYPH_METRIC : 1.346 + valid_upto(kgmetDescent, bc[0]); 1.347 + valid_upto(_rule_length, _pre_context + int8(bc[1])); 1.348 + // level: dp[2] no check necessary 1.349 + break; 1.350 + case PUSH_FEAT : 1.351 + valid_upto(_max.features, bc[0]); 1.352 + valid_upto(_rule_length, _pre_context + int8(bc[1])); 1.353 + break; 1.354 + case PUSH_ATT_TO_GATTR_OBS : 1.355 + valid_upto(_max.glyf_attrs, bc[0]); 1.356 + valid_upto(_rule_length, _pre_context + int8(bc[1])); 1.357 + break; 1.358 + case PUSH_ATT_TO_GLYPH_METRIC : 1.359 + valid_upto(kgmetDescent, bc[0]); 1.360 + valid_upto(_rule_length, _pre_context + int8(bc[1])); 1.361 + // level: dp[2] no check necessary 1.362 + break; 1.363 + case PUSH_ISLOT_ATTR : 1.364 + if (valid_upto(gr_slatMax, bc[0])) 1.365 + { 1.366 + valid_upto(_rule_length, _pre_context + int8(bc[1])); 1.367 + valid_upto(_max.attrid[bc[0]], bc[2]); 1.368 + } 1.369 + break; 1.370 + case PUSH_IGLYPH_ATTR :// not implemented 1.371 + case POP_RET : 1.372 + case RET_ZERO : 1.373 + case RET_TRUE : 1.374 + break; 1.375 + case IATTR_SET : 1.376 + case IATTR_ADD : 1.377 + case IATTR_SUB : 1.378 + if (valid_upto(gr_slatMax, bc[0])) 1.379 + valid_upto(_max.attrid[bc[0]], bc[1]); 1.380 + break; 1.381 + case PUSH_PROC_STATE : // dummy: dp[0] no check necessary 1.382 + case PUSH_VERSION : 1.383 + break; 1.384 + case PUT_SUBS : 1.385 + valid_upto(_rule_length, _pre_context + int8(bc[0])); 1.386 + valid_upto(_max.classes, uint16(bc[1]<< 8) | bc[2]); 1.387 + valid_upto(_max.classes, uint16(bc[3]<< 8) | bc[4]); 1.388 + break; 1.389 + case PUT_SUBS2 : // not implemented 1.390 + case PUT_SUBS3 : // not implemented 1.391 + break; 1.392 + case PUT_GLYPH : 1.393 + valid_upto(_max.classes, uint16(bc[0]<< 8) | bc[1]); 1.394 + break; 1.395 + case PUSH_GLYPH_ATTR : 1.396 + case PUSH_ATT_TO_GLYPH_ATTR : 1.397 + valid_upto(_max.glyf_attrs, uint16(bc[0]<< 8) | bc[1]); 1.398 + valid_upto(_rule_length, _pre_context + int8(bc[2])); 1.399 + break; 1.400 + default: 1.401 + failure(invalid_opcode); 1.402 + break; 1.403 + } 1.404 + 1.405 + return bool(_code) ? opc : MAX_OPCODE; 1.406 +} 1.407 + 1.408 + 1.409 +void Machine::Code::decoder::analyse_opcode(const opcode opc, const int8 * arg) throw() 1.410 +{ 1.411 + if (_code._constraint) return; 1.412 + 1.413 + switch (opc) 1.414 + { 1.415 + case DELETE : 1.416 + _code._delete = true; 1.417 + break; 1.418 + case PUT_GLYPH_8BIT_OBS : 1.419 + case PUT_GLYPH : 1.420 + _code._modify = true; 1.421 + _analysis.set_changed(_analysis.slotref); 1.422 + break; 1.423 + case NEXT : 1.424 + case COPY_NEXT : 1.425 + if (!_analysis.contexts[_analysis.slotref].flags.inserted) 1.426 + ++_analysis.slotref; 1.427 + _analysis.contexts[_analysis.slotref] = context(_code._instr_count+1); 1.428 + if (_analysis.slotref > _analysis.max_ref) _analysis.max_ref = _analysis.slotref; 1.429 + break; 1.430 + case INSERT : 1.431 + _analysis.contexts[_analysis.slotref].flags.inserted = true; 1.432 + _code._modify = true; 1.433 + break; 1.434 + case PUT_SUBS_8BIT_OBS : // slotref on 1st parameter 1.435 + case PUT_SUBS : 1.436 + _code._modify = true; 1.437 + _analysis.set_changed(_analysis.slotref); 1.438 + // no break 1.439 + case PUT_COPY : 1.440 + { 1.441 + if (arg[0] != 0) { _analysis.set_changed(_analysis.slotref); _code._modify = true; } 1.442 + if (arg[0] <= 0 && -arg[0] <= _analysis.slotref - _analysis.contexts[_analysis.slotref].flags.inserted) 1.443 + _analysis.set_ref(_analysis.slotref + arg[0] - _analysis.contexts[_analysis.slotref].flags.inserted); 1.444 + else if (_analysis.slotref + arg[0] > _analysis.max_ref) _analysis.max_ref = _analysis.slotref + arg[0]; 1.445 + break; 1.446 + } 1.447 + case PUSH_ATT_TO_GATTR_OBS : // slotref on 2nd parameter 1.448 + if (_code._constraint) return; 1.449 + // no break 1.450 + case PUSH_GLYPH_ATTR_OBS : 1.451 + case PUSH_SLOT_ATTR : 1.452 + case PUSH_GLYPH_METRIC : 1.453 + case PUSH_ATT_TO_GLYPH_METRIC : 1.454 + case PUSH_ISLOT_ATTR : 1.455 + case PUSH_FEAT : 1.456 + if (arg[1] <= 0 && -arg[1] <= _analysis.slotref - _analysis.contexts[_analysis.slotref].flags.inserted) 1.457 + _analysis.set_ref(_analysis.slotref + arg[1] - _analysis.contexts[_analysis.slotref].flags.inserted); 1.458 + else if (_analysis.slotref + arg[1] > _analysis.max_ref) _analysis.max_ref = _analysis.slotref + arg[1]; 1.459 + break; 1.460 + case PUSH_ATT_TO_GLYPH_ATTR : 1.461 + if (_code._constraint) return; 1.462 + // no break 1.463 + case PUSH_GLYPH_ATTR : 1.464 + if (arg[2] <= 0 && -arg[2] <= _analysis.slotref - _analysis.contexts[_analysis.slotref].flags.inserted) 1.465 + _analysis.set_ref(_analysis.slotref + arg[2] - _analysis.contexts[_analysis.slotref].flags.inserted); 1.466 + else if (_analysis.slotref + arg[2] > _analysis.max_ref) _analysis.max_ref = _analysis.slotref + arg[2]; 1.467 + break; 1.468 + case ASSOC : // slotrefs in varargs 1.469 + break; 1.470 + default: 1.471 + break; 1.472 + } 1.473 +} 1.474 + 1.475 + 1.476 +bool Machine::Code::decoder::emit_opcode(opcode opc, const byte * & bc) 1.477 +{ 1.478 + const opcode_t * op_to_fn = Machine::getOpcodeTable(); 1.479 + const opcode_t & op = op_to_fn[opc]; 1.480 + if (op.impl[_code._constraint] == 0) 1.481 + { 1.482 + failure(unimplemented_opcode_used); 1.483 + return false; 1.484 + } 1.485 + 1.486 + const size_t param_sz = op.param_sz == VARARGS ? bc[0] + 1 : op.param_sz; 1.487 + 1.488 + // Add this instruction 1.489 + *_instr++ = op.impl[_code._constraint]; 1.490 + ++_code._instr_count; 1.491 + 1.492 + // Grab the parameters 1.493 + if (param_sz) { 1.494 + memcpy(_data, bc, param_sz * sizeof(byte)); 1.495 + bc += param_sz; 1.496 + _data += param_sz; 1.497 + _code._data_size += param_sz; 1.498 + } 1.499 + 1.500 + // recursively decode a context item so we can split the skip into 1.501 + // instruction and data portions. 1.502 + if (opc == CNTXT_ITEM) 1.503 + { 1.504 + assert(_pre_context == 0); 1.505 + _pre_context = _max.pre_context + int8(_data[-2]); 1.506 + _rule_length = _max.rule_length; 1.507 + 1.508 + const size_t ctxt_start = _code._instr_count; 1.509 + byte & instr_skip = _data[-1]; 1.510 + byte & data_skip = *_data++; 1.511 + ++_code._data_size; 1.512 + 1.513 + if (load(bc, bc + instr_skip)) 1.514 + { 1.515 + bc += instr_skip; 1.516 + data_skip = instr_skip - (_code._instr_count - ctxt_start); 1.517 + instr_skip = _code._instr_count - ctxt_start; 1.518 + 1.519 + _rule_length = 1; 1.520 + _pre_context = 0; 1.521 + } 1.522 + } 1.523 + 1.524 + return bool(_code); 1.525 +} 1.526 + 1.527 + 1.528 +void Machine::Code::decoder::apply_analysis(instr * const code, instr * code_end) 1.529 +{ 1.530 + // insert TEMP_COPY commands for slots that need them (that change and are referenced later) 1.531 + int tempcount = 0; 1.532 + if (_code._constraint) return; 1.533 + 1.534 + const instr temp_copy = Machine::getOpcodeTable()[TEMP_COPY].impl[0]; 1.535 + for (const context * c = _analysis.contexts, * const ce = c + _analysis.slotref; c != ce; ++c) 1.536 + { 1.537 + if (!c->flags.referenced || !c->flags.changed) continue; 1.538 + 1.539 + instr * const tip = code + c->codeRef + tempcount; 1.540 + memmove(tip+1, tip, (code_end - tip) * sizeof(instr)); 1.541 + *tip = temp_copy; 1.542 + ++code_end; 1.543 + ++tempcount; 1.544 + } 1.545 + 1.546 + _code._instr_count = code_end - code; 1.547 +} 1.548 + 1.549 + 1.550 +inline 1.551 +bool Machine::Code::decoder::validate_opcode(const opcode opc, const byte * const bc) 1.552 +{ 1.553 + if (opc >= MAX_OPCODE) 1.554 + { 1.555 + failure(invalid_opcode); 1.556 + return false; 1.557 + } 1.558 + const opcode_t & op = Machine::getOpcodeTable()[opc]; 1.559 + const size_t param_sz = op.param_sz == VARARGS ? bc[0] + 1 : op.param_sz; 1.560 + if (bc + param_sz > _max.bytecode) 1.561 + { 1.562 + failure(arguments_exhausted); 1.563 + return false; 1.564 + } 1.565 + return true; 1.566 +} 1.567 + 1.568 + 1.569 +bool Machine::Code::decoder::valid_upto(const uint16 limit, const uint16 x) const throw() 1.570 +{ 1.571 + const bool t = x < limit; 1.572 + if (!t) failure(out_of_range_data); 1.573 + return t; 1.574 +} 1.575 + 1.576 + 1.577 +inline 1.578 +void Machine::Code::failure(const status_t s) throw() { 1.579 + release_buffers(); 1.580 + _status = s; 1.581 +} 1.582 + 1.583 + 1.584 +inline 1.585 +void Machine::Code::decoder::analysis::set_ref(const int index) throw() { 1.586 + contexts[index].flags.referenced = true; 1.587 + if (index > max_ref) max_ref = index; 1.588 +} 1.589 + 1.590 + 1.591 +inline 1.592 +void Machine::Code::decoder::analysis::set_changed(const int index) throw() { 1.593 + contexts[index].flags.changed = true; 1.594 + if (index > max_ref) max_ref = index; 1.595 +} 1.596 + 1.597 + 1.598 +void Machine::Code::release_buffers() throw() 1.599 +{ 1.600 + free(_code); 1.601 + free(_data); 1.602 + _code = 0; 1.603 + _data = 0; 1.604 + _own = false; 1.605 +} 1.606 + 1.607 + 1.608 +int32 Machine::Code::run(Machine & m, slotref * & map) const 1.609 +{ 1.610 + assert(_own); 1.611 + assert(*this); // Check we are actually runnable 1.612 + 1.613 + if (m.slotMap().size() <= size_t(_max_ref + m.slotMap().context())) 1.614 + { 1.615 + m._status = Machine::slot_offset_out_bounds; 1.616 +// return (m.slotMap().end() - map); 1.617 + return 1; 1.618 + } 1.619 + 1.620 + return m.run(_code, _data, map); 1.621 +} 1.622 +