js/src/jit/CompactBuffer.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/jit/CompactBuffer.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,166 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99:
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#ifndef jit_Compactbuffer_h
    1.11 +#define jit_Compactbuffer_h
    1.12 +
    1.13 +#include "jsalloc.h"
    1.14 +
    1.15 +#include "jit/IonTypes.h"
    1.16 +#include "js/Vector.h"
    1.17 +
    1.18 +namespace js {
    1.19 +namespace jit {
    1.20 +
    1.21 +class CompactBufferWriter;
    1.22 +
    1.23 +// CompactBuffers are byte streams designed for compressable integers. It has
    1.24 +// helper functions for writing bytes, fixed-size integers, and variable-sized
    1.25 +// integers. Variable sized integers are encoded in 1-5 bytes, each byte
    1.26 +// containing 7 bits of the integer and a bit which specifies whether the next
    1.27 +// byte is also part of the integer.
    1.28 +//
    1.29 +// Fixed-width integers are also available, in case the actual value will not
    1.30 +// be known until later.
    1.31 +
    1.32 +class CompactBufferReader
    1.33 +{
    1.34 +    const uint8_t *buffer_;
    1.35 +    const uint8_t *end_;
    1.36 +
    1.37 +    uint32_t readVariableLength() {
    1.38 +        uint32_t val = 0;
    1.39 +        uint32_t shift = 0;
    1.40 +        uint8_t byte;
    1.41 +        while (true) {
    1.42 +            JS_ASSERT(shift < 32);
    1.43 +            byte = readByte();
    1.44 +            val |= (uint32_t(byte) >> 1) << shift;
    1.45 +            shift += 7;
    1.46 +            if (!(byte & 1))
    1.47 +                return val;
    1.48 +        }
    1.49 +        MOZ_ASSUME_UNREACHABLE("unreachable");
    1.50 +    }
    1.51 +
    1.52 +  public:
    1.53 +    CompactBufferReader(const uint8_t *start, const uint8_t *end)
    1.54 +      : buffer_(start),
    1.55 +        end_(end)
    1.56 +    { }
    1.57 +    inline CompactBufferReader(const CompactBufferWriter &writer);
    1.58 +    uint8_t readByte() {
    1.59 +        JS_ASSERT(buffer_ < end_);
    1.60 +        return *buffer_++;
    1.61 +    }
    1.62 +    uint32_t readFixedUint32_t() {
    1.63 +        uint32_t b0 = readByte();
    1.64 +        uint32_t b1 = readByte();
    1.65 +        uint32_t b2 = readByte();
    1.66 +        uint32_t b3 = readByte();
    1.67 +        return b0 | (b1 << 8) | (b2 << 16) | (b3 << 24);
    1.68 +    }
    1.69 +    uint16_t readFixedUint16_t() {
    1.70 +        uint32_t b0 = readByte();
    1.71 +        uint32_t b1 = readByte();
    1.72 +        return b0 | (b1 << 8);
    1.73 +    }
    1.74 +    uint32_t readUnsigned() {
    1.75 +        return readVariableLength();
    1.76 +    }
    1.77 +    int32_t readSigned() {
    1.78 +        uint8_t b = readByte();
    1.79 +        bool isNegative = !!(b & (1 << 0));
    1.80 +        bool more = !!(b & (1 << 1));
    1.81 +        int32_t result = b >> 2;
    1.82 +        if (more)
    1.83 +            result |= readUnsigned() << 6;
    1.84 +        if (isNegative)
    1.85 +            return -result;
    1.86 +        return result;
    1.87 +    }
    1.88 +
    1.89 +    bool more() const {
    1.90 +        JS_ASSERT(buffer_ <= end_);
    1.91 +        return buffer_ < end_;
    1.92 +    }
    1.93 +
    1.94 +    void seek(const uint8_t *start, uint32_t offset) {
    1.95 +        buffer_ = start + offset;
    1.96 +        MOZ_ASSERT(start < end_);
    1.97 +        MOZ_ASSERT(buffer_ < end_);
    1.98 +    }
    1.99 +};
   1.100 +
   1.101 +class CompactBufferWriter
   1.102 +{
   1.103 +    js::Vector<uint8_t, 32, SystemAllocPolicy> buffer_;
   1.104 +    bool enoughMemory_;
   1.105 +
   1.106 +  public:
   1.107 +    CompactBufferWriter()
   1.108 +      : enoughMemory_(true)
   1.109 +    { }
   1.110 +
   1.111 +    // Note: writeByte() takes uint32 to catch implicit casts with a runtime
   1.112 +    // assert.
   1.113 +    void writeByte(uint32_t byte) {
   1.114 +        JS_ASSERT(byte <= 0xFF);
   1.115 +        enoughMemory_ &= buffer_.append(byte);
   1.116 +    }
   1.117 +    void writeUnsigned(uint32_t value) {
   1.118 +        do {
   1.119 +            uint8_t byte = ((value & 0x7F) << 1) | (value > 0x7F);
   1.120 +            writeByte(byte);
   1.121 +            value >>= 7;
   1.122 +        } while (value);
   1.123 +    }
   1.124 +    void writeSigned(int32_t v) {
   1.125 +        bool isNegative = v < 0;
   1.126 +        uint32_t value = isNegative ? -v : v;
   1.127 +        uint8_t byte = ((value & 0x3F) << 2) | ((value > 0x3F) << 1) | uint32_t(isNegative);
   1.128 +        writeByte(byte);
   1.129 +
   1.130 +        // Write out the rest of the bytes, if needed.
   1.131 +        value >>= 6;
   1.132 +        if (value == 0)
   1.133 +            return;
   1.134 +        writeUnsigned(value);
   1.135 +    }
   1.136 +    void writeFixedUint32_t(uint32_t value) {
   1.137 +        writeByte(value & 0xFF);
   1.138 +        writeByte((value >> 8) & 0xFF);
   1.139 +        writeByte((value >> 16) & 0xFF);
   1.140 +        writeByte((value >> 24) & 0xFF);
   1.141 +    }
   1.142 +    void writeFixedUint16_t(uint16_t value) {
   1.143 +        writeByte(value & 0xFF);
   1.144 +        writeByte(value >> 8);
   1.145 +    }
   1.146 +    size_t length() const {
   1.147 +        return buffer_.length();
   1.148 +    }
   1.149 +    uint8_t *buffer() {
   1.150 +        return &buffer_[0];
   1.151 +    }
   1.152 +    const uint8_t *buffer() const {
   1.153 +        return &buffer_[0];
   1.154 +    }
   1.155 +    bool oom() const {
   1.156 +        return !enoughMemory_;
   1.157 +    }
   1.158 +};
   1.159 +
   1.160 +CompactBufferReader::CompactBufferReader(const CompactBufferWriter &writer)
   1.161 +  : buffer_(writer.buffer()),
   1.162 +    end_(writer.buffer() + writer.length())
   1.163 +{
   1.164 +}
   1.165 +
   1.166 +} // namespace jit
   1.167 +} // namespace js
   1.168 +
   1.169 +#endif /* jit_Compactbuffer_h */

mercurial