2013-04-17 00:47:10 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
|
|
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
2012-05-21 15:12:37 +04:00
|
|
|
* 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/. */
|
2011-10-05 02:33:00 +04:00
|
|
|
|
2013-06-20 04:59:09 +04:00
|
|
|
#ifndef js_Utility_h
|
|
|
|
#define js_Utility_h
|
2011-10-05 02:33:00 +04:00
|
|
|
|
2011-12-20 00:54:12 +04:00
|
|
|
#include "mozilla/Assertions.h"
|
2012-06-08 01:41:11 +04:00
|
|
|
#include "mozilla/Attributes.h"
|
2013-05-01 23:45:05 +04:00
|
|
|
#include "mozilla/Compiler.h"
|
2013-07-03 04:25:13 +04:00
|
|
|
#include "mozilla/Move.h"
|
2012-12-15 03:58:45 +04:00
|
|
|
#include "mozilla/Scoped.h"
|
2013-07-08 23:42:13 +04:00
|
|
|
#include "mozilla/TemplateLib.h"
|
2014-09-19 19:39:54 +04:00
|
|
|
#include "mozilla/UniquePtr.h"
|
2011-12-20 00:54:12 +04:00
|
|
|
|
2011-10-05 02:33:00 +04:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2012-03-11 00:53:03 +04:00
|
|
|
#ifdef JS_OOM_DO_BACKTRACES
|
|
|
|
#include <execinfo.h>
|
2013-08-14 02:34:12 +04:00
|
|
|
#include <stdio.h>
|
2012-03-11 00:53:03 +04:00
|
|
|
#endif
|
|
|
|
|
2011-12-13 23:26:58 +04:00
|
|
|
#include "jstypes.h"
|
2011-10-05 02:33:00 +04:00
|
|
|
|
|
|
|
/* The public JS engine namespace. */
|
|
|
|
namespace JS {}
|
|
|
|
|
|
|
|
/* The mozilla-shared reusable template/utility namespace. */
|
|
|
|
namespace mozilla {}
|
|
|
|
|
|
|
|
/* The private JS engine namespace. */
|
2013-03-19 14:35:41 +04:00
|
|
|
namespace js {}
|
2011-10-05 02:33:00 +04:00
|
|
|
|
|
|
|
/*
|
2014-03-21 01:38:50 +04:00
|
|
|
* Patterns used by SpiderMonkey to overwrite unused memory. If you are
|
|
|
|
* accessing an object with one of these pattern, you probably have a dangling
|
|
|
|
* pointer.
|
2011-10-05 02:33:00 +04:00
|
|
|
*/
|
2014-03-21 01:38:50 +04:00
|
|
|
#define JS_FRESH_NURSERY_PATTERN 0x2F
|
|
|
|
#define JS_SWEPT_NURSERY_PATTERN 0x2B
|
|
|
|
#define JS_ALLOCATED_NURSERY_PATTERN 0x2D
|
|
|
|
#define JS_FRESH_TENURED_PATTERN 0x4F
|
2014-08-14 14:52:24 +04:00
|
|
|
#define JS_MOVED_TENURED_PATTERN 0x49
|
2014-03-21 01:38:50 +04:00
|
|
|
#define JS_SWEPT_TENURED_PATTERN 0x4B
|
|
|
|
#define JS_ALLOCATED_TENURED_PATTERN 0x4D
|
2014-11-19 00:56:46 +03:00
|
|
|
#define JS_EMPTY_STOREBUFFER_PATTERN 0x1B
|
|
|
|
#define JS_SWEPT_CODE_PATTERN 0x3B
|
|
|
|
#define JS_SWEPT_FRAME_PATTERN 0x5B
|
2011-10-05 02:33:00 +04:00
|
|
|
|
2013-07-18 21:59:53 +04:00
|
|
|
#define JS_STATIC_ASSERT(cond) static_assert(cond, "JS_STATIC_ASSERT")
|
2011-12-20 01:58:30 +04:00
|
|
|
#define JS_STATIC_ASSERT_IF(cond, expr) MOZ_STATIC_ASSERT_IF(cond, expr, "JS_STATIC_ASSERT_IF")
|
2011-10-05 02:33:00 +04:00
|
|
|
|
2015-01-27 04:30:19 +03:00
|
|
|
extern MOZ_NORETURN MOZ_COLD JS_PUBLIC_API(void)
|
2015-03-29 01:22:11 +03:00
|
|
|
JS_Assert(const char* s, const char* file, int ln);
|
2012-06-08 01:41:11 +04:00
|
|
|
|
2011-10-05 02:33:00 +04:00
|
|
|
/*
|
|
|
|
* Custom allocator support for SpiderMonkey
|
|
|
|
*/
|
|
|
|
#if defined JS_USE_CUSTOM_ALLOCATOR
|
|
|
|
# include "jscustomallocator.h"
|
|
|
|
#else
|
2015-09-11 17:11:56 +03:00
|
|
|
|
|
|
|
namespace js {
|
|
|
|
namespace oom {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* To make testing OOM in certain helper threads more effective,
|
|
|
|
* allow restricting the OOM testing to a certain helper thread
|
|
|
|
* type. This allows us to fail e.g. in off-thread script parsing
|
|
|
|
* without causing an OOM in the main thread first.
|
|
|
|
*/
|
|
|
|
enum ThreadType {
|
|
|
|
THREAD_TYPE_NONE, // 0
|
|
|
|
THREAD_TYPE_MAIN, // 1
|
|
|
|
THREAD_TYPE_ASMJS, // 2
|
|
|
|
THREAD_TYPE_ION, // 3
|
|
|
|
THREAD_TYPE_PARSE, // 4
|
|
|
|
THREAD_TYPE_COMPRESS, // 5
|
|
|
|
THREAD_TYPE_GCHELPER, // 6
|
|
|
|
THREAD_TYPE_GCPARALLEL, // 7
|
|
|
|
THREAD_TYPE_MAX // Used to check shell function arguments
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Getter/Setter functions to encapsulate mozilla::ThreadLocal,
|
|
|
|
* implementation is in jsutil.cpp.
|
|
|
|
*/
|
|
|
|
# if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
|
|
|
|
extern bool InitThreadType(void);
|
|
|
|
extern void SetThreadType(ThreadType);
|
|
|
|
extern uint32_t GetThreadType(void);
|
|
|
|
# else
|
|
|
|
inline bool InitThreadType(void) { return true; }
|
|
|
|
inline void SetThreadType(ThreadType t) {};
|
|
|
|
inline uint32_t GetThreadType(void) { return 0; }
|
|
|
|
# endif
|
|
|
|
|
|
|
|
} /* namespace oom */
|
|
|
|
} /* namespace js */
|
|
|
|
|
2014-03-27 22:15:22 +04:00
|
|
|
# if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
|
2015-05-22 20:52:38 +03:00
|
|
|
|
2011-10-05 02:33:00 +04:00
|
|
|
/*
|
2013-05-20 23:59:55 +04:00
|
|
|
* In order to test OOM conditions, when the testing function
|
|
|
|
* oomAfterAllocations COUNT is passed, we fail continuously after the NUM'th
|
|
|
|
* allocation from now.
|
2011-10-05 02:33:00 +04:00
|
|
|
*/
|
2014-04-08 21:52:24 +04:00
|
|
|
extern JS_PUBLIC_DATA(uint32_t) OOM_maxAllocations; /* set in builtin/TestingFunctions.cpp */
|
Bug 708735 - Use <stdint.h> types in JSAPI and throughout SpiderMonkey. Continue to provide the {u,}int{8,16,32,64} and JS{Uint,Int}{8,16,32,64} integer types through a single header, however, for a simpler backout strategy -- and also to ease the transition for embedders. r=timeless on switching the jsd API to use the <stdint.h> types, r=luke, r=dmandelin
2011-12-09 07:54:10 +04:00
|
|
|
extern JS_PUBLIC_DATA(uint32_t) OOM_counter; /* data race, who cares. */
|
2015-05-22 20:52:38 +03:00
|
|
|
extern JS_PUBLIC_DATA(bool) OOM_failAlways;
|
2012-03-11 00:53:03 +04:00
|
|
|
|
2014-03-26 03:31:54 +04:00
|
|
|
#ifdef JS_OOM_BREAKPOINT
|
|
|
|
static MOZ_NEVER_INLINE void js_failedAllocBreakpoint() { asm(""); }
|
|
|
|
#define JS_OOM_CALL_BP_FUNC() js_failedAllocBreakpoint()
|
|
|
|
#else
|
|
|
|
#define JS_OOM_CALL_BP_FUNC() do {} while(0)
|
|
|
|
#endif
|
2012-03-11 00:53:03 +04:00
|
|
|
|
2015-03-11 21:06:20 +03:00
|
|
|
namespace js {
|
|
|
|
namespace oom {
|
2015-07-01 20:53:04 +03:00
|
|
|
|
2015-09-11 17:11:56 +03:00
|
|
|
extern JS_PUBLIC_DATA(uint32_t) targetThread;
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
OOMThreadCheck()
|
|
|
|
{
|
|
|
|
return (!js::oom::targetThread
|
|
|
|
|| js::oom::targetThread == js::oom::GetThreadType());
|
|
|
|
}
|
|
|
|
|
2015-07-01 20:53:04 +03:00
|
|
|
static inline bool
|
|
|
|
IsSimulatedOOMAllocation()
|
|
|
|
{
|
2015-09-11 17:11:56 +03:00
|
|
|
return OOMThreadCheck() && (OOM_counter == OOM_maxAllocations ||
|
|
|
|
(OOM_counter > OOM_maxAllocations && OOM_failAlways));
|
2015-07-01 20:53:04 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
ShouldFailWithOOM()
|
2015-03-11 21:06:20 +03:00
|
|
|
{
|
2015-09-11 17:11:56 +03:00
|
|
|
if (!OOMThreadCheck())
|
|
|
|
return false;
|
|
|
|
|
2015-05-22 20:52:38 +03:00
|
|
|
OOM_counter++;
|
2015-07-01 20:53:04 +03:00
|
|
|
if (IsSimulatedOOMAllocation()) {
|
2015-03-11 21:06:20 +03:00
|
|
|
JS_OOM_CALL_BP_FUNC();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2015-07-01 20:53:04 +03:00
|
|
|
|
2015-05-22 20:52:38 +03:00
|
|
|
} /* namespace oom */
|
|
|
|
} /* namespace js */
|
|
|
|
|
|
|
|
# define JS_OOM_POSSIBLY_FAIL() \
|
|
|
|
do { \
|
|
|
|
if (js::oom::ShouldFailWithOOM()) \
|
|
|
|
return nullptr; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
# define JS_OOM_POSSIBLY_FAIL_BOOL() \
|
|
|
|
do { \
|
|
|
|
if (js::oom::ShouldFailWithOOM()) \
|
|
|
|
return false; \
|
|
|
|
} while (0)
|
|
|
|
|
2011-10-05 02:33:00 +04:00
|
|
|
# else
|
2015-05-22 20:52:38 +03:00
|
|
|
|
2011-10-05 02:33:00 +04:00
|
|
|
# define JS_OOM_POSSIBLY_FAIL() do {} while(0)
|
2015-01-08 17:25:18 +03:00
|
|
|
# define JS_OOM_POSSIBLY_FAIL_BOOL() do {} while(0)
|
2015-05-22 20:52:38 +03:00
|
|
|
namespace js {
|
|
|
|
namespace oom {
|
2015-07-01 20:53:04 +03:00
|
|
|
static inline bool IsSimulatedOOMAllocation() { return false; }
|
2015-05-22 20:52:38 +03:00
|
|
|
static inline bool ShouldFailWithOOM() { return false; }
|
|
|
|
} /* namespace oom */
|
|
|
|
} /* namespace js */
|
|
|
|
|
2014-03-27 22:15:22 +04:00
|
|
|
# endif /* DEBUG || JS_OOM_BREAKPOINT */
|
2011-10-05 02:33:00 +04:00
|
|
|
|
2013-10-22 01:34:24 +04:00
|
|
|
static inline void* js_malloc(size_t bytes)
|
2011-10-05 02:33:00 +04:00
|
|
|
{
|
|
|
|
JS_OOM_POSSIBLY_FAIL();
|
|
|
|
return malloc(bytes);
|
|
|
|
}
|
|
|
|
|
2013-10-22 01:34:24 +04:00
|
|
|
static inline void* js_calloc(size_t bytes)
|
2011-10-05 02:33:00 +04:00
|
|
|
{
|
|
|
|
JS_OOM_POSSIBLY_FAIL();
|
|
|
|
return calloc(bytes, 1);
|
|
|
|
}
|
|
|
|
|
2013-10-22 01:34:24 +04:00
|
|
|
static inline void* js_calloc(size_t nmemb, size_t size)
|
2013-09-25 23:18:43 +04:00
|
|
|
{
|
|
|
|
JS_OOM_POSSIBLY_FAIL();
|
|
|
|
return calloc(nmemb, size);
|
|
|
|
}
|
|
|
|
|
2013-10-22 01:34:24 +04:00
|
|
|
static inline void* js_realloc(void* p, size_t bytes)
|
2011-10-05 02:33:00 +04:00
|
|
|
{
|
|
|
|
JS_OOM_POSSIBLY_FAIL();
|
|
|
|
return realloc(p, bytes);
|
|
|
|
}
|
|
|
|
|
2013-10-22 01:34:24 +04:00
|
|
|
static inline void js_free(void* p)
|
2011-10-05 02:33:00 +04:00
|
|
|
{
|
|
|
|
free(p);
|
|
|
|
}
|
2014-09-19 19:39:54 +04:00
|
|
|
|
|
|
|
static inline char* js_strdup(const char* s)
|
|
|
|
{
|
|
|
|
JS_OOM_POSSIBLY_FAIL();
|
|
|
|
return strdup(s);
|
|
|
|
}
|
2011-10-05 02:33:00 +04:00
|
|
|
#endif/* JS_USE_CUSTOM_ALLOCATOR */
|
|
|
|
|
|
|
|
#include <new>
|
|
|
|
|
|
|
|
/*
|
2012-09-01 02:01:33 +04:00
|
|
|
* Low-level memory management in SpiderMonkey:
|
2011-10-05 02:33:00 +04:00
|
|
|
*
|
2012-09-01 02:01:33 +04:00
|
|
|
* ** Do not use the standard malloc/free/realloc: SpiderMonkey allows these
|
|
|
|
* to be redefined (via JS_USE_CUSTOM_ALLOCATOR) and Gecko even #define's
|
|
|
|
* these symbols.
|
2011-10-05 02:33:00 +04:00
|
|
|
*
|
2012-09-01 02:01:33 +04:00
|
|
|
* ** Do not use the builtin C++ operator new and delete: these throw on
|
|
|
|
* error and we cannot override them not to.
|
2011-10-05 02:33:00 +04:00
|
|
|
*
|
2012-09-01 02:01:33 +04:00
|
|
|
* Allocation:
|
2011-10-05 02:33:00 +04:00
|
|
|
*
|
2012-09-01 02:01:33 +04:00
|
|
|
* - If the lifetime of the allocation is tied to the lifetime of a GC-thing
|
|
|
|
* (that is, finalizing the GC-thing will free the allocation), call one of
|
|
|
|
* the following functions:
|
2011-10-05 02:33:00 +04:00
|
|
|
*
|
2012-09-01 02:01:33 +04:00
|
|
|
* JSContext::{malloc_,realloc_,calloc_,new_}
|
|
|
|
* JSRuntime::{malloc_,realloc_,calloc_,new_}
|
2011-10-05 02:33:00 +04:00
|
|
|
*
|
2012-09-01 02:01:33 +04:00
|
|
|
* These functions accumulate the number of bytes allocated which is used as
|
|
|
|
* part of the GC-triggering heuristic.
|
2011-10-05 02:33:00 +04:00
|
|
|
*
|
2012-09-01 02:01:33 +04:00
|
|
|
* The difference between the JSContext and JSRuntime versions is that the
|
|
|
|
* cx version reports an out-of-memory error on OOM. (This follows from the
|
|
|
|
* general SpiderMonkey idiom that a JSContext-taking function reports its
|
|
|
|
* own errors.)
|
2011-10-05 02:33:00 +04:00
|
|
|
*
|
2015-08-19 20:59:50 +03:00
|
|
|
* - Otherwise, use js_malloc/js_realloc/js_calloc/js_new
|
2011-10-05 02:33:00 +04:00
|
|
|
*
|
2012-09-01 02:01:33 +04:00
|
|
|
* Deallocation:
|
2011-10-05 02:33:00 +04:00
|
|
|
*
|
2012-09-01 02:01:33 +04:00
|
|
|
* - Ordinarily, use js_free/js_delete.
|
2011-10-05 02:33:00 +04:00
|
|
|
*
|
2012-09-01 02:01:33 +04:00
|
|
|
* - For deallocations during GC finalization, use one of the following
|
|
|
|
* operations on the FreeOp provided to the finalizer:
|
2011-10-05 02:33:00 +04:00
|
|
|
*
|
2012-09-01 02:01:33 +04:00
|
|
|
* FreeOp::{free_,delete_}
|
2011-10-05 02:33:00 +04:00
|
|
|
*
|
2012-09-01 02:01:33 +04:00
|
|
|
* The advantage of these operations is that the memory is batched and freed
|
|
|
|
* on another thread.
|
2011-10-05 02:33:00 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2015-01-25 07:18:21 +03:00
|
|
|
* Given a class which should provide a 'new' method, add
|
|
|
|
* JS_DECLARE_NEW_METHODS (see js::MallocProvider for an example).
|
2011-10-05 02:33:00 +04:00
|
|
|
*
|
|
|
|
* Note: Do not add a ; at the end of a use of JS_DECLARE_NEW_METHODS,
|
|
|
|
* or the build will break.
|
|
|
|
*/
|
2012-09-01 02:01:33 +04:00
|
|
|
#define JS_DECLARE_NEW_METHODS(NEWNAME, ALLOCATOR, QUALIFIERS)\
|
2015-01-25 07:18:21 +03:00
|
|
|
template <class T, typename... Args> \
|
|
|
|
QUALIFIERS T * \
|
|
|
|
NEWNAME(Args&&... args) MOZ_HEAP_ALLOCATOR { \
|
2015-03-29 01:22:11 +03:00
|
|
|
void* memory = ALLOCATOR(sizeof(T)); \
|
2015-01-25 07:18:21 +03:00
|
|
|
return memory \
|
|
|
|
? new(memory) T(mozilla::Forward<Args>(args)...) \
|
|
|
|
: nullptr; \
|
|
|
|
}
|
2014-07-10 04:58:43 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Given a class which should provide 'make' methods, add
|
2015-01-25 07:18:21 +03:00
|
|
|
* JS_DECLARE_MAKE_METHODS (see js::MallocProvider for an example). This
|
|
|
|
* method is functionally the same as JS_DECLARE_NEW_METHODS: it just declares
|
|
|
|
* methods that return mozilla::UniquePtr instances that will singly-manage
|
|
|
|
* ownership of the created object.
|
2014-07-10 04:58:43 +04:00
|
|
|
*
|
|
|
|
* Note: Do not add a ; at the end of a use of JS_DECLARE_MAKE_METHODS,
|
|
|
|
* or the build will break.
|
|
|
|
*/
|
|
|
|
#define JS_DECLARE_MAKE_METHODS(MAKENAME, NEWNAME, QUALIFIERS)\
|
2015-01-25 07:18:21 +03:00
|
|
|
template <class T, typename... Args> \
|
|
|
|
QUALIFIERS mozilla::UniquePtr<T, JS::DeletePolicy<T>> \
|
|
|
|
MAKENAME(Args&&... args) MOZ_HEAP_ALLOCATOR { \
|
2015-03-29 01:22:11 +03:00
|
|
|
T* ptr = NEWNAME<T>(mozilla::Forward<Args>(args)...); \
|
2015-01-25 07:18:21 +03:00
|
|
|
return mozilla::UniquePtr<T, JS::DeletePolicy<T>>(ptr); \
|
|
|
|
}
|
2011-10-05 02:33:00 +04:00
|
|
|
|
2014-01-25 08:14:56 +04:00
|
|
|
JS_DECLARE_NEW_METHODS(js_new, js_malloc, static MOZ_ALWAYS_INLINE)
|
2011-10-05 02:33:00 +04:00
|
|
|
|
2012-09-01 02:01:33 +04:00
|
|
|
template <class T>
|
2014-01-25 08:14:56 +04:00
|
|
|
static MOZ_ALWAYS_INLINE void
|
2015-08-19 20:59:50 +03:00
|
|
|
js_delete(const T* p)
|
2012-09-01 02:01:33 +04:00
|
|
|
{
|
|
|
|
if (p) {
|
|
|
|
p->~T();
|
2015-08-19 20:59:50 +03:00
|
|
|
js_free(const_cast<T*>(p));
|
2011-10-05 02:33:00 +04:00
|
|
|
}
|
2012-09-01 02:01:33 +04:00
|
|
|
}
|
2011-10-05 02:33:00 +04:00
|
|
|
|
2013-04-11 15:48:09 +04:00
|
|
|
template<class T>
|
2014-01-25 08:14:56 +04:00
|
|
|
static MOZ_ALWAYS_INLINE void
|
2015-08-19 20:59:50 +03:00
|
|
|
js_delete_poison(const T* p)
|
2013-04-11 15:48:09 +04:00
|
|
|
{
|
|
|
|
if (p) {
|
|
|
|
p->~T();
|
2015-08-19 20:59:50 +03:00
|
|
|
memset(const_cast<T*>(p), 0x3B, sizeof(T));
|
|
|
|
js_free(const_cast<T*>(p));
|
2013-04-11 15:48:09 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-01 02:10:10 +04:00
|
|
|
template <class T>
|
2015-03-29 01:22:11 +03:00
|
|
|
static MOZ_ALWAYS_INLINE T*
|
2012-09-01 02:10:10 +04:00
|
|
|
js_pod_malloc()
|
|
|
|
{
|
2015-03-29 01:22:11 +03:00
|
|
|
return (T*)js_malloc(sizeof(T));
|
2012-09-01 02:10:10 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
2015-03-29 01:22:11 +03:00
|
|
|
static MOZ_ALWAYS_INLINE T*
|
2012-09-01 02:10:10 +04:00
|
|
|
js_pod_calloc()
|
|
|
|
{
|
2015-03-29 01:22:11 +03:00
|
|
|
return (T*)js_calloc(sizeof(T));
|
2012-09-01 02:10:10 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
2015-03-29 01:22:11 +03:00
|
|
|
static MOZ_ALWAYS_INLINE T*
|
2012-09-01 02:10:10 +04:00
|
|
|
js_pod_malloc(size_t numElems)
|
|
|
|
{
|
2015-02-12 19:37:01 +03:00
|
|
|
if (MOZ_UNLIKELY(numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value))
|
2013-09-19 23:24:53 +04:00
|
|
|
return nullptr;
|
2015-03-29 01:22:11 +03:00
|
|
|
return (T*)js_malloc(numElems * sizeof(T));
|
2012-09-01 02:10:10 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
2015-03-29 01:22:11 +03:00
|
|
|
static MOZ_ALWAYS_INLINE T*
|
2012-09-01 02:10:10 +04:00
|
|
|
js_pod_calloc(size_t numElems)
|
|
|
|
{
|
2015-02-12 19:37:01 +03:00
|
|
|
if (MOZ_UNLIKELY(numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value))
|
2013-09-19 23:24:53 +04:00
|
|
|
return nullptr;
|
2015-03-29 01:22:11 +03:00
|
|
|
return (T*)js_calloc(numElems * sizeof(T));
|
2012-09-01 02:10:10 +04:00
|
|
|
}
|
|
|
|
|
2014-08-06 01:06:35 +04:00
|
|
|
template <class T>
|
2015-03-29 01:22:11 +03:00
|
|
|
static MOZ_ALWAYS_INLINE T*
|
|
|
|
js_pod_realloc(T* prior, size_t oldSize, size_t newSize)
|
2014-08-06 01:06:35 +04:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(!(oldSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value));
|
2015-02-12 19:37:01 +03:00
|
|
|
if (MOZ_UNLIKELY(newSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value))
|
2014-08-06 01:06:35 +04:00
|
|
|
return nullptr;
|
2015-03-29 01:22:11 +03:00
|
|
|
return (T*)js_realloc(prior, newSize * sizeof(T));
|
2014-08-06 01:06:35 +04:00
|
|
|
}
|
|
|
|
|
2011-10-05 02:33:00 +04:00
|
|
|
namespace js {
|
|
|
|
|
2012-07-06 04:29:56 +04:00
|
|
|
template<typename T>
|
|
|
|
struct ScopedFreePtrTraits
|
|
|
|
{
|
|
|
|
typedef T* type;
|
2013-09-19 23:24:53 +04:00
|
|
|
static T* empty() { return nullptr; }
|
2012-09-01 02:01:33 +04:00
|
|
|
static void release(T* ptr) { js_free(ptr); }
|
2012-07-06 04:29:56 +04:00
|
|
|
};
|
2012-11-02 08:35:21 +04:00
|
|
|
SCOPED_TEMPLATE(ScopedJSFreePtr, ScopedFreePtrTraits)
|
2012-07-06 04:29:56 +04:00
|
|
|
|
2012-06-12 04:08:34 +04:00
|
|
|
template <typename T>
|
2012-07-06 04:29:56 +04:00
|
|
|
struct ScopedDeletePtrTraits : public ScopedFreePtrTraits<T>
|
2012-06-12 04:08:34 +04:00
|
|
|
{
|
2015-03-29 01:22:11 +03:00
|
|
|
static void release(T* ptr) { js_delete(ptr); }
|
2012-06-12 04:08:34 +04:00
|
|
|
};
|
2012-11-02 08:35:21 +04:00
|
|
|
SCOPED_TEMPLATE(ScopedJSDeletePtr, ScopedDeletePtrTraits)
|
2012-06-12 04:08:34 +04:00
|
|
|
|
2013-03-15 13:29:02 +04:00
|
|
|
template <typename T>
|
|
|
|
struct ScopedReleasePtrTraits : public ScopedFreePtrTraits<T>
|
|
|
|
{
|
2015-03-29 01:22:11 +03:00
|
|
|
static void release(T* ptr) { if (ptr) ptr->release(); }
|
2013-03-15 13:29:02 +04:00
|
|
|
};
|
|
|
|
SCOPED_TEMPLATE(ScopedReleasePtr, ScopedReleasePtrTraits)
|
|
|
|
|
2011-10-05 02:33:00 +04:00
|
|
|
} /* namespace js */
|
|
|
|
|
2014-07-10 03:53:42 +04:00
|
|
|
namespace JS {
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct DeletePolicy
|
|
|
|
{
|
|
|
|
void operator()(T* ptr) {
|
|
|
|
js_delete(ptr);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct FreePolicy
|
|
|
|
{
|
|
|
|
void operator()(void* ptr) {
|
|
|
|
js_free(ptr);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace JS
|
|
|
|
|
2011-10-05 02:33:00 +04:00
|
|
|
namespace js {
|
2013-01-08 14:04:19 +04:00
|
|
|
|
2012-07-04 01:33:38 +04:00
|
|
|
/* Integral types for all hash functions. */
|
|
|
|
typedef uint32_t HashNumber;
|
2012-07-25 21:43:29 +04:00
|
|
|
const unsigned HashNumberSizeBits = 32;
|
2012-07-04 01:33:38 +04:00
|
|
|
|
2014-09-19 19:39:54 +04:00
|
|
|
typedef mozilla::UniquePtr<char, JS::FreePolicy> UniqueChars;
|
|
|
|
|
|
|
|
static inline UniqueChars make_string_copy(const char* str)
|
|
|
|
{
|
|
|
|
return UniqueChars(js_strdup(str));
|
|
|
|
}
|
|
|
|
|
2012-07-04 01:33:38 +04:00
|
|
|
namespace detail {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Given a raw hash code, h, return a number that can be used to select a hash
|
|
|
|
* bucket.
|
|
|
|
*
|
|
|
|
* This function aims to produce as uniform an output distribution as possible,
|
|
|
|
* especially in the most significant (leftmost) bits, even though the input
|
|
|
|
* distribution may be highly nonrandom, given the constraints that this must
|
|
|
|
* be deterministic and quick to compute.
|
|
|
|
*
|
|
|
|
* Since the leftmost bits of the result are best, the hash bucket index is
|
|
|
|
* computed by doing ScrambleHashCode(h) / (2^32/N) or the equivalent
|
|
|
|
* right-shift, not ScrambleHashCode(h) % N or the equivalent bit-mask.
|
|
|
|
*
|
|
|
|
* FIXME: OrderedHashTable uses a bit-mask; see bug 775896.
|
|
|
|
*/
|
|
|
|
inline HashNumber
|
|
|
|
ScrambleHashCode(HashNumber h)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Simply returning h would not cause any hash tables to produce wrong
|
|
|
|
* answers. But it can produce pathologically bad performance: The caller
|
|
|
|
* right-shifts the result, keeping only the highest bits. The high bits of
|
|
|
|
* hash codes are very often completely entropy-free. (So are the lowest
|
|
|
|
* bits.)
|
|
|
|
*
|
|
|
|
* So we use Fibonacci hashing, as described in Knuth, The Art of Computer
|
|
|
|
* Programming, 6.4. This mixes all the bits of the input hash code h.
|
2015-05-22 20:52:38 +03:00
|
|
|
*
|
2012-07-04 01:33:38 +04:00
|
|
|
* The value of goldenRatio is taken from the hex
|
|
|
|
* expansion of the golden ratio, which starts 1.9E3779B9....
|
|
|
|
* This value is especially good if values with consecutive hash codes
|
|
|
|
* are stored in a hash table; see Knuth for details.
|
|
|
|
*/
|
|
|
|
static const HashNumber goldenRatio = 0x9E3779B9U;
|
|
|
|
return h * goldenRatio;
|
|
|
|
}
|
|
|
|
|
|
|
|
} /* namespace detail */
|
|
|
|
|
2011-10-05 02:33:00 +04:00
|
|
|
} /* namespace js */
|
|
|
|
|
|
|
|
/* sixgill annotation defines */
|
|
|
|
#ifndef HAVE_STATIC_ANNOTATIONS
|
|
|
|
# define HAVE_STATIC_ANNOTATIONS
|
|
|
|
# ifdef XGILL_PLUGIN
|
|
|
|
# define STATIC_PRECONDITION(COND) __attribute__((precondition(#COND)))
|
|
|
|
# define STATIC_PRECONDITION_ASSUME(COND) __attribute__((precondition_assume(#COND)))
|
|
|
|
# define STATIC_POSTCONDITION(COND) __attribute__((postcondition(#COND)))
|
|
|
|
# define STATIC_POSTCONDITION_ASSUME(COND) __attribute__((postcondition_assume(#COND)))
|
|
|
|
# define STATIC_INVARIANT(COND) __attribute__((invariant(#COND)))
|
|
|
|
# define STATIC_INVARIANT_ASSUME(COND) __attribute__((invariant_assume(#COND)))
|
|
|
|
# define STATIC_ASSUME(COND) \
|
|
|
|
JS_BEGIN_MACRO \
|
|
|
|
__attribute__((assume_static(#COND), unused)) \
|
|
|
|
int STATIC_PASTE1(assume_static_, __COUNTER__); \
|
|
|
|
JS_END_MACRO
|
|
|
|
# else /* XGILL_PLUGIN */
|
|
|
|
# define STATIC_PRECONDITION(COND) /* nothing */
|
|
|
|
# define STATIC_PRECONDITION_ASSUME(COND) /* nothing */
|
|
|
|
# define STATIC_POSTCONDITION(COND) /* nothing */
|
|
|
|
# define STATIC_POSTCONDITION_ASSUME(COND) /* nothing */
|
|
|
|
# define STATIC_INVARIANT(COND) /* nothing */
|
|
|
|
# define STATIC_INVARIANT_ASSUME(COND) /* nothing */
|
|
|
|
# define STATIC_ASSUME(COND) JS_BEGIN_MACRO /* nothing */ JS_END_MACRO
|
|
|
|
# endif /* XGILL_PLUGIN */
|
|
|
|
# define STATIC_SKIP_INFERENCE STATIC_INVARIANT(skip_inference())
|
|
|
|
#endif /* HAVE_STATIC_ANNOTATIONS */
|
|
|
|
|
2013-06-20 04:59:09 +04:00
|
|
|
#endif /* js_Utility_h */
|