2009-07-10 12:58:34 -07:00
|
|
|
/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
|
|
|
|
/* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
|
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version 1.1 (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.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
|
|
|
|
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
|
|
|
|
* language governing rights and limitations under the License.
|
|
|
|
*
|
|
|
|
* The Original Code is [Open Source Virtual Machine.]
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is Adobe System Incorporated. Portions created
|
|
|
|
* by the Initial Developer are Copyright (C)[ 2004-2006 ] Adobe Systems Incorporated. All Rights
|
|
|
|
* Reserved.
|
2008-06-18 19:55:26 -07:00
|
|
|
*
|
|
|
|
* Contributor(s): Adobe AS3 Team
|
2008-06-28 09:58:15 -07:00
|
|
|
* Andreas Gal <gal@mozilla.com>
|
2008-09-02 10:15:26 -07:00
|
|
|
* Asko Tontti <atontti@cc.hut.fi>
|
2009-07-10 12:58:34 -07:00
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of either the GNU
|
|
|
|
* General Public License Version 2 or later (the "GPL"), or the GNU Lesser General Public
|
|
|
|
* License Version 2.1 or later (the "LGPL"), in which case the provisions of the GPL or the
|
|
|
|
* LGPL are applicable instead of those above. If you wish to allow use of your version of this
|
|
|
|
* file only under the terms of either the GPL or the LGPL, and not to allow others to use your
|
|
|
|
* version of this file under the terms of the MPL, indicate your decision by deleting provisions
|
|
|
|
* above and replace them with the notice and other provisions required by the GPL or the
|
|
|
|
* LGPL. If you do not delete the provisions above, a recipient may use your version of this file
|
|
|
|
* under the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
*
|
2008-06-18 19:55:26 -07:00
|
|
|
***** END LICENSE BLOCK ***** */
|
|
|
|
|
|
|
|
#ifndef avm_h___
|
|
|
|
#define avm_h___
|
|
|
|
|
|
|
|
#include <assert.h>
|
2008-06-18 20:29:01 -07:00
|
|
|
#include <string.h>
|
2008-06-19 10:47:58 -07:00
|
|
|
#include <stdio.h>
|
2009-09-18 13:31:09 -07:00
|
|
|
#include <ctype.h>
|
2008-07-10 07:03:45 -07:00
|
|
|
#include <stdlib.h>
|
2008-09-02 10:15:26 -07:00
|
|
|
|
2009-08-19 04:42:46 -07:00
|
|
|
#if defined(AVMPLUS_UNIX) || defined(AVMPLUS_OS2)
|
2008-09-02 10:15:26 -07:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/mman.h>
|
|
|
|
#endif
|
|
|
|
|
2008-06-18 19:55:26 -07:00
|
|
|
#include "jstypes.h"
|
Bug 479258: Don't define <stdint.h> types in public headers. r=brendan
On systems that don't have <stdint.h> (i.e., Microsoft, which is
tragically underfunded and cannot spare the resources necessary to
provide and support this header: http://tinyurl.com/absoh8),
SpiderMonkey header files should not introduce definitions for these
types, as doing so may conflict with client code's attempts to provide
its own definitions for these types.
Instead, have jstypes.h define JS{Int,Uint}{8,16,32,64,Ptr} types
based on configure's results, and make jsstdint.h into an uninstalled
header for use within SpiderMonkey that does whatever is necessary to
get definitions for the <stdint.h> types.
The changes to make the appropriate SpiderMonkey .cpp files #include
"jsstdint.h" explicitly are in a separate patch, for ease of review.
2009-03-18 11:38:15 -07:00
|
|
|
#include "jsstdint.h"
|
2008-06-18 19:55:26 -07:00
|
|
|
|
2009-02-15 18:10:03 -08:00
|
|
|
#if !defined(AVMPLUS_LITTLE_ENDIAN) && !defined(AVMPLUS_BIG_ENDIAN)
|
|
|
|
#ifdef IS_BIG_ENDIAN
|
|
|
|
#define AVMPLUS_BIG_ENDIAN
|
|
|
|
#else
|
|
|
|
#define AVMPLUS_LITTLE_ENDIAN
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2008-08-10 00:39:18 -07:00
|
|
|
#define FASTCALL JS_FASTCALL
|
|
|
|
|
2008-09-02 11:43:55 -07:00
|
|
|
#if defined(JS_NO_FASTCALL)
|
|
|
|
#define NJ_NO_FASTCALL
|
|
|
|
#if defined(AVMPLUS_IA32)
|
|
|
|
#define SIMULATE_FASTCALL(lr, state_ptr, frag_ptr, func_addr) \
|
|
|
|
asm volatile( \
|
|
|
|
"call *%%esi" \
|
|
|
|
: "=a" (lr) \
|
|
|
|
: "c" (state_ptr), "d" (frag_ptr), "S" (func_addr) \
|
|
|
|
: "memory", "cc" \
|
|
|
|
);
|
|
|
|
#endif /* defined(AVMPLUS_IA32) */
|
|
|
|
#endif /* defined(JS_NO_FASTCALL) */
|
|
|
|
|
2008-09-02 10:28:14 -07:00
|
|
|
#ifdef WIN32
|
2008-07-10 15:39:51 -07:00
|
|
|
#include <windows.h>
|
2009-08-24 01:21:37 -07:00
|
|
|
#elif defined(AVMPLUS_OS2)
|
|
|
|
#define INCL_DOSMEMMGR
|
|
|
|
#include <os2.h>
|
2008-06-18 20:45:37 -07:00
|
|
|
#endif
|
|
|
|
|
2009-07-15 12:31:26 -07:00
|
|
|
#if defined(DEBUG) || defined(MOZ_NO_VARADIC_MACROS)
|
2008-07-29 17:19:51 -07:00
|
|
|
#if !defined _DEBUG
|
2008-06-19 15:32:40 -07:00
|
|
|
#define _DEBUG
|
2008-07-29 17:19:51 -07:00
|
|
|
#endif
|
2008-09-24 10:21:49 -07:00
|
|
|
#define NJ_VERBOSE 1
|
|
|
|
#define NJ_PROFILE 1
|
2008-06-19 15:32:40 -07:00
|
|
|
#include <stdarg.h>
|
|
|
|
#endif
|
2008-06-19 10:47:58 -07:00
|
|
|
|
2008-08-28 19:07:49 -07:00
|
|
|
#ifdef _DEBUG
|
|
|
|
void NanoAssertFail();
|
|
|
|
#endif
|
|
|
|
|
2008-06-18 19:55:26 -07:00
|
|
|
#define AvmAssert(x) assert(x)
|
2009-07-10 12:58:34 -07:00
|
|
|
#define AvmAssertMsg(x, y)
|
2008-06-19 10:47:58 -07:00
|
|
|
#define AvmDebugLog(x) printf x
|
2008-06-18 19:55:26 -07:00
|
|
|
|
2008-09-05 16:56:03 -07:00
|
|
|
#if defined(AVMPLUS_IA32)
|
|
|
|
#if defined(_MSC_VER)
|
2008-07-29 17:19:51 -07:00
|
|
|
__declspec(naked) static inline __int64 rdtsc()
|
|
|
|
{
|
|
|
|
__asm
|
|
|
|
{
|
|
|
|
rdtsc;
|
|
|
|
ret;
|
|
|
|
}
|
|
|
|
}
|
2008-09-05 16:56:03 -07:00
|
|
|
#elif defined(SOLARIS)
|
|
|
|
static inline unsigned long long rdtsc(void)
|
|
|
|
{
|
|
|
|
unsigned long long int x;
|
|
|
|
asm volatile (".byte 0x0f, 0x31" : "=A" (x));
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
#elif defined(__i386__)
|
2008-07-01 02:37:07 -07:00
|
|
|
static __inline__ unsigned long long rdtsc(void)
|
|
|
|
{
|
|
|
|
unsigned long long int x;
|
|
|
|
__asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
|
|
|
|
return x;
|
|
|
|
}
|
2008-09-05 16:56:03 -07:00
|
|
|
#endif /* compilers */
|
|
|
|
|
2008-07-01 02:37:07 -07:00
|
|
|
#elif defined(__x86_64__)
|
|
|
|
|
2008-08-18 12:41:55 -07:00
|
|
|
static __inline__ uint64_t rdtsc(void)
|
2008-07-01 02:37:07 -07:00
|
|
|
{
|
|
|
|
unsigned hi, lo;
|
|
|
|
__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
|
2008-08-18 12:41:55 -07:00
|
|
|
return ( (uint64_t)lo)|( ((uint64_t)hi)<<32 );
|
2008-07-01 02:37:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#elif defined(__powerpc__)
|
|
|
|
|
|
|
|
typedef unsigned long long int unsigned long long;
|
|
|
|
|
|
|
|
static __inline__ unsigned long long rdtsc(void)
|
|
|
|
{
|
|
|
|
unsigned long long int result=0;
|
|
|
|
unsigned long int upper, lower,tmp;
|
|
|
|
__asm__ volatile(
|
|
|
|
"0: \n"
|
|
|
|
"\tmftbu %0 \n"
|
|
|
|
"\tmftb %1 \n"
|
|
|
|
"\tmftbu %2 \n"
|
|
|
|
"\tcmpw %2,%0 \n"
|
|
|
|
"\tbne 0b \n"
|
|
|
|
: "=r"(upper),"=r"(lower),"=r"(tmp)
|
|
|
|
);
|
|
|
|
result = upper;
|
|
|
|
result = result<<32;
|
|
|
|
result = result|lower;
|
|
|
|
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
2008-09-05 16:56:03 -07:00
|
|
|
#endif /* architecture */
|
2008-07-01 02:37:07 -07:00
|
|
|
|
2008-07-08 17:16:51 -07:00
|
|
|
struct JSContext;
|
|
|
|
|
2009-09-18 13:31:09 -07:00
|
|
|
#ifdef PERFM
|
|
|
|
# define PERFM_NVPROF(n,v) _nvprof(n,v)
|
|
|
|
# define PERFM_NTPROF(n) _ntprof(n)
|
|
|
|
# define PERFM_TPROF_END() _tprof_end()
|
|
|
|
#else
|
|
|
|
# define PERFM_NVPROF(n,v)
|
|
|
|
# define PERFM_NTPROF(n)
|
|
|
|
# define PERFM_TPROF_END()
|
|
|
|
#endif
|
|
|
|
|
2009-07-15 09:34:17 -07:00
|
|
|
#define VMPI_strlen strlen
|
|
|
|
#define VMPI_strcat strcat
|
2009-09-17 18:13:05 -07:00
|
|
|
#define VMPI_strncat strncat
|
2009-07-15 09:34:17 -07:00
|
|
|
#define VMPI_strcpy strcpy
|
|
|
|
#define VMPI_sprintf sprintf
|
2009-08-04 07:18:25 -07:00
|
|
|
#define VMPI_memset memset
|
2009-09-18 13:31:09 -07:00
|
|
|
#define VMPI_isdigit isdigit
|
|
|
|
#define VMPI_getDate()
|
2009-07-15 09:34:17 -07:00
|
|
|
|
2009-07-15 16:50:01 -07:00
|
|
|
extern void VMPI_setPageProtection(void *address,
|
|
|
|
size_t size,
|
|
|
|
bool executableFlag,
|
|
|
|
bool writeableFlag);
|
|
|
|
|
2009-07-16 11:50:27 -07:00
|
|
|
namespace avmplus {
|
|
|
|
|
2008-11-07 15:52:51 -08:00
|
|
|
typedef int FunctionID;
|
2008-06-19 10:47:58 -07:00
|
|
|
|
2009-07-15 16:50:01 -07:00
|
|
|
extern void AvmLog(char const *msg, ...);
|
|
|
|
|
2008-12-10 17:19:40 -08:00
|
|
|
class Config
|
2008-06-19 10:47:58 -07:00
|
|
|
{
|
|
|
|
public:
|
2008-12-10 17:19:40 -08:00
|
|
|
Config() {
|
|
|
|
memset(this, 0, sizeof(Config));
|
2008-06-19 15:32:40 -07:00
|
|
|
#ifdef DEBUG
|
2009-06-24 20:32:00 -07:00
|
|
|
verbose = false;
|
2008-06-19 15:32:40 -07:00
|
|
|
verbose_addrs = 1;
|
|
|
|
verbose_exits = 1;
|
|
|
|
verbose_live = 1;
|
|
|
|
show_stats = 1;
|
|
|
|
#endif
|
2008-06-19 10:47:58 -07:00
|
|
|
}
|
2009-07-10 12:58:34 -07:00
|
|
|
|
2008-06-19 10:47:58 -07:00
|
|
|
uint32_t tree_opt:1;
|
2008-06-19 15:32:40 -07:00
|
|
|
uint32_t quiet_opt:1;
|
|
|
|
uint32_t verbose:1;
|
|
|
|
uint32_t verbose_addrs:1;
|
|
|
|
uint32_t verbose_live:1;
|
|
|
|
uint32_t verbose_exits:1;
|
|
|
|
uint32_t show_stats:1;
|
2008-12-10 17:19:40 -08:00
|
|
|
|
2009-06-10 15:21:10 -07:00
|
|
|
#if defined (AVMPLUS_IA32)
|
2009-07-10 12:58:34 -07:00
|
|
|
// Whether or not we can use SSE2 instructions and conditional moves.
|
2009-03-20 15:53:33 -07:00
|
|
|
bool sse2;
|
|
|
|
bool use_cmov;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined (AVMPLUS_ARM)
|
2009-05-09 13:14:38 -07:00
|
|
|
// Whether or not to generate VFP instructions.
|
2009-03-20 15:53:33 -07:00
|
|
|
# if defined (NJ_FORCE_SOFTFLOAT)
|
|
|
|
static const bool vfp = false;
|
|
|
|
# else
|
|
|
|
bool vfp;
|
|
|
|
# endif
|
|
|
|
|
2009-05-09 13:14:38 -07:00
|
|
|
// The ARM architecture version.
|
|
|
|
# if defined (NJ_FORCE_ARM_ARCH_VERSION)
|
|
|
|
static const unsigned int arch = NJ_FORCE_ARM_ARCH_VERSION;
|
2009-03-20 15:53:33 -07:00
|
|
|
# else
|
2009-05-09 13:14:38 -07:00
|
|
|
unsigned int arch;
|
2009-03-20 15:53:33 -07:00
|
|
|
# endif
|
2009-05-09 13:14:38 -07:00
|
|
|
|
|
|
|
// Support for Thumb, even if it isn't used by nanojit. This is used to
|
|
|
|
// determine whether or not to generate interworking branches.
|
|
|
|
# if defined (NJ_FORCE_NO_ARM_THUMB)
|
|
|
|
static const bool thumb = false;
|
|
|
|
# else
|
|
|
|
bool thumb;
|
|
|
|
# endif
|
|
|
|
|
|
|
|
// Support for Thumb2, even if it isn't used by nanojit. This is used to
|
|
|
|
// determine whether or not to use some of the ARMv6T2 instructions.
|
|
|
|
# if defined (NJ_FORCE_NO_ARM_THUMB2)
|
|
|
|
static const bool thumb2 = false;
|
|
|
|
# else
|
|
|
|
bool thumb2;
|
|
|
|
# endif
|
|
|
|
|
2009-03-20 15:53:33 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined (NJ_FORCE_SOFTFLOAT)
|
|
|
|
static const bool soft_float = true;
|
|
|
|
#else
|
|
|
|
bool soft_float;
|
|
|
|
#endif
|
2008-06-19 15:32:40 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
static const int kstrconst_emptyString = 0;
|
|
|
|
|
|
|
|
class AvmInterpreter
|
|
|
|
{
|
|
|
|
class Labels {
|
|
|
|
public:
|
2008-07-07 02:47:40 -07:00
|
|
|
const char* format(const void* ip)
|
2008-06-19 15:32:40 -07:00
|
|
|
{
|
|
|
|
static char buf[33];
|
|
|
|
sprintf(buf, "%p", ip);
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Labels _labels;
|
|
|
|
public:
|
|
|
|
Labels* labels;
|
|
|
|
|
|
|
|
AvmInterpreter()
|
|
|
|
{
|
|
|
|
labels = &_labels;
|
|
|
|
}
|
|
|
|
|
2008-06-19 10:47:58 -07:00
|
|
|
};
|
2009-07-10 12:58:34 -07:00
|
|
|
|
|
|
|
class AvmConsole
|
2008-06-18 20:29:01 -07:00
|
|
|
{
|
2008-06-19 10:47:58 -07:00
|
|
|
public:
|
2008-06-19 15:32:40 -07:00
|
|
|
AvmConsole& operator<<(const char* s)
|
|
|
|
{
|
2008-07-18 14:13:31 -07:00
|
|
|
fprintf(stdout, "%s", s);
|
2008-06-19 15:32:40 -07:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class AvmCore
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
AvmInterpreter interp;
|
|
|
|
AvmConsole console;
|
2009-07-10 12:58:34 -07:00
|
|
|
|
2008-12-10 17:19:40 -08:00
|
|
|
static Config config;
|
2008-06-19 15:32:40 -07:00
|
|
|
|
2009-06-10 15:21:10 -07:00
|
|
|
#ifdef AVMPLUS_IA32
|
2008-06-19 15:32:40 -07:00
|
|
|
static inline bool
|
|
|
|
use_sse2()
|
2008-06-19 10:47:58 -07:00
|
|
|
{
|
2008-12-10 17:19:40 -08:00
|
|
|
return config.sse2;
|
2008-06-19 10:47:58 -07:00
|
|
|
}
|
2009-06-10 15:21:10 -07:00
|
|
|
#endif
|
2009-07-10 12:58:34 -07:00
|
|
|
|
2008-09-26 20:39:21 -07:00
|
|
|
static inline bool
|
|
|
|
use_cmov()
|
|
|
|
{
|
2009-06-10 15:21:10 -07:00
|
|
|
#ifdef AVMPLUS_IA32
|
2008-12-10 17:19:40 -08:00
|
|
|
return config.use_cmov;
|
2009-06-10 15:21:10 -07:00
|
|
|
#else
|
2009-07-10 12:58:34 -07:00
|
|
|
return true;
|
2008-12-11 13:50:55 -08:00
|
|
|
#endif
|
2009-06-10 15:21:10 -07:00
|
|
|
}
|
2008-06-19 10:47:58 -07:00
|
|
|
|
2008-06-19 15:32:40 -07:00
|
|
|
static inline bool
|
|
|
|
quiet_opt()
|
|
|
|
{
|
|
|
|
return config.quiet_opt;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
verbose()
|
|
|
|
{
|
|
|
|
return config.verbose;
|
|
|
|
}
|
|
|
|
|
2008-06-18 20:29:01 -07:00
|
|
|
};
|
2008-06-19 15:32:40 -07:00
|
|
|
|
2008-06-18 20:29:01 -07:00
|
|
|
/**
|
2009-07-10 12:58:34 -07:00
|
|
|
* Bit vectors are an efficent method of keeping True/False information
|
|
|
|
* on a set of items or conditions. Class BitSet provides functions
|
2008-06-18 20:29:01 -07:00
|
|
|
* to manipulate individual bits in the vector.
|
|
|
|
*
|
|
|
|
* Since most vectors are rather small an array of longs is used by
|
|
|
|
* default to house the value of the bits. If more bits are needed
|
2009-07-10 12:58:34 -07:00
|
|
|
* then an array is allocated dynamically outside of this object.
|
|
|
|
*
|
2008-06-18 20:29:01 -07:00
|
|
|
* This object is not optimized for a fixed sized bit vector
|
|
|
|
* it instead allows for dynamically growing the bit vector.
|
2009-07-10 12:58:34 -07:00
|
|
|
*/
|
2008-06-18 20:29:01 -07:00
|
|
|
class BitSet
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
enum { kUnit = 8*sizeof(long),
|
|
|
|
kDefaultCapacity = 4 };
|
|
|
|
|
|
|
|
BitSet()
|
|
|
|
{
|
|
|
|
capacity = kDefaultCapacity;
|
|
|
|
reset();
|
|
|
|
}
|
2009-07-10 12:58:34 -07:00
|
|
|
|
2008-06-18 20:29:01 -07:00
|
|
|
~BitSet()
|
|
|
|
{
|
|
|
|
if (capacity > kDefaultCapacity)
|
2008-09-23 18:12:53 -07:00
|
|
|
free(bits.ptr);
|
2008-06-18 20:29:01 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void reset()
|
|
|
|
{
|
|
|
|
if (capacity > kDefaultCapacity)
|
|
|
|
for(int i=0; i<capacity; i++)
|
|
|
|
bits.ptr[i] = 0;
|
|
|
|
else
|
|
|
|
for(int i=0; i<capacity; i++)
|
|
|
|
bits.ar[i] = 0;
|
|
|
|
}
|
|
|
|
|
2009-07-08 13:21:55 -07:00
|
|
|
void set(int bitNbr)
|
2008-06-18 20:29:01 -07:00
|
|
|
{
|
|
|
|
int index = bitNbr / kUnit;
|
|
|
|
int bit = bitNbr % kUnit;
|
|
|
|
if (index >= capacity)
|
2009-07-08 13:21:55 -07:00
|
|
|
grow(index+1);
|
2008-06-18 20:29:01 -07:00
|
|
|
|
|
|
|
if (capacity > kDefaultCapacity)
|
|
|
|
bits.ptr[index] |= (1<<bit);
|
|
|
|
else
|
|
|
|
bits.ar[index] |= (1<<bit);
|
|
|
|
}
|
|
|
|
|
|
|
|
void clear(int bitNbr)
|
|
|
|
{
|
|
|
|
int index = bitNbr / kUnit;
|
|
|
|
int bit = bitNbr % kUnit;
|
|
|
|
if (index < capacity)
|
|
|
|
{
|
|
|
|
if (capacity > kDefaultCapacity)
|
|
|
|
bits.ptr[index] &= ~(1<<bit);
|
|
|
|
else
|
|
|
|
bits.ar[index] &= ~(1<<bit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool get(int bitNbr) const
|
|
|
|
{
|
|
|
|
int index = bitNbr / kUnit;
|
|
|
|
int bit = bitNbr % kUnit;
|
|
|
|
bool value = false;
|
|
|
|
if (index < capacity)
|
|
|
|
{
|
|
|
|
if (capacity > kDefaultCapacity)
|
|
|
|
value = ( bits.ptr[index] & (1<<bit) ) ? true : false;
|
|
|
|
else
|
|
|
|
value = ( bits.ar[index] & (1<<bit) ) ? true : false;
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
// Grow the array until at least newCapacity big
|
2009-07-08 13:21:55 -07:00
|
|
|
void grow(int newCapacity)
|
2008-06-18 20:29:01 -07:00
|
|
|
{
|
2009-07-10 12:58:34 -07:00
|
|
|
// create vector that is 2x bigger than requested
|
2008-06-18 20:29:01 -07:00
|
|
|
newCapacity *= 2;
|
|
|
|
//MEMTAG("BitVector::Grow - long[]");
|
2008-07-01 02:37:07 -07:00
|
|
|
long* newBits = (long*)calloc(1, newCapacity * sizeof(long));
|
|
|
|
//memset(newBits, 0, newCapacity * sizeof(long));
|
2008-06-18 20:29:01 -07:00
|
|
|
|
2009-07-10 12:58:34 -07:00
|
|
|
// copy the old one
|
2008-06-18 20:29:01 -07:00
|
|
|
if (capacity > kDefaultCapacity)
|
|
|
|
for(int i=0; i<capacity; i++)
|
|
|
|
newBits[i] = bits.ptr[i];
|
|
|
|
else
|
|
|
|
for(int i=0; i<capacity; i++)
|
|
|
|
newBits[i] = bits.ar[i];
|
|
|
|
|
|
|
|
// in with the new out with the old
|
|
|
|
if (capacity > kDefaultCapacity)
|
2008-07-01 02:37:07 -07:00
|
|
|
free(bits.ptr);
|
2008-06-18 20:29:01 -07:00
|
|
|
|
|
|
|
bits.ptr = newBits;
|
|
|
|
capacity = newCapacity;
|
|
|
|
}
|
|
|
|
|
2009-07-10 12:58:34 -07:00
|
|
|
// by default we use the array, but if the vector
|
2008-06-18 20:29:01 -07:00
|
|
|
// size grows beyond kDefaultCapacity we allocate
|
|
|
|
// space dynamically.
|
|
|
|
int capacity;
|
|
|
|
union
|
|
|
|
{
|
|
|
|
long ar[kDefaultCapacity];
|
|
|
|
long* ptr;
|
|
|
|
}
|
|
|
|
bits;
|
|
|
|
};
|
2008-06-18 19:55:26 -07:00
|
|
|
}
|
|
|
|
|
2008-06-18 20:29:01 -07:00
|
|
|
#endif
|