Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | /* GRAPHITE2 LICENSING |
michael@0 | 2 | |
michael@0 | 3 | Copyright 2010, SIL International |
michael@0 | 4 | All rights reserved. |
michael@0 | 5 | |
michael@0 | 6 | This library is free software; you can redistribute it and/or modify |
michael@0 | 7 | it under the terms of the GNU Lesser General Public License as published |
michael@0 | 8 | by the Free Software Foundation; either version 2.1 of License, or |
michael@0 | 9 | (at your option) any later version. |
michael@0 | 10 | |
michael@0 | 11 | This program is distributed in the hope that it will be useful, |
michael@0 | 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
michael@0 | 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
michael@0 | 14 | Lesser General Public License for more details. |
michael@0 | 15 | |
michael@0 | 16 | You should also have received a copy of the GNU Lesser General Public |
michael@0 | 17 | License along with this library in the file named "LICENSE". |
michael@0 | 18 | If not, write to the Free Software Foundation, 51 Franklin Street, |
michael@0 | 19 | Suite 500, Boston, MA 02110-1335, USA or visit their web page on the |
michael@0 | 20 | internet at http://www.fsf.org/licenses/lgpl.html. |
michael@0 | 21 | |
michael@0 | 22 | Alternatively, the contents of this file may be used under the terms of the |
michael@0 | 23 | Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public |
michael@0 | 24 | License, as published by the Free Software Foundation, either version 2 |
michael@0 | 25 | of the License or (at your option) any later version. |
michael@0 | 26 | */ |
michael@0 | 27 | // This direct threaded interpreter implmentation for machine.h |
michael@0 | 28 | // Author: Tim Eves |
michael@0 | 29 | |
michael@0 | 30 | // Build either this interpreter or the call_machine implementation. |
michael@0 | 31 | // The direct threaded interpreter is relies upon a gcc feature called |
michael@0 | 32 | // labels-as-values so is only portable to compilers that support the |
michael@0 | 33 | // extension (gcc only as far as I know) however it should build on any |
michael@0 | 34 | // architecture gcc supports. |
michael@0 | 35 | // This is twice as fast as the call threaded model and is likely faster on |
michael@0 | 36 | // inorder processors with short pipelines and little branch prediction such |
michael@0 | 37 | // as the ARM and possibly Atom chips. |
michael@0 | 38 | |
michael@0 | 39 | |
michael@0 | 40 | #include <cassert> |
michael@0 | 41 | #include <cstring> |
michael@0 | 42 | #include "inc/Machine.h" |
michael@0 | 43 | #include "inc/Segment.h" |
michael@0 | 44 | #include "inc/Slot.h" |
michael@0 | 45 | #include "inc/Rule.h" |
michael@0 | 46 | |
michael@0 | 47 | #define STARTOP(name) name: { |
michael@0 | 48 | #define ENDOP }; goto *((sp - sb)/Machine::STACK_MAX ? &&end : *++ip); |
michael@0 | 49 | #define EXIT(status) { push(status); goto end; } |
michael@0 | 50 | |
michael@0 | 51 | #define do_(name) &&name |
michael@0 | 52 | |
michael@0 | 53 | |
michael@0 | 54 | using namespace graphite2; |
michael@0 | 55 | using namespace vm; |
michael@0 | 56 | |
michael@0 | 57 | namespace { |
michael@0 | 58 | |
michael@0 | 59 | const void * direct_run(const bool get_table_mode, |
michael@0 | 60 | const instr * program, |
michael@0 | 61 | const byte * data, |
michael@0 | 62 | Machine::stack_t * stack, |
michael@0 | 63 | slotref * & __map, |
michael@0 | 64 | SlotMap * __smap=0) |
michael@0 | 65 | { |
michael@0 | 66 | // We need to define and return to opcode table from within this function |
michael@0 | 67 | // other inorder to take the addresses of the instruction bodies. |
michael@0 | 68 | #include "inc/opcode_table.h" |
michael@0 | 69 | if (get_table_mode) |
michael@0 | 70 | return opcode_table; |
michael@0 | 71 | |
michael@0 | 72 | // Declare virtual machine registers |
michael@0 | 73 | const instr * ip = program; |
michael@0 | 74 | const byte * dp = data; |
michael@0 | 75 | Machine::stack_t * sp = stack + Machine::STACK_GUARD, |
michael@0 | 76 | * const sb = sp; |
michael@0 | 77 | SlotMap & smap = *__smap; |
michael@0 | 78 | Segment & seg = smap.segment; |
michael@0 | 79 | slotref is = *__map, |
michael@0 | 80 | * map = __map, |
michael@0 | 81 | * const mapb = smap.begin()+smap.context(); |
michael@0 | 82 | int8 flags = 0; |
michael@0 | 83 | |
michael@0 | 84 | // start the program |
michael@0 | 85 | goto **ip; |
michael@0 | 86 | |
michael@0 | 87 | // Pull in the opcode definitions |
michael@0 | 88 | #include "inc/opcodes.h" |
michael@0 | 89 | |
michael@0 | 90 | end: |
michael@0 | 91 | __map = map; |
michael@0 | 92 | *__map = is; |
michael@0 | 93 | return sp; |
michael@0 | 94 | } |
michael@0 | 95 | |
michael@0 | 96 | } |
michael@0 | 97 | |
michael@0 | 98 | const opcode_t * Machine::getOpcodeTable() throw() |
michael@0 | 99 | { |
michael@0 | 100 | slotref * dummy; |
michael@0 | 101 | return static_cast<const opcode_t *>(direct_run(true, 0, 0, 0, dummy, 0)); |
michael@0 | 102 | } |
michael@0 | 103 | |
michael@0 | 104 | |
michael@0 | 105 | Machine::stack_t Machine::run(const instr * program, |
michael@0 | 106 | const byte * data, |
michael@0 | 107 | slotref * & is) |
michael@0 | 108 | { |
michael@0 | 109 | assert(program != 0); |
michael@0 | 110 | |
michael@0 | 111 | const stack_t *sp = static_cast<const stack_t *>( |
michael@0 | 112 | direct_run(false, program, data, _stack, is, &_map)); |
michael@0 | 113 | const stack_t ret = sp == _stack+STACK_GUARD+1 ? *sp-- : 0; |
michael@0 | 114 | check_final_stack(sp); |
michael@0 | 115 | return ret; |
michael@0 | 116 | } |
michael@0 | 117 |