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 */