/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- * vim: set ts=8 sts=2 et sw=2 tw=80: * * Copyright 2015 Mozilla Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef wasm_serialize_h #define wasm_serialize_h #include #include "js/Vector.h" namespace js { namespace wasm { // Factor out common serialization, cloning and about:memory size-computation // functions for reuse when serializing wasm and asm.js modules. static inline uint8_t* WriteBytes(uint8_t* dst, const void* src, size_t nbytes) { if (nbytes) { memcpy(dst, src, nbytes); } return dst + nbytes; } static inline const uint8_t* ReadBytes(const uint8_t* src, void* dst, size_t nbytes) { if (nbytes) { memcpy(dst, src, nbytes); } return src + nbytes; } static inline const uint8_t* ReadBytesChecked(const uint8_t* src, size_t* remain, void* dst, size_t nbytes) { if (*remain < nbytes) { return nullptr; } memcpy(dst, src, nbytes); *remain -= nbytes; return src + nbytes; } template static inline uint8_t* WriteScalar(uint8_t* dst, T t) { memcpy(dst, &t, sizeof(t)); return dst + sizeof(t); } template static inline const uint8_t* ReadScalar(const uint8_t* src, T* dst) { memcpy(dst, src, sizeof(*dst)); return src + sizeof(*dst); } template static inline const uint8_t* ReadScalarChecked(const uint8_t* src, size_t* remain, T* dst) { if (*remain < sizeof(*dst)) { return nullptr; } memcpy(dst, src, sizeof(*dst)); *remain -= sizeof(*dst); return src + sizeof(*dst); } template static inline size_t SerializedVectorSize( const mozilla::Vector& vec) { size_t size = sizeof(uint32_t); for (size_t i = 0; i < vec.length(); i++) { size += vec[i].serializedSize(); } return size; } template static inline uint8_t* SerializeVector( uint8_t* cursor, const mozilla::Vector& vec) { cursor = WriteScalar(cursor, vec.length()); for (size_t i = 0; i < vec.length(); i++) { cursor = vec[i].serialize(cursor); } return cursor; } template static inline const uint8_t* DeserializeVector( const uint8_t* cursor, mozilla::Vector* vec) { uint32_t length; cursor = ReadScalar(cursor, &length); if (!vec->resize(length)) { return nullptr; } for (size_t i = 0; i < vec->length(); i++) { if (!(cursor = (*vec)[i].deserialize(cursor))) { return nullptr; } } return cursor; } template static inline size_t SizeOfVectorExcludingThis( const mozilla::Vector& vec, MallocSizeOf mallocSizeOf) { size_t size = vec.sizeOfExcludingThis(mallocSizeOf); for (const T& t : vec) { size += t.sizeOfExcludingThis(mallocSizeOf); } return size; } template static inline size_t SerializedPodVectorSize( const mozilla::Vector& vec) { return sizeof(uint32_t) + vec.length() * sizeof(T); } template static inline uint8_t* SerializePodVector( uint8_t* cursor, const mozilla::Vector& vec) { // This binary format must not change without taking into consideration the // constraints in Assumptions::serialize. cursor = WriteScalar(cursor, vec.length()); cursor = WriteBytes(cursor, vec.begin(), vec.length() * sizeof(T)); return cursor; } template static inline const uint8_t* DeserializePodVector( const uint8_t* cursor, mozilla::Vector* vec) { uint32_t length; cursor = ReadScalar(cursor, &length); if (!vec->initLengthUninitialized(length)) { return nullptr; } cursor = ReadBytes(cursor, vec->begin(), length * sizeof(T)); return cursor; } template static inline const uint8_t* DeserializePodVectorChecked( const uint8_t* cursor, size_t* remain, mozilla::Vector* vec) { uint32_t length; cursor = ReadScalarChecked(cursor, remain, &length); if (!cursor || !vec->initLengthUninitialized(length)) { return nullptr; } cursor = ReadBytesChecked(cursor, remain, vec->begin(), length * sizeof(T)); return cursor; } template inline size_t SerializableRefPtr::serializedSize() const { return (*this)->serializedSize(); } template inline uint8_t* SerializableRefPtr::serialize(uint8_t* cursor) const { return (*this)->serialize(cursor); } template inline const uint8_t* SerializableRefPtr::deserialize( const uint8_t* cursor) { auto* t = js_new>(); *this = t; return t->deserialize(cursor); } template inline size_t SerializableRefPtr::sizeOfExcludingThis( mozilla::MallocSizeOf mallocSizeOf) const { return (*this)->sizeOfExcludingThis(mallocSizeOf); } } // namespace wasm } // namespace js #endif // wasm_serialize_h