2008-06-30 15:33:41 -07:00
|
|
|
/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */
|
2008-06-18 20:49:37 -07:00
|
|
|
/* ***** 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-2007
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
* Adobe AS3 Team
|
|
|
|
*
|
|
|
|
* 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 the 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.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
2008-07-07 02:47:40 -07:00
|
|
|
#ifndef __nanojit_h__
|
2008-06-18 20:49:37 -07:00
|
|
|
#define __nanojit_h__
|
|
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
#include "avmplus.h"
|
|
|
|
|
2008-10-13 13:29:18 -07:00
|
|
|
#ifdef FEATURE_NANOJIT
|
|
|
|
|
2008-06-18 20:49:37 -07:00
|
|
|
#ifdef AVMPLUS_IA32
|
|
|
|
#define NANOJIT_IA32
|
|
|
|
#elif AVMPLUS_ARM
|
|
|
|
#define NANOJIT_ARM
|
|
|
|
#elif AVMPLUS_PPC
|
|
|
|
#define NANOJIT_PPC
|
2009-02-15 18:10:03 -08:00
|
|
|
#elif AVMPLUS_SPARC
|
|
|
|
#define NANOJIT_SPARC
|
2008-06-30 15:33:41 -07:00
|
|
|
#elif AVMPLUS_AMD64
|
|
|
|
#define NANOJIT_AMD64
|
|
|
|
#define NANOJIT_64BIT
|
2008-06-18 20:49:37 -07:00
|
|
|
#else
|
|
|
|
#error "unknown nanojit architecture"
|
|
|
|
#endif
|
|
|
|
|
2008-10-20 15:51:13 -07:00
|
|
|
/*
|
|
|
|
If we're using MMGC, using operator delete on a GCFinalizedObject is problematic:
|
|
|
|
in particular, calling it from inside a dtor is risky because the dtor for the sub-object
|
|
|
|
might already have been called, wrecking its vtable and ending up in the wrong version
|
|
|
|
of operator delete (the global version rather than the class-specific one). Calling GC::Free
|
|
|
|
directly is fine (since it ignores the vtable), so we macro-ize to make the distinction.
|
|
|
|
|
|
|
|
macro-ization of operator new isn't strictly necessary, but is done to bottleneck both
|
|
|
|
sides of the new/delete pair to forestall future needs.
|
|
|
|
*/
|
|
|
|
#ifdef MMGC_API
|
|
|
|
|
|
|
|
// separate overloads because GCObject and GCFinalizedObjects have different dtors
|
|
|
|
// (GCFinalizedObject's is virtual, GCObject's is not)
|
|
|
|
inline void mmgc_delete(GCObject* o)
|
|
|
|
{
|
|
|
|
GC* g = GC::GetGC(o);
|
|
|
|
if (g->Collecting())
|
|
|
|
g->Free(o);
|
|
|
|
else
|
|
|
|
delete o;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void mmgc_delete(GCFinalizedObject* o)
|
|
|
|
{
|
|
|
|
GC* g = GC::GetGC(o);
|
|
|
|
if (g->Collecting())
|
|
|
|
g->Free(o);
|
|
|
|
else
|
|
|
|
delete o;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define NJ_NEW(gc, cls) new (gc) cls
|
|
|
|
#define NJ_DELETE(obj) do { mmgc_delete(obj); } while (0)
|
|
|
|
#else
|
|
|
|
#define NJ_NEW(gc, cls) new (gc) cls
|
|
|
|
#define NJ_DELETE(obj) do { delete obj; } while (0)
|
|
|
|
#endif
|
|
|
|
|
2009-03-05 13:24:03 -08:00
|
|
|
// Embed no-op macros that let Valgrind work with the JIT.
|
|
|
|
#ifdef MOZ_VALGRIND
|
|
|
|
# define JS_VALGRIND
|
|
|
|
#endif
|
|
|
|
#ifdef JS_VALGRIND
|
|
|
|
# include <valgrind/valgrind.h>
|
|
|
|
#else
|
|
|
|
# define VALGRIND_DISCARD_TRANSLATIONS(addr, szB)
|
|
|
|
#endif
|
|
|
|
|
2008-06-18 20:49:37 -07:00
|
|
|
namespace nanojit
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* -------------------------------------------
|
|
|
|
* START AVM bridging definitions
|
|
|
|
* -------------------------------------------
|
|
|
|
*/
|
|
|
|
class Fragment;
|
|
|
|
class LIns;
|
|
|
|
struct SideExit;
|
|
|
|
class RegAlloc;
|
2008-11-14 12:46:35 -08:00
|
|
|
struct Page;
|
2008-06-18 20:49:37 -07:00
|
|
|
typedef avmplus::AvmCore AvmCore;
|
|
|
|
typedef avmplus::OSDep OSDep;
|
2008-07-15 13:06:05 -07:00
|
|
|
typedef avmplus::GCSortedMap<const void*,Fragment*,avmplus::LIST_GCObjects> FragmentMap;
|
2008-06-18 20:49:37 -07:00
|
|
|
typedef avmplus::SortedMap<SideExit*,RegAlloc*,avmplus::LIST_GCObjects> RegAllocMap;
|
|
|
|
typedef avmplus::List<LIns*,avmplus::LIST_NonGCObjects> InsList;
|
|
|
|
typedef avmplus::List<char*, avmplus::LIST_GCObjects> StringList;
|
2008-11-14 12:46:35 -08:00
|
|
|
typedef avmplus::List<Page*,avmplus::LIST_NonGCObjects> PageList;
|
2008-06-18 20:49:37 -07:00
|
|
|
|
2008-10-13 13:29:18 -07:00
|
|
|
const uint32_t MAXARGS = 8;
|
|
|
|
|
2008-09-04 10:29:50 -07:00
|
|
|
#if defined(_MSC_VER) && _MSC_VER < 1400
|
|
|
|
static void NanoAssertMsgf(bool a,const char *f,...) {}
|
|
|
|
static void NanoAssertMsg(bool a,const char *m) {}
|
|
|
|
static void NanoAssert(bool a) {}
|
|
|
|
#elif defined(_DEBUG)
|
2008-06-18 20:49:37 -07:00
|
|
|
|
2008-08-28 16:57:49 -07:00
|
|
|
#define __NanoAssertMsgf(a, file_, line_, f, ...) \
|
|
|
|
if (!(a)) { \
|
|
|
|
fprintf(stderr, "Assertion failed: " f "%s (%s:%d)\n", __VA_ARGS__, #a, file_, line_); \
|
2008-08-28 19:07:49 -07:00
|
|
|
NanoAssertFail(); \
|
2008-08-28 16:57:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#define _NanoAssertMsgf(a, file_, line_, f, ...) __NanoAssertMsgf(a, file_, line_, f, __VA_ARGS__)
|
2008-06-18 20:49:37 -07:00
|
|
|
|
2008-08-28 16:57:49 -07:00
|
|
|
#define NanoAssertMsgf(a,f,...) do { __NanoAssertMsgf(a, __FILE__, __LINE__, f ": ", __VA_ARGS__); } while (0)
|
|
|
|
#define NanoAssertMsg(a,m) do { __NanoAssertMsgf(a, __FILE__, __LINE__, "\"%s\": ", m); } while (0)
|
|
|
|
#define NanoAssert(a) do { __NanoAssertMsgf(a, __FILE__, __LINE__, "%s", ""); } while (0)
|
2008-06-18 20:49:37 -07:00
|
|
|
#else
|
2008-08-28 17:15:51 -07:00
|
|
|
#define NanoAssertMsgf(a,f,...) do { } while (0) /* no semi */
|
|
|
|
#define NanoAssertMsg(a,m) do { } while (0) /* no semi */
|
|
|
|
#define NanoAssert(a) do { } while (0) /* no semi */
|
2008-06-18 20:49:37 -07:00
|
|
|
#endif
|
|
|
|
|
2008-11-08 01:45:50 -08:00
|
|
|
/*
|
|
|
|
* Sun Studio C++ compiler has a bug
|
|
|
|
* "sizeof expression not accepted as size of array parameter"
|
|
|
|
* The bug number is 6688515. It is not public yet.
|
|
|
|
* Turn off this assert for Sun Studio until this bug is fixed.
|
|
|
|
*/
|
|
|
|
#ifdef __SUNPRO_CC
|
|
|
|
#define NanoStaticAssert(condition)
|
|
|
|
#else
|
|
|
|
#define NanoStaticAssert(condition) \
|
|
|
|
extern void nano_static_assert(int arg[(condition) ? 1 : -1])
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2008-06-18 20:49:37 -07:00
|
|
|
/**
|
|
|
|
* -------------------------------------------
|
|
|
|
* END AVM bridging definitions
|
|
|
|
* -------------------------------------------
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef AVMPLUS_VERBOSE
|
|
|
|
#define NJ_VERBOSE 1
|
|
|
|
#define NJ_PROFILE 1
|
|
|
|
#endif
|
|
|
|
|
2008-12-13 15:45:38 -08:00
|
|
|
#if defined(_MSC_VER) && _MSC_VER < 1400
|
|
|
|
#include <stdio.h>
|
2009-06-24 20:32:00 -07:00
|
|
|
#define verbose_outputf if (_logc->lcbits & LC_Assembly) \
|
|
|
|
Assembler::outputf
|
|
|
|
#define verbose_only(x) x
|
2008-12-13 15:45:38 -08:00
|
|
|
#elif defined(NJ_VERBOSE)
|
2008-06-18 20:49:37 -07:00
|
|
|
#include <stdio.h>
|
2009-06-24 20:32:00 -07:00
|
|
|
#define verbose_outputf if (_logc->lcbits & LC_Assembly) \
|
|
|
|
Assembler::outputf
|
|
|
|
#define verbose_only(...) __VA_ARGS__
|
2008-06-18 20:49:37 -07:00
|
|
|
#else
|
|
|
|
#define verbose_outputf
|
2008-12-10 17:25:46 -08:00
|
|
|
#define verbose_only(...)
|
2008-06-18 20:49:37 -07:00
|
|
|
#endif /*NJ_VERBOSE*/
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
#define debug_only(x) x
|
|
|
|
#else
|
|
|
|
#define debug_only(x)
|
|
|
|
#endif /* DEBUG */
|
|
|
|
|
|
|
|
#ifdef NJ_PROFILE
|
|
|
|
#define counter_struct_begin() struct {
|
|
|
|
#define counter_struct_end() } _stats;
|
|
|
|
#define counter_define(x) int32_t x
|
|
|
|
#define counter_value(x) _stats.x
|
|
|
|
#define counter_set(x,v) (counter_value(x)=(v))
|
|
|
|
#define counter_adjust(x,i) (counter_value(x)+=(int32_t)(i))
|
|
|
|
#define counter_reset(x) counter_set(x,0)
|
|
|
|
#define counter_increment(x) counter_adjust(x,1)
|
|
|
|
#define counter_decrement(x) counter_adjust(x,-1)
|
|
|
|
#define profile_only(x) x
|
|
|
|
#else
|
|
|
|
#define counter_struct_begin()
|
|
|
|
#define counter_struct_end()
|
|
|
|
#define counter_define(x)
|
|
|
|
#define counter_value(x)
|
|
|
|
#define counter_set(x,v)
|
|
|
|
#define counter_adjust(x,i)
|
|
|
|
#define counter_reset(x)
|
|
|
|
#define counter_increment(x)
|
|
|
|
#define counter_decrement(x)
|
|
|
|
#define profile_only(x)
|
|
|
|
#endif /* NJ_PROFILE */
|
|
|
|
|
|
|
|
#define isS8(i) ( int32_t(i) == int8_t(i) )
|
|
|
|
#define isU8(i) ( int32_t(i) == uint8_t(i) )
|
|
|
|
#define isS16(i) ( int32_t(i) == int16_t(i) )
|
|
|
|
#define isU16(i) ( int32_t(i) == uint16_t(i) )
|
2008-09-02 22:29:23 -07:00
|
|
|
#define isS24(i) ( ((int32_t(i)<<8)>>8) == (i) )
|
2008-06-18 20:49:37 -07:00
|
|
|
|
2008-07-31 13:28:12 -07:00
|
|
|
#define alignTo(x,s) ((((uintptr_t)(x)))&~(((uintptr_t)s)-1))
|
|
|
|
#define alignUp(x,s) ((((uintptr_t)(x))+(((uintptr_t)s)-1))&~(((uintptr_t)s)-1))
|
2008-06-18 20:49:37 -07:00
|
|
|
|
2009-06-16 14:01:31 -07:00
|
|
|
#define pageTop(x) ( alignTo(x,NJ_PAGE_SIZE) )
|
|
|
|
#define pageDataStart(x) ( alignTo(x,NJ_PAGE_SIZE) + sizeof(PageHeader) )
|
|
|
|
#define pageBottom(x) ( alignTo(x,NJ_PAGE_SIZE) + NJ_PAGE_SIZE - 1 )
|
|
|
|
#define samepage(x,y) ( pageTop(x) == pageTop(y) )
|
2008-06-18 20:49:37 -07:00
|
|
|
|
2009-05-26 11:14:41 -07:00
|
|
|
|
2009-06-24 20:32:00 -07:00
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// START debug-logging definitions
|
|
|
|
// -------------------------------------------------------------------
|
2009-05-26 11:14:41 -07:00
|
|
|
|
2009-06-24 20:32:00 -07:00
|
|
|
/* Debug printing stuff. All Nanojit and jstracer debug printing
|
|
|
|
should be routed through LogControl::printf. Don't use
|
|
|
|
ad-hoc calls to printf, fprintf(stderr, ...) etc.
|
|
|
|
|
|
|
|
Similarly, don't use ad-hoc getenvs etc to decide whether or not to
|
|
|
|
print debug output. Instead consult the relevant control bit in
|
|
|
|
LogControl::lcbits in the LogControl object you are supplied with.
|
|
|
|
*/
|
2009-05-26 11:14:41 -07:00
|
|
|
|
|
|
|
# if defined(__GNUC__)
|
|
|
|
# define PRINTF_CHECK(x, y) __attribute__((format(__printf__, x, y)))
|
|
|
|
# else
|
|
|
|
# define PRINTF_CHECK(x, y)
|
|
|
|
# endif
|
|
|
|
|
2009-06-24 20:32:00 -07:00
|
|
|
namespace nanojit {
|
|
|
|
|
|
|
|
// LogControl, a class for controlling and routing debug output
|
|
|
|
|
|
|
|
enum LC_Bits {
|
|
|
|
/* Output control bits for Nanojit code. Only use bits 15
|
|
|
|
and below, so that callers can use bits 16 and above for
|
|
|
|
themselves. */
|
|
|
|
// TODO: add entries for the writer pipeline
|
|
|
|
LC_Liveness = 1<<7, // (show LIR liveness analysis)
|
|
|
|
LC_ReadLIR = 1<<6, // As read from LirBuffer
|
|
|
|
LC_AfterSF_SP = 1<<5, // After StackFilter(sp)
|
|
|
|
LC_AfterSF_RP = 1<<4, // After StackFilter(rp)
|
|
|
|
LC_AfterDeadF = 1<<3, // After DeadFilter
|
|
|
|
LC_RegAlloc = 1<<2, // stuff to do with reg alloc
|
|
|
|
LC_Assembly = 1<<1, // final assembly
|
|
|
|
LC_NoCodeAddrs = 1<<0 // (don't show code addresses on asm output)
|
|
|
|
};
|
|
|
|
|
|
|
|
class LogControl
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
// All Nanojit and jstracer printing should be routed through
|
|
|
|
// this function.
|
|
|
|
void printf( const char* format, ... ) PRINTF_CHECK(2,3);
|
|
|
|
|
|
|
|
// An OR of LC_Bits values, indicating what should be output
|
|
|
|
uint32_t lcbits;
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
2009-05-26 11:14:41 -07:00
|
|
|
|
2009-06-24 20:32:00 -07:00
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// END debug-logging definitions
|
|
|
|
// -------------------------------------------------------------------
|
2009-05-26 11:14:41 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
2008-06-18 20:57:17 -07:00
|
|
|
#include "Native.h"
|
2008-06-18 21:11:15 -07:00
|
|
|
#include "LIR.h"
|
2008-06-18 21:23:53 -07:00
|
|
|
#include "RegAlloc.h"
|
2008-06-18 20:49:37 -07:00
|
|
|
#include "Fragmento.h"
|
2008-06-18 21:32:23 -07:00
|
|
|
#include "Assembler.h"
|
2008-06-18 20:49:37 -07:00
|
|
|
|
2008-10-13 13:29:18 -07:00
|
|
|
#endif // FEATURE_NANOJIT
|
2008-07-07 02:47:40 -07:00
|
|
|
#endif // __nanojit_h__
|