mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
bug 1366287 - Part 2.0: Use GMP integers to represent BigInt values. r=jwalden
Also link to libgmp and initialize it with custom memory allocation functions. --HG-- extra : rebase_source : 3aab0578a0b9e61c4aea5c7b7d1d572316f63b46
This commit is contained in:
parent
798233c7bc
commit
f6e5382e6a
@ -1335,6 +1335,11 @@ if CONFIG['MOZ_SYSTEM_ICU']:
|
||||
'unicode/utypes.h',
|
||||
]
|
||||
|
||||
if CONFIG['ENABLE_BIGINT']:
|
||||
system_headers += [
|
||||
'gmp.h'
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WAYLAND']:
|
||||
system_headers += [
|
||||
'wayland-client.h',
|
||||
|
@ -34,6 +34,11 @@ if CONFIG['ENABLE_INTL_API']:
|
||||
'icu',
|
||||
]
|
||||
|
||||
if CONFIG['ENABLE_BIGINT']:
|
||||
OS_LIBS += [
|
||||
'gmp',
|
||||
]
|
||||
|
||||
USE_LIBS += [
|
||||
'nspr',
|
||||
'zlib',
|
||||
|
@ -9,43 +9,82 @@
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/HashFunctions.h"
|
||||
|
||||
#include <gmp.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "jsapi.h"
|
||||
|
||||
#include "gc/Allocator.h"
|
||||
#include "gc/Tracer.h"
|
||||
#include "js/Utility.h"
|
||||
#include "vm/JSContext.h"
|
||||
#include "vm/SelfHosting.h"
|
||||
|
||||
using namespace js;
|
||||
|
||||
// The following functions are wrappers for use with
|
||||
// mp_set_memory_functions. GMP passes extra arguments to the realloc
|
||||
// and free functions not needed by the JS allocation interface.
|
||||
// js_malloc has the signature expected for GMP's malloc function, so no
|
||||
// wrapper is required.
|
||||
|
||||
static void*
|
||||
js_mp_realloc(void* ptr, size_t old_size, size_t new_size)
|
||||
{
|
||||
return js_realloc(ptr, new_size);
|
||||
}
|
||||
|
||||
static void
|
||||
js_mp_free(void* ptr, size_t size)
|
||||
{
|
||||
return js_free(ptr);
|
||||
}
|
||||
|
||||
void
|
||||
BigInt::init()
|
||||
{
|
||||
mp_set_memory_functions(js_malloc, js_mp_realloc, js_mp_free);
|
||||
}
|
||||
|
||||
BigInt*
|
||||
BigInt::create(JSContext* cx)
|
||||
{
|
||||
BigInt* x = Allocate<BigInt>(cx);
|
||||
if (!x)
|
||||
return nullptr;
|
||||
mpz_init(x->num_); // to zero
|
||||
return x;
|
||||
}
|
||||
|
||||
BigInt*
|
||||
BigInt::copy(JSContext* cx, HandleBigInt x)
|
||||
{
|
||||
BigInt* bi = create(cx);
|
||||
BigInt* bi = Allocate<BigInt>(cx);
|
||||
if (!bi)
|
||||
return nullptr;
|
||||
mpz_init_set(bi->num_, x->num_);
|
||||
return bi;
|
||||
}
|
||||
|
||||
JSLinearString*
|
||||
BigInt::toString(JSContext* cx, BigInt* x)
|
||||
{
|
||||
return nullptr;
|
||||
// We need two extra chars for '\0' and potentially '-'.
|
||||
size_t strSize = mpz_sizeinbase(x->num_, 10) + 2;
|
||||
UniqueChars str(static_cast<char*>(js_malloc(strSize)));
|
||||
if (!str) {
|
||||
ReportOutOfMemory(cx);
|
||||
return nullptr;
|
||||
}
|
||||
mpz_get_str(str.get(), 10, x->num_);
|
||||
|
||||
return NewStringCopyZ<CanGC>(cx, str.get());
|
||||
}
|
||||
|
||||
void
|
||||
BigInt::finalize(js::FreeOp* fop)
|
||||
{
|
||||
return;
|
||||
mpz_clear(num_);
|
||||
}
|
||||
|
||||
JSAtom*
|
||||
@ -60,24 +99,35 @@ js::BigIntToAtom(JSContext* cx, BigInt* bi)
|
||||
bool
|
||||
BigInt::toBoolean()
|
||||
{
|
||||
return false;
|
||||
return mpz_sgn(num_) != 0;
|
||||
}
|
||||
|
||||
js::HashNumber
|
||||
BigInt::hash()
|
||||
{
|
||||
return 0;
|
||||
const mp_limb_t* limbs = mpz_limbs_read(num_);
|
||||
size_t limbCount = mpz_size(num_);
|
||||
uint32_t hash = mozilla::HashBytes(limbs, limbCount * sizeof(mp_limb_t));
|
||||
hash = mozilla::AddToHash(hash, mpz_sgn(num_));
|
||||
return hash;
|
||||
}
|
||||
|
||||
size_t
|
||||
BigInt::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
|
||||
{
|
||||
return 0;
|
||||
// Use the total number of limbs allocated when calculating the size
|
||||
// (_mp_alloc), not the number of limbs currently in use (_mp_size).
|
||||
// See the Info node `(gmp)Integer Internals` for details.
|
||||
mpz_srcptr n = static_cast<mpz_srcptr>(num_);
|
||||
return sizeof(*n) + sizeof(mp_limb_t) * n->_mp_alloc;
|
||||
}
|
||||
|
||||
JS::ubi::Node::Size
|
||||
JS::ubi::Concrete<BigInt>::size(mozilla::MallocSizeOf mallocSizeOf) const
|
||||
{
|
||||
MOZ_ASSERT(get().isTenured());
|
||||
return js::gc::Arena::thingSize(get().asTenured().getAllocKind());
|
||||
BigInt& bi = get();
|
||||
MOZ_ASSERT(bi.isTenured());
|
||||
size_t size = js::gc::Arena::thingSize(bi.asTenured().getAllocKind());
|
||||
size += bi.sizeOfExcludingThis(mallocSizeOf);
|
||||
return size;
|
||||
}
|
||||
|
@ -7,6 +7,8 @@
|
||||
#ifndef vm_BigIntType_h
|
||||
#define vm_BigIntType_h
|
||||
|
||||
#include <gmp.h>
|
||||
|
||||
#include "gc/Barrier.h"
|
||||
#include "gc/GC.h"
|
||||
#include "gc/Heap.h"
|
||||
@ -23,7 +25,10 @@ class BigInt final : public js::gc::TenuredCell
|
||||
private:
|
||||
// The minimum allocation size is currently 16 bytes (see
|
||||
// SortedArenaList in gc/ArenaList.h).
|
||||
uint8_t unused_[js::gc::MinCellSize];
|
||||
union {
|
||||
mpz_t num_;
|
||||
uint8_t unused_[js::gc::MinCellSize];
|
||||
};
|
||||
|
||||
public:
|
||||
// Allocate and initialize a BigInt value
|
||||
@ -42,6 +47,8 @@ class BigInt final : public js::gc::TenuredCell
|
||||
static JSLinearString* toString(JSContext* cx, BigInt* x);
|
||||
bool toBoolean();
|
||||
|
||||
static void init();
|
||||
|
||||
static BigInt* copy(JSContext* cx, Handle<BigInt*> x);
|
||||
};
|
||||
|
||||
|
@ -25,6 +25,9 @@
|
||||
#include "unicode/uclean.h"
|
||||
#include "unicode/utypes.h"
|
||||
#endif // ENABLE_INTL_API
|
||||
#ifdef ENABLE_BIGINT
|
||||
#include "vm/BigIntType.h"
|
||||
#endif
|
||||
#include "vm/DateTime.h"
|
||||
#include "vm/HelperThreads.h"
|
||||
#include "vm/Runtime.h"
|
||||
@ -134,6 +137,10 @@ JS::detail::InitWithFailureDiagnostic(bool isDebugBuild)
|
||||
RETURN_IF_FAIL(js::jit::SimulatorProcess::initialize());
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_BIGINT
|
||||
JS::BigInt::init();
|
||||
#endif
|
||||
|
||||
libraryInitState = InitState::Running;
|
||||
return nullptr;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user