Chromium Code Reviews| Index: runtime/vm/verified_memory.h |
| =================================================================== |
| --- runtime/vm/verified_memory.h (revision 0) |
| +++ runtime/vm/verified_memory.h (revision 0) |
| @@ -0,0 +1,88 @@ |
| +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| +// for details. All rights reserved. Use of this source code is governed by a |
| +// BSD-style license that can be found in the LICENSE file. |
| + |
| +#ifndef VM_VERIFIED_MEMORY_H_ |
| +#define VM_VERIFIED_MEMORY_H_ |
| + |
| +#include "vm/allocation.h" |
| +#include "vm/flags.h" |
| +#include "vm/virtual_memory.h" |
| + |
| +namespace dart { |
| + |
| +#if defined(DEBUG) |
| +DECLARE_FLAG(bool, verified_mem); |
| +DECLARE_FLAG(int, verified_mem_max_reserve_mb); |
| +#endif |
| + |
| + |
| +// A wrapper around VirtualMemory for verifying that a particular class of |
| +// memory writes are only performed through a particular interface. |
| +// |
| +// The main use case is verifying that storing pointers into objects is only |
| +// performed by code aware of the GC write barrier. |
| +// |
| +// NOTE: Verification is enabled only if 'verified_mem' is true, and this flag |
| +// only exists in DEBUG builds. |
| +class VerifiedMemory : public AllStatic { |
| + public: |
| + // Reserves a block of memory for which all methods in this class may |
| + // be called. Returns NULL if out of memory. |
| + static VirtualMemory* Reserve(intptr_t size) { |
|
Ivan Posva
2014/10/29 05:06:07
Here and other places in this code:
We had planned
koda
2014/10/29 19:47:31
I agree with your comment. Will leave as is for no
|
| + return enabled() ? ReserveInternal(size) : VirtualMemory::Reserve(size); |
| + } |
| + |
| + // Verifies that [start, start + size) has only been mutated through |
| + // methods in this class (or explicitly accepted by calling Accept). |
| + static void Verify(uword start, intptr_t size) { |
| + if (!enabled()) return; |
| + ASSERT(size <= offset()); |
| + ASSERT(memcmp(reinterpret_cast<void*>(start + offset()), |
| + reinterpret_cast<void*>(start), |
| + size) == 0); |
| + } |
| + |
| + // Assigns value to *ptr after verifying previous content at that location. |
| + template<typename T> |
| + static void Write(T* ptr, const T& value) { |
| + if (enabled()) { |
| + uword addr = reinterpret_cast<uword>(ptr); |
| + Verify(addr, sizeof(T)); |
| + T* offset_ptr = reinterpret_cast<T*>(addr + offset()); |
| + *offset_ptr = value; |
| + } |
| + *ptr = value; |
| + } |
| + |
| + // Accepts the current state of [start, start + size), even if it has been |
| + // mutated by other means. |
| + static void Accept(uword start, intptr_t size) { |
| + if (!enabled()) return; |
| + ASSERT(size <= offset()); |
| + memmove(reinterpret_cast<void*>(start + offset()), |
| + reinterpret_cast<void*>(start), |
| + size); |
| + } |
| + |
| + private: |
| +#if defined(DEBUG) |
| + static bool enabled() { return FLAG_verified_mem; } |
| + static intptr_t offset() { return FLAG_verified_mem_max_reserve_mb * MB; } |
| + static VirtualMemory* ReserveInternal(intptr_t size); |
| +#else |
| + // In release mode, most code in this class is optimized away. |
| + static bool enabled() { return false; } |
| + static intptr_t offset() { UNREACHABLE(); return -1; } |
| + static VirtualMemory* ReserveInternal(intptr_t size) { |
| + UNREACHABLE(); |
| + return NULL; |
| + } |
| +#endif |
| + |
| + friend class Assembler; // To use enabled/offset when generating code. |
| +}; |
| + |
| +} // namespace dart |
| + |
| +#endif // VM_VERIFIED_MEMORY_H_ |