gfx/graphite2/src/inc/Machine.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /*  GRAPHITE2 LICENSING
     3     Copyright 2010, SIL International
     4     All rights reserved.
     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.
    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.
    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.
    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 general interpreter interface.
    28 // Author: Tim Eves
    30 // Build one of direct_machine.cpp or call_machine.cpp to implement this 
    31 // interface.
    33 #pragma once
    34 #include <cstring>
    35 #include <graphite2/Types.h>
    36 #include "inc/Main.h"
    38 #if defined(__GNUC__)
    39 #if defined(__clang__) || (__GNUC__ * 100 + __GNUC_MINOR__ * 10) < 430
    40 #define     HOT
    41 #if defined(__x86_64)
    42 #define     REGPARM(n)      __attribute__((regparm(n)))
    43 #else
    44 #define     REGPARM(n)
    45 #endif
    46 #else
    47 #define     HOT             __attribute__((hot))
    48 #if defined(__x86_64)
    49 #define     REGPARM(n)      __attribute__((hot, regparm(n)))
    50 #else
    51 #define     REGPARM(n)
    52 #endif
    53 #endif
    54 #else
    55 #define     HOT
    56 #define     REGPARM(n)
    57 #endif
    59 namespace graphite2 {
    61 // Forward declarations
    62 class Segment;
    63 class Slot;
    64 class SlotMap;
    67 namespace vm 
    68 {
    71 typedef void * instr;
    72 typedef Slot * slotref;
    74 enum {VARARGS = 0xff, MAX_NAME_LEN=32};
    76 enum opcode {
    77     NOP = 0,
    79     PUSH_BYTE,      PUSH_BYTEU,     PUSH_SHORT,     PUSH_SHORTU,    PUSH_LONG,
    81     ADD,            SUB,            MUL,            DIV,
    82     MIN_,           MAX_,
    83     NEG,
    84     TRUNC8,         TRUNC16,
    86     COND,
    88     AND,            OR,             NOT,
    89     EQUAL,          NOT_EQ,
    90     LESS,           GTR,            LESS_EQ,        GTR_EQ,
    92     NEXT,           NEXT_N,         COPY_NEXT,
    93     PUT_GLYPH_8BIT_OBS,              PUT_SUBS_8BIT_OBS,   PUT_COPY,
    94     INSERT,         DELETE,
    95     ASSOC,
    96     CNTXT_ITEM,
    98     ATTR_SET,       ATTR_ADD,       ATTR_SUB,
    99     ATTR_SET_SLOT,
   100     IATTR_SET_SLOT,
   101     PUSH_SLOT_ATTR,                 PUSH_GLYPH_ATTR_OBS,
   102     PUSH_GLYPH_METRIC,              PUSH_FEAT,
   103     PUSH_ATT_TO_GATTR_OBS,          PUSH_ATT_TO_GLYPH_METRIC,
   104     PUSH_ISLOT_ATTR,
   106     PUSH_IGLYPH_ATTR,    // not implemented
   108     POP_RET,                        RET_ZERO,           RET_TRUE,
   109     IATTR_SET,                      IATTR_ADD,          IATTR_SUB,
   110     PUSH_PROC_STATE,                PUSH_VERSION,
   111     PUT_SUBS,                       PUT_SUBS2,          PUT_SUBS3,
   112     PUT_GLYPH,                      PUSH_GLYPH_ATTR,    PUSH_ATT_TO_GLYPH_ATTR,
   113     MAX_OPCODE,
   114     // private opcodes for internal use only, comes after all other on disk opcodes
   115     TEMP_COPY = MAX_OPCODE
   116 };
   118 struct opcode_t 
   119 {
   120     instr           impl[2];
   121     uint8           param_sz;
   122     char            name[MAX_NAME_LEN];
   123 };
   126 class Machine
   127 {
   128 public:
   129     typedef int32  stack_t;
   130     static size_t const STACK_ORDER  = 10,
   131                         STACK_MAX    = 1 << STACK_ORDER,
   132                         STACK_GUARD  = 2;
   134     class Code;
   136     enum status_t {
   137         finished = 0,
   138         stack_underflow,
   139         stack_not_empty,
   140         stack_overflow,
   141         slot_offset_out_bounds
   142     };
   144     Machine(SlotMap &) throw();
   145     static const opcode_t *   getOpcodeTable() throw();
   147     CLASS_NEW_DELETE;
   149     SlotMap   & slotMap() const throw();
   150     status_t    status() const throw();
   151     operator bool () const throw();
   153 private:
   154     void    check_final_stack(const stack_t * const sp);
   155     stack_t run(const instr * program, const byte * data,
   156                 slotref * & map) HOT;
   158     SlotMap       & _map;
   159     stack_t         _stack[STACK_MAX + 2*STACK_GUARD];
   160     status_t        _status;
   161 };
   163 inline Machine::Machine(SlotMap & map) throw()
   164 : _map(map), _status(finished)
   165 {
   166     // Initialise stack guard +1 entries as the stack pointer points to the
   167     //  current top of stack, hence the first push will never write entry 0.
   168     // Initialising the guard space like this is unnecessary and is only
   169     //  done to keep valgrind happy during fuzz testing.  Hopefully loop
   170     //  unrolling will flatten this.
   171     for (size_t n = STACK_GUARD + 1; n; --n)  _stack[n-1] = 0;
   172 }
   174 inline SlotMap& Machine::slotMap() const throw()
   175 {
   176     return _map;
   177 }
   179 inline Machine::status_t Machine::status() const throw()
   180 {
   181     return _status;
   182 }
   184 inline void Machine::check_final_stack(const int32 * const sp)
   185 {
   186     stack_t const * const base  = _stack + STACK_GUARD,
   187                   * const limit = base + STACK_MAX;
   188     if      (sp <  base)    _status = stack_underflow;       // This should be impossible now.
   189     else if (sp >= limit)   _status = stack_overflow;        // So should this.
   190     else if (sp != base)    _status = stack_not_empty;
   191 }
   193 } // namespace vm
   194 } // namespace graphite2

mercurial