diff options
Diffstat (limited to 'js/src/jit/x86-shared/Patching-x86-shared.h')
-rw-r--r-- | js/src/jit/x86-shared/Patching-x86-shared.h | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/js/src/jit/x86-shared/Patching-x86-shared.h b/js/src/jit/x86-shared/Patching-x86-shared.h new file mode 100644 index 0000000000..85c523cd15 --- /dev/null +++ b/js/src/jit/x86-shared/Patching-x86-shared.h @@ -0,0 +1,113 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef jit_x86_shared_Patching_x86_shared_h +#define jit_x86_shared_Patching_x86_shared_h + +namespace js { +namespace jit { + +namespace X86Encoding { + +inline void* GetPointer(const void* where) { + void* res; + memcpy(&res, (const char*)where - sizeof(void*), sizeof(void*)); + return res; +} + +inline void SetPointer(void* where, const void* value) { + memcpy((char*)where - sizeof(void*), &value, sizeof(void*)); +} + +inline int32_t GetInt32(const void* where) { + int32_t res; + memcpy(&res, (const char*)where - sizeof(int32_t), sizeof(int32_t)); + return res; +} + +inline void SetInt32(void* where, int32_t value, uint32_t trailing = 0) { + memcpy((char*)where - trailing - sizeof(int32_t), &value, sizeof(int32_t)); +} + +inline void SetRel32(void* from, void* to, uint32_t trailing = 0) { + intptr_t offset = + reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(from); + MOZ_ASSERT(offset == static_cast<int32_t>(offset), + "offset is too great for a 32-bit relocation"); + if (offset != static_cast<int32_t>(offset)) { + MOZ_CRASH("offset is too great for a 32-bit relocation"); + } + + SetInt32(from, offset, trailing); +} + +inline void* GetRel32Target(void* where) { + int32_t rel = GetInt32(where); + return (char*)where + rel; +} + +// JmpSrc represents a positive offset within a code buffer, or an uninitialized +// value. Lots of code depends on uninitialized JmpSrc holding the value -1, on +// -1 being a legal value of JmpSrc, and on being able to initialize a JmpSrc +// with the value -1. +// +// The value of the `offset` is always positive and <= MaxCodeBytesPerProcess, +// see ProcessExecutableMemory.h. The latter quantity in turn must fit in an +// i32. But we further require that the value is not precisely INT32_MAX, so as +// to allow the JmpSrc value -1 to mean "uninitialized" without ambiguity. +// +// The quantity `trailing` denotes the number of bytes of data that follow the +// patch field in the instruction. The offset points to the end of the +// instruction as per normal. The information about trailing bytes is needed +// separately from the offset to correctly patch instructions that have +// immediates trailing the patch field (eg CMPSS and CMPSD). Currently the only +// allowed values for `trailing` are 0 and 1. + +static_assert(MaxCodeBytesPerProcess < size_t(INT32_MAX), "Invariant"); + +class JmpSrc { + public: + JmpSrc() : offset_(INT32_MAX), trailing_(0) {} + explicit JmpSrc(int32_t offset) : offset_(offset), trailing_(0) { + // offset -1 is stored as INT32_MAX + MOZ_ASSERT(offset == -1 || (offset >= 0 && offset < INT32_MAX)); + } + JmpSrc(int32_t offset, uint32_t trailing) + : offset_(offset), trailing_(trailing) { + // Disallow offset -1 in this situation, it does not apply. + MOZ_ASSERT(offset >= 0 && offset < INT32_MAX); + MOZ_ASSERT(trailing <= 1); + } + int32_t offset() const { + return offset_ == INT32_MAX ? -1 : int32_t(offset_); + } + uint32_t trailing() const { return trailing_; } + + private: + uint32_t offset_ : 31; + uint32_t trailing_ : 1; +}; + +class JmpDst { + public: + explicit JmpDst(int32_t offset) : offset_(offset) {} + int32_t offset() const { return offset_; } + + private: + int32_t offset_; +}; + +inline bool CanRelinkJump(void* from, void* to) { + intptr_t offset = static_cast<char*>(to) - static_cast<char*>(from); + return (offset == static_cast<int32_t>(offset)); +} + +} // namespace X86Encoding + +} // namespace jit +} // namespace js + +#endif /* jit_x86_shared_Patching_x86_shared_h */ |