Line data Source code
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 : #pragma once
33 :
34 : #include <cassert>
35 : #include <graphite2/Types.h>
36 : #include "inc/Main.h"
37 : #include "inc/Machine.h"
38 :
39 : namespace graphite2 {
40 :
41 : class Silf;
42 : class Face;
43 :
44 : enum passtype {
45 : PASS_TYPE_UNKNOWN = 0,
46 : PASS_TYPE_LINEBREAK,
47 : PASS_TYPE_SUBSTITUTE,
48 : PASS_TYPE_POSITIONING,
49 : PASS_TYPE_JUSTIFICATION
50 : };
51 :
52 : namespace vm {
53 :
54 : class Machine::Code
55 : {
56 : public:
57 : enum status_t
58 : {
59 : loaded,
60 : alloc_failed,
61 : invalid_opcode,
62 : unimplemented_opcode_used,
63 : out_of_range_data,
64 : jump_past_end,
65 : arguments_exhausted,
66 : missing_return,
67 : nested_context_item,
68 : underfull_stack
69 : };
70 :
71 : private:
72 : class decoder;
73 :
74 : instr * _code;
75 : byte * _data;
76 : size_t _data_size,
77 : _instr_count;
78 : byte _max_ref;
79 : mutable status_t _status;
80 : bool _constraint,
81 : _modify,
82 : _delete;
83 : mutable bool _own;
84 :
85 : void release_buffers() throw ();
86 : void failure(const status_t) throw();
87 :
88 : public:
89 : static size_t estimateCodeDataOut(size_t num_bytecodes, int nRules, int nSlots);
90 :
91 : Code() throw();
92 : Code(bool is_constraint, const byte * bytecode_begin, const byte * const bytecode_end,
93 : uint8 pre_context, uint16 rule_length, const Silf &, const Face &,
94 : enum passtype pt, byte * * const _out = 0);
95 : Code(const Machine::Code &) throw();
96 : ~Code() throw();
97 :
98 : Code & operator=(const Code &rhs) throw();
99 0 : operator bool () const throw() { return _code && status() == loaded; }
100 0 : status_t status() const throw() { return _status; }
101 0 : bool constraint() const throw() { return _constraint; }
102 : size_t dataSize() const throw() { return _data_size; }
103 : size_t instructionCount() const throw() { return _instr_count; }
104 0 : bool immutable() const throw() { return !(_delete || _modify); }
105 0 : bool deletes() const throw() { return _delete; }
106 : size_t maxRef() const throw() { return _max_ref; }
107 : void externalProgramMoved(ptrdiff_t) throw();
108 :
109 : int32 run(Machine &m, slotref * & map) const;
110 :
111 0 : CLASS_NEW_DELETE;
112 : };
113 :
114 : inline
115 0 : size_t Machine::Code::estimateCodeDataOut(size_t n_bc, int nRules, int nSlots)
116 : {
117 : // max is: all codes are instructions + 1 for each rule + max tempcopies
118 : // allocate space for separate maximal code and data then merge them later
119 0 : return (n_bc + nRules + nSlots) * sizeof(instr) + n_bc * sizeof(byte);
120 : }
121 :
122 :
123 0 : inline Machine::Code::Code() throw()
124 : : _code(0), _data(0), _data_size(0), _instr_count(0), _max_ref(0),
125 : _status(loaded), _constraint(false), _modify(false), _delete(false),
126 0 : _own(false)
127 : {
128 0 : }
129 :
130 : inline Machine::Code::Code(const Machine::Code &obj) throw ()
131 : : _code(obj._code),
132 : _data(obj._data),
133 : _data_size(obj._data_size),
134 : _instr_count(obj._instr_count),
135 : _max_ref(obj._max_ref),
136 : _status(obj._status),
137 : _constraint(obj._constraint),
138 : _modify(obj._modify),
139 : _delete(obj._delete),
140 : _own(obj._own)
141 : {
142 : obj._own = false;
143 : }
144 :
145 0 : inline Machine::Code & Machine::Code::operator=(const Machine::Code &rhs) throw() {
146 0 : if (_instr_count > 0)
147 0 : release_buffers();
148 0 : _code = rhs._code;
149 0 : _data = rhs._data;
150 0 : _data_size = rhs._data_size;
151 0 : _instr_count = rhs._instr_count;
152 0 : _status = rhs._status;
153 0 : _constraint = rhs._constraint;
154 0 : _modify = rhs._modify;
155 0 : _delete = rhs._delete;
156 0 : _own = rhs._own;
157 0 : rhs._own = false;
158 0 : return *this;
159 : }
160 :
161 0 : inline void Machine::Code::externalProgramMoved(ptrdiff_t dist) throw()
162 : {
163 0 : if (_code && !_own)
164 : {
165 0 : _code += dist / sizeof(instr);
166 0 : _data += dist;
167 : }
168 0 : }
169 :
170 : } // namespace vm
171 : } // namespace graphite2
|