js/src/jit/CompactBuffer.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * vim: set ts=8 sts=4 et sw=4 tw=99:
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifndef jit_Compactbuffer_h
michael@0 8 #define jit_Compactbuffer_h
michael@0 9
michael@0 10 #include "jsalloc.h"
michael@0 11
michael@0 12 #include "jit/IonTypes.h"
michael@0 13 #include "js/Vector.h"
michael@0 14
michael@0 15 namespace js {
michael@0 16 namespace jit {
michael@0 17
michael@0 18 class CompactBufferWriter;
michael@0 19
michael@0 20 // CompactBuffers are byte streams designed for compressable integers. It has
michael@0 21 // helper functions for writing bytes, fixed-size integers, and variable-sized
michael@0 22 // integers. Variable sized integers are encoded in 1-5 bytes, each byte
michael@0 23 // containing 7 bits of the integer and a bit which specifies whether the next
michael@0 24 // byte is also part of the integer.
michael@0 25 //
michael@0 26 // Fixed-width integers are also available, in case the actual value will not
michael@0 27 // be known until later.
michael@0 28
michael@0 29 class CompactBufferReader
michael@0 30 {
michael@0 31 const uint8_t *buffer_;
michael@0 32 const uint8_t *end_;
michael@0 33
michael@0 34 uint32_t readVariableLength() {
michael@0 35 uint32_t val = 0;
michael@0 36 uint32_t shift = 0;
michael@0 37 uint8_t byte;
michael@0 38 while (true) {
michael@0 39 JS_ASSERT(shift < 32);
michael@0 40 byte = readByte();
michael@0 41 val |= (uint32_t(byte) >> 1) << shift;
michael@0 42 shift += 7;
michael@0 43 if (!(byte & 1))
michael@0 44 return val;
michael@0 45 }
michael@0 46 MOZ_ASSUME_UNREACHABLE("unreachable");
michael@0 47 }
michael@0 48
michael@0 49 public:
michael@0 50 CompactBufferReader(const uint8_t *start, const uint8_t *end)
michael@0 51 : buffer_(start),
michael@0 52 end_(end)
michael@0 53 { }
michael@0 54 inline CompactBufferReader(const CompactBufferWriter &writer);
michael@0 55 uint8_t readByte() {
michael@0 56 JS_ASSERT(buffer_ < end_);
michael@0 57 return *buffer_++;
michael@0 58 }
michael@0 59 uint32_t readFixedUint32_t() {
michael@0 60 uint32_t b0 = readByte();
michael@0 61 uint32_t b1 = readByte();
michael@0 62 uint32_t b2 = readByte();
michael@0 63 uint32_t b3 = readByte();
michael@0 64 return b0 | (b1 << 8) | (b2 << 16) | (b3 << 24);
michael@0 65 }
michael@0 66 uint16_t readFixedUint16_t() {
michael@0 67 uint32_t b0 = readByte();
michael@0 68 uint32_t b1 = readByte();
michael@0 69 return b0 | (b1 << 8);
michael@0 70 }
michael@0 71 uint32_t readUnsigned() {
michael@0 72 return readVariableLength();
michael@0 73 }
michael@0 74 int32_t readSigned() {
michael@0 75 uint8_t b = readByte();
michael@0 76 bool isNegative = !!(b & (1 << 0));
michael@0 77 bool more = !!(b & (1 << 1));
michael@0 78 int32_t result = b >> 2;
michael@0 79 if (more)
michael@0 80 result |= readUnsigned() << 6;
michael@0 81 if (isNegative)
michael@0 82 return -result;
michael@0 83 return result;
michael@0 84 }
michael@0 85
michael@0 86 bool more() const {
michael@0 87 JS_ASSERT(buffer_ <= end_);
michael@0 88 return buffer_ < end_;
michael@0 89 }
michael@0 90
michael@0 91 void seek(const uint8_t *start, uint32_t offset) {
michael@0 92 buffer_ = start + offset;
michael@0 93 MOZ_ASSERT(start < end_);
michael@0 94 MOZ_ASSERT(buffer_ < end_);
michael@0 95 }
michael@0 96 };
michael@0 97
michael@0 98 class CompactBufferWriter
michael@0 99 {
michael@0 100 js::Vector<uint8_t, 32, SystemAllocPolicy> buffer_;
michael@0 101 bool enoughMemory_;
michael@0 102
michael@0 103 public:
michael@0 104 CompactBufferWriter()
michael@0 105 : enoughMemory_(true)
michael@0 106 { }
michael@0 107
michael@0 108 // Note: writeByte() takes uint32 to catch implicit casts with a runtime
michael@0 109 // assert.
michael@0 110 void writeByte(uint32_t byte) {
michael@0 111 JS_ASSERT(byte <= 0xFF);
michael@0 112 enoughMemory_ &= buffer_.append(byte);
michael@0 113 }
michael@0 114 void writeUnsigned(uint32_t value) {
michael@0 115 do {
michael@0 116 uint8_t byte = ((value & 0x7F) << 1) | (value > 0x7F);
michael@0 117 writeByte(byte);
michael@0 118 value >>= 7;
michael@0 119 } while (value);
michael@0 120 }
michael@0 121 void writeSigned(int32_t v) {
michael@0 122 bool isNegative = v < 0;
michael@0 123 uint32_t value = isNegative ? -v : v;
michael@0 124 uint8_t byte = ((value & 0x3F) << 2) | ((value > 0x3F) << 1) | uint32_t(isNegative);
michael@0 125 writeByte(byte);
michael@0 126
michael@0 127 // Write out the rest of the bytes, if needed.
michael@0 128 value >>= 6;
michael@0 129 if (value == 0)
michael@0 130 return;
michael@0 131 writeUnsigned(value);
michael@0 132 }
michael@0 133 void writeFixedUint32_t(uint32_t value) {
michael@0 134 writeByte(value & 0xFF);
michael@0 135 writeByte((value >> 8) & 0xFF);
michael@0 136 writeByte((value >> 16) & 0xFF);
michael@0 137 writeByte((value >> 24) & 0xFF);
michael@0 138 }
michael@0 139 void writeFixedUint16_t(uint16_t value) {
michael@0 140 writeByte(value & 0xFF);
michael@0 141 writeByte(value >> 8);
michael@0 142 }
michael@0 143 size_t length() const {
michael@0 144 return buffer_.length();
michael@0 145 }
michael@0 146 uint8_t *buffer() {
michael@0 147 return &buffer_[0];
michael@0 148 }
michael@0 149 const uint8_t *buffer() const {
michael@0 150 return &buffer_[0];
michael@0 151 }
michael@0 152 bool oom() const {
michael@0 153 return !enoughMemory_;
michael@0 154 }
michael@0 155 };
michael@0 156
michael@0 157 CompactBufferReader::CompactBufferReader(const CompactBufferWriter &writer)
michael@0 158 : buffer_(writer.buffer()),
michael@0 159 end_(writer.buffer() + writer.length())
michael@0 160 {
michael@0 161 }
michael@0 162
michael@0 163 } // namespace jit
michael@0 164 } // namespace js
michael@0 165
michael@0 166 #endif /* jit_Compactbuffer_h */

mercurial