Merge mozilla-central to mozilla-inbound

This commit is contained in:
Matt Brubeck 2011-10-24 20:24:51 -07:00
commit 57042802ec
68 changed files with 1199 additions and 978 deletions

View File

@ -43,7 +43,7 @@
#include <time.h>
#include <windows.h>
#include <pstore.h>
#include <ole2.h>
#include "nsIBrowserProfileMigrator.h"
#include "nsIObserverService.h"
#include "nsTArray.h"
@ -61,6 +61,79 @@ struct SignonData {
char* realm;
};
// VC11 doesn't ship with pstore.h, so we go ahead and define the stuff that
// we need from that file here.
class IEnumPStoreItems : public IUnknown {
public:
virtual HRESULT STDMETHODCALLTYPE Next(DWORD celt, LPWSTR* rgelt,
DWORD* pceltFetched) = 0;
virtual HRESULT STDMETHODCALLTYPE Skip(DWORD celt) = 0;
virtual HRESULT STDMETHODCALLTYPE Reset() = 0;
virtual HRESULT STDMETHODCALLTYPE Clone(IEnumPStoreItems** ppenum) = 0;
};
class IEnumPStoreTypes; // not used
struct PST_PROVIDERINFO; // not used
struct PST_TYPEINFO; // not used
struct PST_PROMPTINFO; // not used
struct PST_ACCESSRULESET; // not used
typedef DWORD PST_KEY;
typedef DWORD PST_ACCESSMODE;
class IPStore : public IUnknown {
public:
virtual HRESULT STDMETHODCALLTYPE GetInfo(PST_PROVIDERINFO** ppProperties) = 0;
virtual HRESULT STDMETHODCALLTYPE GetProvParam(DWORD dwParam, DWORD* pcbData,
BYTE** ppbData, DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE SetProvParam(DWORD dwParam, DWORD cbData,
BYTE* pbData, DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE CreateType(PST_KEY Key, const GUID* pType,
PST_TYPEINFO* pInfo, DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(PST_KEY Key, const GUID* pType,
PST_TYPEINFO** ppInfo, DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE DeleteType(PST_KEY Key, const GUID* pType,
DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE CreateSubtype(PST_KEY Key, const GUID* pType,
const GUID* pSubtype, PST_TYPEINFO* pInfo,
PST_ACCESSRULESET* pRules, DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE GetSubtypeInfo(PST_KEY Key, const GUID* pType,
const GUID* pSubtype, PST_TYPEINFO** ppInfo,
DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE DeleteSubtype(PST_KEY Key, const GUID* pType,
const GUID* pSubtype, DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE ReadAccessRuleset(PST_KEY Key, const GUID* pType,
const GUID* pSubtype, PST_ACCESSRULESET** ppRules,
DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE WriteAccessRuleset(PST_KEY Key, const GUID* pType,
const GUID* pSubtype, PST_ACCESSRULESET* pRules,
DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE EnumTypes(PST_KEY Key, DWORD dwFlags, IEnumPStoreTypes** ppenum) = 0;
virtual HRESULT STDMETHODCALLTYPE EnumSubtypes(PST_KEY Key, const GUID* pType,
DWORD dwFlags, IEnumPStoreTypes** ppenum) = 0;
virtual HRESULT STDMETHODCALLTYPE DeleteItem(PST_KEY Key, const GUID* pItemType,
const GUID* pItemSubtype, LPCWSTR szItemName,
PST_PROMPTINFO* pPromptInfo, DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE ReadItem(PST_KEY Key, const GUID* pItemType,
const GUID* pItemSubtype, LPCWSTR szItemName,
DWORD* pcbData, BYTE** ppbData,
PST_PROMPTINFO* pPromptInfo, DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE WriteItem(PST_KEY Key, const GUID* pItemType,
const GUID* pItemSubtype, LPCWSTR szItemName,
DWORD cbData, BYTE* pbData,
PST_PROMPTINFO* pPromptInfo, DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE OpenItem(PST_KEY Key, const GUID* pItemType,
const GUID* pItemSubtype, LPCWSTR szItemName,
PST_ACCESSMODE ModeFlags, PST_PROMPTINFO* pPromptInfo,
DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE CloseItem(PST_KEY Key, const GUID* pItemType,
const GUID* pItemSubtype, LPCWSTR szItemName,
DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE EnumItems(PST_KEY Key, const GUID* pItemType,
const GUID* pItemSubtype, DWORD dwFlags,
IEnumPStoreItems** ppenum) = 0;
};
class nsIEProfileMigrator : public nsIBrowserProfileMigrator,
public nsINavHistoryBatchCallback {
public:

View File

@ -1643,7 +1643,7 @@ nsJSContext::ExecuteScript(void *aScriptObject,
nsCOMPtr<nsIPrincipal> principal;
rv = sSecurityManager->GetObjectPrincipal(mContext,
JS_GetObjectFromScript(script),
JS_GetGlobalFromScript(script),
getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -182,7 +182,7 @@ CPPSRCS = \
# doing!
INSTALLED_HEADERS = \
js-config.h \
jsautocfg.h \
jscpucfg.h \
$(CURDIR)/jsautokw.h \
js.msg \
jsalloc.h \
@ -542,10 +542,6 @@ else
CPPSRCS += pm_stub.cpp
endif
ifeq ($(OS_ARCH),WINNT)
INSTALLED_HEADERS += jscpucfg.h
endif
EXPORTS = $(INSTALLED_HEADERS)
DASH_R = -r
@ -760,12 +756,6 @@ DEFINES += -DIMPL_MFBT
INCLUDES += -I$(srcdir)
GARBAGE += jscpucfg.o jsautocfg.h jsautocfg.tmp jscpucfg
ifneq (,$(CROSS_COMPILE)$(filter-out WINNT,$(OS_ARCH)))
TARGETS += jscpucfg$(HOST_BIN_SUFFIX)
endif
ifdef JS_THREADSAFE
DEFINES += -DJS_THREADSAFE
endif
@ -880,34 +870,6 @@ jsdtoa.o: jsdtoa.cpp Makefile.in
$(CXX) -o $@ -c $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(COMPILE_CFLAGS)) $<
endif
export:: jsautocfg.h
ifeq (,$(CROSS_COMPILE)$(GNU_CC)$(filter-out WINNT,$(OS_ARCH)))
jsautocfg.h:
$(TOUCH) $@
else
jsautocfg.h: jscpucfg$(HOST_BIN_SUFFIX)
@$(RM) $@ jsautocfg.tmp
./jscpucfg > jsautocfg.tmp
mv jsautocfg.tmp $@
endif
# jscpucfg is a strange target
# Needs to be built with the host compiler but needs to include
# the mdcpucfg for the target so it needs the appropriate target defines
ifdef HOST_NSPR_MDCPUCFG
HOST_CXX := $(HOST_CXX) -DMDCPUCFG=$(TARGET_NSPR_MDCPUCFG)
HOST_CXXFLAGS := $(patsubst -DXP_%,,$(HOST_CXXFLAGS))
endif
ifdef CROSS_COMPILE
# jscpucfg needs to know when it's supposed to produce a config for the target
JSCPUCFG_DEFINES = $(ACDEFINES)
endif
jscpucfg$(HOST_BIN_SUFFIX): jscpucfg.cpp Makefile.in
$(HOST_CXX) $(HOST_CXXFLAGS) $(JSCPUCFG_DEFINES) $(DEFINES) $(NSPR_CFLAGS) $(HOST_OUTOPTION)$@ $<
# Compute the linker flags that programs linking against SpiderMonkey should
# pass to get SpiderMonkey and its dependencies, beyond just the -L and -l
# for the SpiderMonkey library itself.

View File

@ -2718,6 +2718,11 @@ fi
MOZ_ALIGN_OF_TYPE(JS_ALIGN_OF_POINTER, void*, 2 4 8 16)
MOZ_SIZE_OF_TYPE(JS_BYTES_PER_DOUBLE, double, 6 8 10 12 14)
AC_CHECK_HEADERS(endian.h)
if test "$ac_cv_header_endian_h" = yes; then
AC_DEFINE(JS_HAVE_ENDIAN_H)
fi
dnl Check for int16_t, int32_t, int64_t, int64, uint, uint_t, and uint16_t.
dnl ========================================================
AC_MSG_CHECKING(for int16_t)

View File

@ -51,8 +51,6 @@
using namespace js;
using namespace js::frontend;
namespace js {
/*
* Compile a top-level script.
*/
@ -74,7 +72,7 @@ BytecodeCompiler::compileScript(JSContext *cx, JSObject *scopeChain, StackFrame
bool inDirectivePrologue;
JS_ASSERT(!(tcflags & ~(TCF_COMPILE_N_GO | TCF_NO_SCRIPT_RVAL | TCF_NEED_MUTABLE_SCRIPT |
TCF_COMPILE_FOR_EVAL | TCF_NEED_SCRIPT_OBJECT)));
TCF_COMPILE_FOR_EVAL | TCF_NEED_SCRIPT_GLOBAL)));
/*
* The scripted callerFrame can only be given for compile-and-go scripts
@ -476,5 +474,3 @@ BytecodeCompiler::compileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipa
return pn != NULL;
}
} /* namespace js */

View File

@ -93,9 +93,6 @@ using namespace js::frontend;
extern uint8 js_opcode2extra[];
#endif
namespace js {
namespace frontend {
static JSBool
NewTryNote(JSContext *cx, CodeGenerator *cg, JSTryNoteKind kind, uintN stackDepth,
size_t start, size_t end);
@ -106,7 +103,8 @@ EmitIndexOp(JSContext *cx, JSOp op, uintN index, CodeGenerator *cg, JSOp *psuffi
static JSBool
EmitLeaveBlock(JSContext *cx, CodeGenerator *cg, JSOp op, ObjectBox *box);
} /* namespace frontend */
static JSBool
SetSrcNoteOffset(JSContext *cx, CodeGenerator *cg, uintN index, uintN which, ptrdiff_t offset);
void
TreeContext::trace(JSTracer *trc)
@ -162,8 +160,6 @@ CodeGenerator::~CodeGenerator()
cx->free_(spanDeps);
}
namespace frontend {
static ptrdiff_t
EmitCheck(JSContext *cx, CodeGenerator *cg, ptrdiff_t delta)
{
@ -269,7 +265,7 @@ UpdateDecomposeLength(CodeGenerator *cg, uintN start)
}
ptrdiff_t
Emit1(JSContext *cx, CodeGenerator *cg, JSOp op)
frontend::Emit1(JSContext *cx, CodeGenerator *cg, JSOp op)
{
ptrdiff_t offset = EmitCheck(cx, cg, 1);
@ -281,7 +277,7 @@ Emit1(JSContext *cx, CodeGenerator *cg, JSOp op)
}
ptrdiff_t
Emit2(JSContext *cx, CodeGenerator *cg, JSOp op, jsbytecode op1)
frontend::Emit2(JSContext *cx, CodeGenerator *cg, JSOp op, jsbytecode op1)
{
ptrdiff_t offset = EmitCheck(cx, cg, 2);
@ -296,8 +292,8 @@ Emit2(JSContext *cx, CodeGenerator *cg, JSOp op, jsbytecode op1)
}
ptrdiff_t
Emit3(JSContext *cx, CodeGenerator *cg, JSOp op, jsbytecode op1,
jsbytecode op2)
frontend::Emit3(JSContext *cx, CodeGenerator *cg, JSOp op, jsbytecode op1,
jsbytecode op2)
{
ptrdiff_t offset = EmitCheck(cx, cg, 3);
@ -313,7 +309,7 @@ Emit3(JSContext *cx, CodeGenerator *cg, JSOp op, jsbytecode op1,
}
ptrdiff_t
Emit5(JSContext *cx, CodeGenerator *cg, JSOp op, uint16 op1, uint16 op2)
frontend::Emit5(JSContext *cx, CodeGenerator *cg, JSOp op, uint16 op1, uint16 op2)
{
ptrdiff_t offset = EmitCheck(cx, cg, 5);
@ -331,7 +327,7 @@ Emit5(JSContext *cx, CodeGenerator *cg, JSOp op, uint16 op1, uint16 op2)
}
ptrdiff_t
EmitN(JSContext *cx, CodeGenerator *cg, JSOp op, size_t extra)
frontend::EmitN(JSContext *cx, CodeGenerator *cg, JSOp op, size_t extra)
{
ptrdiff_t length = 1 + (ptrdiff_t)extra;
ptrdiff_t offset = EmitCheck(cx, cg, length);
@ -558,7 +554,8 @@ AddJumpTarget(AddJumpTargetArgs *args, JumpTarget **jtp)
}
#ifdef DEBUG_brendan
static int AVLCheck(JumpTarget *jt)
static int
AVLCheck(JumpTarget *jt)
{
int lh, rh;
@ -1267,7 +1264,7 @@ GetJumpOffset(CodeGenerator *cg, jsbytecode *pc)
}
JSBool
SetJumpOffset(JSContext *cx, CodeGenerator *cg, jsbytecode *pc, ptrdiff_t off)
frontend::SetJumpOffset(JSContext *cx, CodeGenerator *cg, jsbytecode *pc, ptrdiff_t off)
{
if (!cg->spanDeps) {
if (JUMP_OFFSET_MIN <= off && off <= JUMP_OFFSET_MAX) {
@ -1282,8 +1279,6 @@ SetJumpOffset(JSContext *cx, CodeGenerator *cg, jsbytecode *pc, ptrdiff_t off)
return SetSpanDepTarget(cx, cg, GetSpanDep(cg, pc), off);
}
} /* namespace frontend */
bool
TreeContext::inStatement(StmtType type)
{
@ -1344,10 +1339,8 @@ TreeContext::skipSpansGenerator(unsigned skip)
return false;
}
namespace frontend {
bool
SetStaticLevel(TreeContext *tc, uintN staticLevel)
frontend::SetStaticLevel(TreeContext *tc, uintN staticLevel)
{
/*
* This is a lot simpler than error-checking every UpvarCookie::set, and
@ -1363,7 +1356,7 @@ SetStaticLevel(TreeContext *tc, uintN staticLevel)
}
bool
GenerateBlockId(TreeContext *tc, uint32& blockid)
frontend::GenerateBlockId(TreeContext *tc, uint32& blockid)
{
if (tc->blockidGen == JS_BIT(20)) {
JS_ReportErrorNumber(tc->parser->context, js_GetErrorMessage, NULL,
@ -1375,7 +1368,7 @@ GenerateBlockId(TreeContext *tc, uint32& blockid)
}
void
PushStatement(TreeContext *tc, StmtInfo *stmt, StmtType type, ptrdiff_t top)
frontend::PushStatement(TreeContext *tc, StmtInfo *stmt, StmtType type, ptrdiff_t top)
{
stmt->type = type;
stmt->flags = 0;
@ -1394,7 +1387,7 @@ PushStatement(TreeContext *tc, StmtInfo *stmt, StmtType type, ptrdiff_t top)
}
void
PushBlockScope(TreeContext *tc, StmtInfo *stmt, ObjectBox *blockBox, ptrdiff_t top)
frontend::PushBlockScope(TreeContext *tc, StmtInfo *stmt, ObjectBox *blockBox, ptrdiff_t top)
{
PushStatement(tc, stmt, STMT_BLOCK, top);
stmt->flags |= SIF_SCOPE;
@ -1680,7 +1673,7 @@ BackPatch(JSContext *cx, CodeGenerator *cg, ptrdiff_t last, jsbytecode *target,
}
void
PopStatementTC(TreeContext *tc)
frontend::PopStatementTC(TreeContext *tc)
{
StmtInfo *stmt = tc->topStmt;
tc->topStmt = stmt->down;
@ -1693,7 +1686,7 @@ PopStatementTC(TreeContext *tc)
}
JSBool
PopStatementCG(JSContext *cx, CodeGenerator *cg)
frontend::PopStatementCG(JSContext *cx, CodeGenerator *cg)
{
StmtInfo *stmt = cg->topStmt;
if (!STMT_IS_TRYING(stmt) &&
@ -1707,7 +1700,7 @@ PopStatementCG(JSContext *cx, CodeGenerator *cg)
}
JSBool
DefineCompileTimeConstant(JSContext *cx, CodeGenerator *cg, JSAtom *atom, ParseNode *pn)
frontend::DefineCompileTimeConstant(JSContext *cx, CodeGenerator *cg, JSAtom *atom, ParseNode *pn)
{
/* XXX just do numbers for now */
if (pn->isKind(TOK_NUMBER)) {
@ -1718,7 +1711,7 @@ DefineCompileTimeConstant(JSContext *cx, CodeGenerator *cg, JSAtom *atom, ParseN
}
StmtInfo *
LexicalLookup(TreeContext *tc, JSAtom *atom, jsint *slotp, StmtInfo *stmt)
frontend::LexicalLookup(TreeContext *tc, JSAtom *atom, jsint *slotp, StmtInfo *stmt)
{
if (!stmt)
stmt = tc->topScopeStmt;
@ -1960,16 +1953,12 @@ EmitSlotIndexOp(JSContext *cx, JSOp op, uintN slot, uintN index, CodeGenerator *
return bigSuffix == JSOP_NOP || Emit1(cx, cg, bigSuffix) >= 0;
}
} /* namespace frontend */
bool
CodeGenerator::shouldNoteClosedName(ParseNode *pn)
{
return !callsEval() && pn->isDefn() && pn->isClosed();
}
namespace frontend {
/*
* Adjust the slot for a block local to account for the number of variables
* that share the same index space with locals. Due to the incremental code
@ -2524,8 +2513,6 @@ BindNameToSlot(JSContext *cx, CodeGenerator *cg, ParseNode *pn)
return JS_TRUE;
}
} /* namespace frontend */
bool
CodeGenerator::addGlobalUse(JSAtom *atom, uint32 slot, UpvarCookie *cookie)
{
@ -2560,8 +2547,6 @@ CodeGenerator::addGlobalUse(JSAtom *atom, uint32 slot, UpvarCookie *cookie)
return globalMap->add(p, atom, globalUseIndex);
}
namespace frontend {
/*
* If pn contains a useful expression, return true with *answer set to true.
* If pn contains a useless expression, return true with *answer set to false.
@ -3924,7 +3909,7 @@ bad:
}
JSBool
EmitFunctionScript(JSContext *cx, CodeGenerator *cg, ParseNode *body)
frontend::EmitFunctionScript(JSContext *cx, CodeGenerator *cg, ParseNode *body)
{
/*
* The decompiler has assumptions about what may occur immediately after
@ -4823,8 +4808,6 @@ EmitEndInit(JSContext *cx, CodeGenerator *cg, uint32 count)
return Emit1(cx, cg, JSOP_ENDINIT) >= 0;
}
} /* namespace frontend */
bool
ParseNode::getConstantValue(JSContext *cx, bool strictChecks, Value *vp)
{
@ -4916,8 +4899,6 @@ ParseNode::getConstantValue(JSContext *cx, bool strictChecks, Value *vp)
return false;
}
namespace frontend {
static bool
EmitSingletonInitialiser(JSContext *cx, CodeGenerator *cg, ParseNode *pn)
{
@ -5858,7 +5839,7 @@ EmitFor(JSContext *cx, CodeGenerator *cg, ParseNode *pn, ptrdiff_t top)
}
JSBool
EmitTree(JSContext *cx, CodeGenerator *cg, ParseNode *pn)
frontend::EmitTree(JSContext *cx, CodeGenerator *cg, ParseNode *pn)
{
JSBool useful, wantval;
StmtInfo stmtInfo;
@ -7464,7 +7445,7 @@ AllocSrcNote(JSContext *cx, CodeGenerator *cg)
}
intN
NewSrcNote(JSContext *cx, CodeGenerator *cg, SrcNoteType type)
frontend::NewSrcNote(JSContext *cx, CodeGenerator *cg, SrcNoteType type)
{
intN index, n;
jssrcnote *sn;
@ -7512,7 +7493,7 @@ NewSrcNote(JSContext *cx, CodeGenerator *cg, SrcNoteType type)
}
intN
NewSrcNote2(JSContext *cx, CodeGenerator *cg, SrcNoteType type, ptrdiff_t offset)
frontend::NewSrcNote2(JSContext *cx, CodeGenerator *cg, SrcNoteType type, ptrdiff_t offset)
{
intN index;
@ -7525,7 +7506,7 @@ NewSrcNote2(JSContext *cx, CodeGenerator *cg, SrcNoteType type, ptrdiff_t offset
}
intN
NewSrcNote3(JSContext *cx, CodeGenerator *cg, SrcNoteType type, ptrdiff_t offset1,
frontend::NewSrcNote3(JSContext *cx, CodeGenerator *cg, SrcNoteType type, ptrdiff_t offset1,
ptrdiff_t offset2)
{
intN index;
@ -7555,7 +7536,7 @@ GrowSrcNotes(JSContext *cx, CodeGenerator *cg)
}
jssrcnote *
AddToSrcNoteDelta(JSContext *cx, CodeGenerator *cg, jssrcnote *sn, ptrdiff_t delta)
frontend::AddToSrcNoteDelta(JSContext *cx, CodeGenerator *cg, jssrcnote *sn, ptrdiff_t delta)
{
ptrdiff_t base, limit, newdelta, diff;
intN index;
@ -7588,7 +7569,7 @@ AddToSrcNoteDelta(JSContext *cx, CodeGenerator *cg, jssrcnote *sn, ptrdiff_t del
return sn;
}
JSBool
static JSBool
SetSrcNoteOffset(JSContext *cx, CodeGenerator *cg, uintN index, uintN which, ptrdiff_t offset)
{
jssrcnote *sn;
@ -7647,7 +7628,8 @@ SetSrcNoteOffset(JSContext *cx, CodeGenerator *cg, uintN index, uintN which, ptr
#define NBINS 10
static uint32 hist[NBINS];
static void DumpSrcNoteSizeHist()
static void
DumpSrcNoteSizeHist()
{
static FILE *fp;
int i, n;
@ -7677,7 +7659,7 @@ static void DumpSrcNoteSizeHist()
* CORRESPONDING CHANGES!
*/
JSBool
FinishTakingSrcNotes(JSContext *cx, CodeGenerator *cg, jssrcnote *notes)
frontend::FinishTakingSrcNotes(JSContext *cx, CodeGenerator *cg, jssrcnote *notes)
{
uintN prologCount, mainCount, totalCount;
ptrdiff_t offset, delta;
@ -7758,7 +7740,7 @@ NewTryNote(JSContext *cx, CodeGenerator *cg, JSTryNoteKind kind, uintN stackDept
}
void
FinishTakingTryNotes(CodeGenerator *cg, JSTryNoteArray *array)
frontend::FinishTakingTryNotes(CodeGenerator *cg, JSTryNoteArray *array)
{
TryNode *tryNode;
JSTryNote *tn;
@ -7772,8 +7754,6 @@ FinishTakingTryNotes(CodeGenerator *cg, JSTryNoteArray *array)
JS_ASSERT(tn == array->vector);
}
} /* namespace frontend */
/*
* Find the index of the given object for code generator.
*
@ -7852,8 +7832,6 @@ GCConstList::finish(JSConstArray *array)
*dst = *src;
}
} /* namespace js */
/*
* We should try to get rid of offsetBias (always 0 or 1, where 1 is
* JSOP_{NOP,POP}_LENGTH), which is used only by SRC_FOR and SRC_DECL.

View File

@ -275,7 +275,7 @@ struct StmtInfo {
/*
* The caller is JS_Compile*Script*.
*/
#define TCF_NEED_SCRIPT_OBJECT 0x40000000
#define TCF_NEED_SCRIPT_GLOBAL 0x40000000
/*
* Flags to check for return; vs. return expr; in a function.
@ -1077,9 +1077,6 @@ NewSrcNote3(JSContext *cx, CodeGenerator *cg, SrcNoteType type, ptrdiff_t offset
jssrcnote *
AddToSrcNoteDelta(JSContext *cx, CodeGenerator *cg, jssrcnote *sn, ptrdiff_t delta);
JSBool
SetSrcNoteOffset(JSContext *cx, CodeGenerator *cg, uintN index, uintN which, ptrdiff_t offset);
/*
* Finish taking source notes in cx's notePool, copying final notes to the new
* stable store allocated by the caller and passed in via notes. Return false

View File

@ -434,10 +434,8 @@ Boolish(ParseNode *pn)
}
}
namespace js {
bool
FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
{
ParseNode *pn1 = NULL, *pn2 = NULL, *pn3 = NULL;
@ -908,5 +906,3 @@ FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
return true;
}
} /* namespace js */

View File

@ -56,8 +56,6 @@ JS_STATIC_ASSERT(pn_offsetof(pn_link) == pn_offsetof(dn_uses));
#undef pn_offsetof
namespace js {
void
ParseNode::become(ParseNode *pn2)
{
@ -465,14 +463,10 @@ NameNode::create(JSAtom *atom, TreeContext *tc)
return (NameNode *)pn;
}
} /* namespace js */
const char js_argument_str[] = "argument";
const char js_variable_str[] = "variable";
const char js_unknown_str[] = "unknown";
namespace js {
const char *
Definition::kindString(Kind kind)
{
@ -602,7 +596,7 @@ CloneParseTree(ParseNode *opn, TreeContext *tc)
* the original tree.
*/
ParseNode *
CloneLeftHandSide(ParseNode *opn, TreeContext *tc)
js::CloneLeftHandSide(ParseNode *opn, TreeContext *tc)
{
ParseNode *pn = tc->parser->new_<ParseNode>(opn->getKind(), opn->getOp(), opn->getArity(),
opn->pn_pos);
@ -670,5 +664,3 @@ CloneLeftHandSide(ParseNode *opn, TreeContext *tc)
}
return pn;
}
} /* namespace js */

View File

@ -586,8 +586,6 @@ ReportBadParameter(JSContext *cx, TreeContext *tc, JSAtom *name, uintN errorNumb
ReportStrictModeError(cx, TS(tc->parser), tc, dn, errorNumber, bytes.ptr());
}
namespace js {
/*
* In strict mode code, all parameter names must be distinct, must not be
* strict mode reserved keywords, and must not be 'eval' or 'arguments'. We
@ -595,7 +593,7 @@ namespace js {
* function's body may turn on strict mode for the function head.
*/
bool
CheckStrictParameters(JSContext *cx, TreeContext *tc)
js::CheckStrictParameters(JSContext *cx, TreeContext *tc)
{
JS_ASSERT(tc->inFunction());
@ -649,8 +647,6 @@ CheckStrictParameters(JSContext *cx, TreeContext *tc)
return true;
}
} /* namespace js */
ParseNode *
Parser::functionBody()
{
@ -865,10 +861,8 @@ MakeDefIntoUse(Definition *dn, ParseNode *pn, JSAtom *atom, TreeContext *tc)
return dn;
}
namespace js {
bool
DefineArg(ParseNode *pn, JSAtom *atom, uintN i, TreeContext *tc)
js::DefineArg(ParseNode *pn, JSAtom *atom, uintN i, TreeContext *tc)
{
ParseNode *argpn, *argsbody;
@ -909,8 +903,6 @@ DefineArg(ParseNode *pn, JSAtom *atom, uintN i, TreeContext *tc)
return true;
}
} /* namespace js */
/*
* Parameter block types for the several Binder functions. We use a common
* helper function signature in order to share code among destructuring and
@ -7287,7 +7279,7 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot)
pn3 = NullaryNode::create(tc);
if (!pn3)
return NULL;
pn3->pn_dval = tokenStream.currentToken().t_dval;
pn3->pn_dval = tokenStream.currentToken().number();
if (!js_ValueToAtom(context, DoubleValue(pn3->pn_dval), &atom))
return NULL;
break;
@ -7313,7 +7305,7 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot)
pn3 = NullaryNode::create(tc);
if (!pn3)
return NULL;
pn3->pn_dval = tokenStream.currentToken().t_dval;
pn3->pn_dval = tokenStream.currentToken().number();
if (!js_ValueToAtom(context, DoubleValue(pn3->pn_dval), &atom))
return NULL;
} else {
@ -7459,7 +7451,7 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot)
pn = UnaryNode::create(tc);
if (!pn)
return NULL;
pn->pn_num = (jsint) tokenStream.currentToken().t_dval;
pn->pn_num = tokenStream.currentToken().sharpNumber();
tt = tokenStream.getToken(TSF_OPERAND);
pn->pn_kid = primaryExpr(tt, JS_FALSE);
if (!pn->pn_kid)
@ -7483,7 +7475,7 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot)
return NULL;
if (!tc->ensureSharpSlots())
return NULL;
pn->pn_num = (jsint) tokenStream.currentToken().t_dval;
pn->pn_num = tokenStream.currentToken().sharpNumber();
break;
#endif /* JS_HAS_SHARP_VARS */
@ -7687,7 +7679,7 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot)
const jschar *chars = tokenStream.getTokenbuf().begin();
size_t length = tokenStream.getTokenbuf().length();
RegExpFlag flags = RegExpFlag(tokenStream.currentToken().t_reflags);
RegExpFlag flags = tokenStream.currentToken().regExpFlags();
RegExpStatics *res = context->regExpStatics();
RegExpObject *reobj;
@ -7717,7 +7709,7 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot)
if (!pn)
return NULL;
pn->setOp(JSOP_DOUBLE);
pn->pn_dval = tokenStream.currentToken().t_dval;
pn->pn_dval = tokenStream.currentToken().number();
break;
case TOK_PRIMARY:

View File

@ -91,10 +91,8 @@ static const KeywordInfo keywords[] = {
#undef JS_KEYWORD
};
namespace js {
const KeywordInfo *
FindKeyword(const jschar *s, size_t length)
js::FindKeyword(const jschar *s, size_t length)
{
JS_ASSERT(length != 0);
@ -131,7 +129,7 @@ FindKeyword(const jschar *s, size_t length)
}
JSBool
IsIdentifier(JSLinearString *str)
js::IsIdentifier(JSLinearString *str)
{
const jschar *chars = str->chars();
size_t length = str->length();
@ -548,8 +546,8 @@ TokenStream::reportCompileErrorNumberVA(ParseNode *pn, uintN flags, uintN errorN
}
bool
ReportStrictModeError(JSContext *cx, TokenStream *ts, TreeContext *tc, ParseNode *pn,
uintN errorNumber, ...)
js::ReportStrictModeError(JSContext *cx, TokenStream *ts, TreeContext *tc, ParseNode *pn,
uintN errorNumber, ...)
{
JS_ASSERT(ts || tc);
JS_ASSERT(cx == ts->getContext());
@ -573,8 +571,8 @@ ReportStrictModeError(JSContext *cx, TokenStream *ts, TreeContext *tc, ParseNode
}
bool
ReportCompileErrorNumber(JSContext *cx, TokenStream *ts, ParseNode *pn, uintN flags,
uintN errorNumber, ...)
js::ReportCompileErrorNumber(JSContext *cx, TokenStream *ts, ParseNode *pn, uintN flags,
uintN errorNumber, ...)
{
va_list ap;
@ -1715,7 +1713,7 @@ TokenStream::getTokenInternal()
if (!js_strtod(cx, numStart, userbuf.addressOfNextRawChar(), &dummy, &dval))
goto error;
}
tp->t_dval = dval;
tp->setNumber(dval);
tt = TOK_NUMBER;
goto out;
}
@ -1801,7 +1799,7 @@ TokenStream::getTokenInternal()
const jschar *dummy;
if (!GetPrefixInteger(cx, numStart, userbuf.addressOfNextRawChar(), radix, &dummy, &dval))
goto error;
tp->t_dval = dval;
tp->setNumber(dval);
tt = TOK_NUMBER;
goto out;
}
@ -1962,10 +1960,9 @@ TokenStream::getTokenInternal()
* Look for a regexp.
*/
if (flags & TSF_OPERAND) {
uintN reflags, length;
JSBool inCharClass = JS_FALSE;
tokenbuf.clear();
bool inCharClass = false;
for (;;) {
c = getChar();
if (c == '\\') {
@ -1973,9 +1970,9 @@ TokenStream::getTokenInternal()
goto error;
c = getChar();
} else if (c == '[') {
inCharClass = JS_TRUE;
inCharClass = true;
} else if (c == ']') {
inCharClass = JS_FALSE;
inCharClass = false;
} else if (c == '/' && !inCharClass) {
/* For compat with IE, allow unescaped / in char classes. */
break;
@ -1989,31 +1986,36 @@ TokenStream::getTokenInternal()
if (!tokenbuf.append(c))
goto error;
}
for (reflags = 0, length = tokenbuf.length() + 1; ; length++) {
RegExpFlag reflags = NoFlags;
uintN length = tokenbuf.length() + 1;
while (true) {
c = peekChar();
if (c == 'g' && !(reflags & JSREG_GLOB))
reflags |= JSREG_GLOB;
if (c == 'g' && !(reflags & GlobalFlag))
reflags = RegExpFlag(reflags | GlobalFlag);
else if (c == 'i' && !(reflags & IgnoreCaseFlag))
reflags |= IgnoreCaseFlag;
reflags = RegExpFlag(reflags | IgnoreCaseFlag);
else if (c == 'm' && !(reflags & MultilineFlag))
reflags |= MultilineFlag;
reflags = RegExpFlag(reflags | MultilineFlag);
else if (c == 'y' && !(reflags & StickyFlag))
reflags |= StickyFlag;
reflags = RegExpFlag(reflags | StickyFlag);
else
break;
getChar();
length++;
}
c = peekChar();
if (JS7_ISLET(c)) {
char buf[2] = { '\0' };
char buf[2] = { '\0', '\0' };
tp->pos.begin.index += length + 1;
buf[0] = (char)c;
buf[0] = char(c);
ReportCompileErrorNumber(cx, this, NULL, JSREPORT_ERROR, JSMSG_BAD_REGEXP_FLAG,
buf);
(void) getChar();
goto error;
}
tp->t_reflags = reflags;
tp->setRegExpFlags(reflags);
tt = TOK_REGEXP;
break;
}
@ -2069,9 +2071,8 @@ TokenStream::getTokenInternal()
goto error;
}
}
tp->t_dval = (jsdouble) n;
if (cx->hasStrictOption() &&
(c == '=' || c == '#')) {
tp->setSharpNumber(uint16(n));
if (cx->hasStrictOption() && (c == '=' || c == '#')) {
char buf[20];
JS_snprintf(buf, sizeof buf, "#%u%c", n, c);
if (!ReportCompileErrorNumber(cx, this, NULL, JSREPORT_WARNING | JSREPORT_STRICT,
@ -2128,8 +2129,6 @@ TokenStream::getTokenInternal()
return TOK_ERROR;
}
} /* namespace js */
JS_FRIEND_API(int)
js_fgets(char *buf, int size, FILE *file)
{

View File

@ -265,18 +265,26 @@ struct Token {
JSAtom *atom; /* potentially-numeric atom */
} n;
} s;
uintN reflags; /* regexp flags, use tokenbuf to access
regexp chars */
class { /* pair for <?target data?> XML PI */
friend struct Token;
private:
friend struct Token;
struct { /* pair for <?target data?> XML PI */
JSAtom *data; /* auxiliary atom table entry */
PropertyName *target; /* main atom table entry */
} xmlpi;
jsdouble dval; /* floating point number */
uint16 sharpNumber; /* sharp variable number: #1# or #1= */
jsdouble number; /* floating point number */
RegExpFlag reflags; /* regexp flags, use tokenbuf to access
regexp chars */
} u;
/* Mutators */
/*
* FIXME: Init type early enough such that all mutators can assert
* type-safety. See bug 697000.
*/
void setName(JSOp op, PropertyName *name) {
JS_ASSERT(op == JSOP_NAME);
u.s.op = op;
@ -294,6 +302,19 @@ struct Token {
u.xmlpi.data = data;
}
void setRegExpFlags(js::RegExpFlag flags) {
JS_ASSERT((flags & AllFlags) == flags);
u.reflags = flags;
}
void setSharpNumber(uint16 sharpNum) {
u.sharpNumber = sharpNum;
}
void setNumber(jsdouble n) {
u.number = n;
}
/* Type-safe accessors */
PropertyName *name() const {
@ -320,11 +341,25 @@ struct Token {
JS_ASSERT(type == TOK_XMLPI);
return u.xmlpi.data;
}
js::RegExpFlag regExpFlags() const {
JS_ASSERT(type == TOK_REGEXP);
JS_ASSERT((u.reflags & AllFlags) == u.reflags);
return u.reflags;
}
uint16 sharpNumber() const {
JS_ASSERT(type == TOK_DEFSHARP || type == TOK_USESHARP);
return u.sharpNumber;
}
jsdouble number() const {
JS_ASSERT(type == TOK_NUMBER);
return u.number;
}
};
#define t_op u.s.op
#define t_reflags u.reflags
#define t_dval u.dval
enum TokenStreamFlags
{

View File

@ -59,6 +59,10 @@
useable. See jstypes.h and jsstdint.h. */
#undef JS_HAVE_STDINT_H
/* Define to 1 if the <endian.h> header is present and
useable. See jscpucfg.h. */
#undef JS_HAVE_ENDIAN_H
/* Define to 1 if the <sys/types.h> defines int8_t, etc. */
#undef JS_SYS_TYPES_H_DEFINES_EXACT_SIZE_TYPES

View File

@ -370,3 +370,4 @@ MSG_DEF(JSMSG_DEBUG_BAD_LINE, 283, 0, JSEXN_TYPEERR, "invalid line numbe
MSG_DEF(JSMSG_DEBUG_NOT_DEBUGGING, 284, 0, JSEXN_ERR, "can't set breakpoint: script global is not a debuggee")
MSG_DEF(JSMSG_DEBUG_COMPARTMENT_MISMATCH, 285, 2, JSEXN_TYPEERR, "{0}: descriptor .{1} property is an object in a different compartment than the target object")
MSG_DEF(JSMSG_DEBUG_NOT_SCRIPT_FRAME, 286, 0, JSEXN_ERR, "stack frame is not running JavaScript code")
MSG_DEF(JSMSG_CANT_WATCH_PROP, 287, 0, JSEXN_TYPEERR, "properties whose names are objects can't be watched")

View File

@ -1278,30 +1278,33 @@ JS_EnterCrossCompartmentCall(JSContext *cx, JSObject *target)
return reinterpret_cast<JSCrossCompartmentCall *>(call);
}
namespace js {
// Declared in jscompartment.h
JSClass js_dummy_class = {
Class dummy_class = {
"jdummy",
JSCLASS_GLOBAL_FLAGS,
JS_PropertyStub, JS_PropertyStub,
JS_PropertyStub, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub,
JS_ConvertStub, NULL,
JSCLASS_NO_OPTIONAL_MEMBERS
JS_ConvertStub
};
} /*namespace js */
JS_PUBLIC_API(JSCrossCompartmentCall *)
JS_EnterCrossCompartmentCallScript(JSContext *cx, JSScript *target)
{
CHECK_REQUEST(cx);
JSObject *scriptObject = target->u.object;
if (!scriptObject) {
JS_ASSERT(!target->isCachedEval);
GlobalObject *global = target->u.globalObject;
if (!global) {
SwitchToCompartment sc(cx, target->compartment());
scriptObject = JS_NewGlobalObject(cx, &js_dummy_class);
if (!scriptObject)
global = GlobalObject::create(cx, &dummy_class);
if (!global)
return NULL;
}
return JS_EnterCrossCompartmentCall(cx, scriptObject);
return JS_EnterCrossCompartmentCall(cx, global);
}
JS_PUBLIC_API(JSCrossCompartmentCall *)
@ -4582,7 +4585,7 @@ CompileUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj, JSPrincipals *p
assertSameCompartment(cx, obj, principals);
AutoLastFrameCheck lfc(cx);
uint32 tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_MUTABLE_SCRIPT | TCF_NEED_SCRIPT_OBJECT;
uint32 tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_MUTABLE_SCRIPT | TCF_NEED_SCRIPT_GLOBAL;
return BytecodeCompiler::compileScript(cx, obj, NULL, principals, tcflags, chars, length,
filename, lineno, version);
}
@ -4759,7 +4762,7 @@ CompileFileHelper(JSContext *cx, JSObject *obj, JSPrincipals *principals,
JS_ASSERT(i <= len);
len = i;
uint32 tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_MUTABLE_SCRIPT | TCF_NEED_SCRIPT_OBJECT;
uint32 tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_MUTABLE_SCRIPT | TCF_NEED_SCRIPT_GLOBAL;
script = BytecodeCompiler::compileScript(cx, obj, NULL, principals, tcflags, buf, len,
filename, 1, cx->findVersion());
cx->free_(buf);
@ -4820,11 +4823,12 @@ JS_CompileFileHandle(JSContext *cx, JSObject *obj, const char *filename, FILE *f
}
JS_PUBLIC_API(JSObject *)
JS_GetObjectFromScript(JSScript *script)
JS_GetGlobalFromScript(JSScript *script)
{
JS_ASSERT(script->u.object);
JS_ASSERT(!script->isCachedEval);
JS_ASSERT(script->u.globalObject);
return script->u.object;
return script->u.globalObject;
}
static JSFunction *
@ -5018,7 +5022,7 @@ EvaluateUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj,
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
uint32 flags = TCF_COMPILE_N_GO | TCF_NEED_SCRIPT_OBJECT;
uint32 flags = TCF_COMPILE_N_GO | TCF_NEED_SCRIPT_GLOBAL;
if (!rval)
flags |= TCF_NO_SCRIPT_RVAL;

View File

@ -3817,7 +3817,7 @@ JS_CompileFileHandleForPrincipalsVersion(JSContext *cx, JSObject *obj,
JSVersion version);
extern JS_PUBLIC_API(JSObject *)
JS_GetObjectFromScript(JSScript *script);
JS_GetGlobalFromScript(JSScript *script);
extern JS_PUBLIC_API(JSFunction *)
JS_CompileFunction(JSContext *cx, JSObject *obj, const char *name,

File diff suppressed because it is too large Load Diff

View File

@ -208,8 +208,8 @@ class CompartmentChecker
void check(JSScript *script) {
if (script) {
check(script->compartment());
if (script->u.object)
check(script->u.object);
if (!script->isCachedEval && script->u.globalObject)
check(script->u.globalObject);
}
}

View File

@ -278,7 +278,7 @@ JSCompartment::wrap(JSContext *cx, Value *vp)
if (vp->isObject()) {
JSObject *obj = &vp->toObject();
JS_ASSERT(obj->isCrossCompartmentWrapper());
if (global->getJSClass() != &js_dummy_class && obj->getParent() != global) {
if (global->getClass() != &dummy_class && obj->getParent() != global) {
do {
obj->setParent(global);
obj = obj->getProto();
@ -861,14 +861,11 @@ JSCompartment::getBreakpointSite(jsbytecode *pc)
}
BreakpointSite *
JSCompartment::getOrCreateBreakpointSite(JSContext *cx, JSScript *script, jsbytecode *pc, JSObject *scriptObject)
JSCompartment::getOrCreateBreakpointSite(JSContext *cx, JSScript *script, jsbytecode *pc,
GlobalObject *scriptGlobal)
{
JS_ASSERT(script->code <= pc);
JS_ASSERT(pc < script->code + script->length);
JS_ASSERT_IF(scriptObject, scriptObject->isScript() || scriptObject->isFunction());
JS_ASSERT_IF(scriptObject && scriptObject->isFunction(),
scriptObject->getFunctionPrivate()->script() == script);
JS_ASSERT_IF(scriptObject && scriptObject->isScript(), scriptObject->getScript() == script);
BreakpointSiteMap::AddPtr p = breakpointSites.lookupForAdd(pc);
if (!p) {
@ -880,10 +877,10 @@ JSCompartment::getOrCreateBreakpointSite(JSContext *cx, JSScript *script, jsbyte
}
BreakpointSite *site = p->value;
if (site->scriptObject)
JS_ASSERT_IF(scriptObject, site->scriptObject == scriptObject);
if (site->scriptGlobal)
JS_ASSERT_IF(scriptGlobal, site->scriptGlobal == scriptGlobal);
else
site->scriptObject = scriptObject;
site->scriptGlobal = scriptGlobal;
return site;
}

View File

@ -293,10 +293,11 @@ struct TraceMonitor {
namespace mjit {
class JaegerCompartment;
}
}
/* Defined in jsapi.cpp */
extern JSClass js_dummy_class;
extern Class dummy_class;
} /* namespace js */
#ifndef JS_EVAL_CACHE_SHIFT
# define JS_EVAL_CACHE_SHIFT 6
@ -615,7 +616,7 @@ struct JS_FRIEND_API(JSCompartment) {
js::BreakpointSite *getBreakpointSite(jsbytecode *pc);
js::BreakpointSite *getOrCreateBreakpointSite(JSContext *cx, JSScript *script, jsbytecode *pc,
JSObject *scriptObject);
js::GlobalObject *scriptGlobal);
void clearBreakpointsIn(JSContext *cx, js::Debugger *dbg, JSScript *script, JSObject *handler);
void clearTraps(JSContext *cx, JSScript *script);
bool markTrapClosuresIteratively(JSTracer *trc);

View File

@ -1,182 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** 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 Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
*
* Alternatively, the contents of this file may be used under the terms of
* either of 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 ***** */
/*
* Generate CPU-specific bit-size and similar #defines.
*/
#include <stdio.h>
#include <stdlib.h>
#if defined(CROSS_COMPILE) && !defined(FORCE_BIG_ENDIAN) && !defined(FORCE_LITTLE_ENDIAN)
#include <prtypes.h>
#endif
/************************************************************************/
int main(int argc, char **argv)
{
printf("#ifndef js_cpucfg___\n");
printf("#define js_cpucfg___\n\n");
printf("/* AUTOMATICALLY GENERATED - DO NOT EDIT */\n\n");
#ifdef CROSS_COMPILE
#if defined(__APPLE__) && !defined(FORCE_BIG_ENDIAN) && !defined(FORCE_LITTLE_ENDIAN)
/*
* Darwin NSPR uses the same MDCPUCFG (_darwin.cfg) for multiple
* processors, and determines which processor to configure for based
* on compiler predefined macros. We do the same thing here.
*/
printf("#ifdef __LITTLE_ENDIAN__\n");
printf("#define IS_LITTLE_ENDIAN 1\n");
printf("#undef IS_BIG_ENDIAN\n");
printf("#else\n");
printf("#undef IS_LITTLE_ENDIAN\n");
printf("#define IS_BIG_ENDIAN 1\n");
printf("#endif\n\n");
#elif defined(IS_LITTLE_ENDIAN) || defined(FORCE_LITTLE_ENDIAN)
printf("#define IS_LITTLE_ENDIAN 1\n");
printf("#undef IS_BIG_ENDIAN\n\n");
#elif defined(IS_BIG_ENDIAN) || defined(FORCE_BIG_ENDIAN)
printf("#undef IS_LITTLE_ENDIAN\n");
printf("#define IS_BIG_ENDIAN 1\n\n");
#else
#error "Endianess not defined."
#endif
#else
/*
* We don't handle PDP-endian or similar orders: if a short is big-endian,
* so must int and long be big-endian for us to generate the IS_BIG_ENDIAN
* #define and the IS_LITTLE_ENDIAN #undef.
*/
{
int big_endian = 0, little_endian = 0, ntests = 0;
if (sizeof(short) == 2) {
/* force |volatile| here to get rid of any compiler optimisations
* (var in register etc.) which may be appiled to |auto| vars -
* even those in |union|s...
* (|static| is used to get the same functionality for compilers
* which do not honor |volatile|...).
*/
volatile static union {
short i;
char c[2];
} u;
u.i = 0x0102;
big_endian += (u.c[0] == 0x01 && u.c[1] == 0x02);
little_endian += (u.c[0] == 0x02 && u.c[1] == 0x01);
ntests++;
}
if (sizeof(int) == 4) {
/* force |volatile| here ... */
volatile static union {
int i;
char c[4];
} u;
u.i = 0x01020304;
big_endian += (u.c[0] == 0x01 && u.c[1] == 0x02 &&
u.c[2] == 0x03 && u.c[3] == 0x04);
little_endian += (u.c[0] == 0x04 && u.c[1] == 0x03 &&
u.c[2] == 0x02 && u.c[3] == 0x01);
ntests++;
}
if (sizeof(long) == 8) {
/* force |volatile| here ... */
volatile static union {
long i;
char c[8];
} u;
/*
* Write this as portably as possible: avoid 0x0102030405060708L
* and <<= 32.
*/
u.i = 0x01020304;
u.i <<= 16, u.i <<= 16;
u.i |= 0x05060708;
big_endian += (u.c[0] == 0x01 && u.c[1] == 0x02 &&
u.c[2] == 0x03 && u.c[3] == 0x04 &&
u.c[4] == 0x05 && u.c[5] == 0x06 &&
u.c[6] == 0x07 && u.c[7] == 0x08);
little_endian += (u.c[0] == 0x08 && u.c[1] == 0x07 &&
u.c[2] == 0x06 && u.c[3] == 0x05 &&
u.c[4] == 0x04 && u.c[5] == 0x03 &&
u.c[6] == 0x02 && u.c[7] == 0x01);
ntests++;
}
if (big_endian && big_endian == ntests) {
printf("#undef IS_LITTLE_ENDIAN\n");
printf("#define IS_BIG_ENDIAN 1\n\n");
} else if (little_endian && little_endian == ntests) {
printf("#define IS_LITTLE_ENDIAN 1\n");
printf("#undef IS_BIG_ENDIAN\n\n");
} else {
fprintf(stderr, "%s: unknown byte order"
"(big_endian=%d, little_endian=%d, ntests=%d)!\n",
argv[0], big_endian, little_endian, ntests);
return EXIT_FAILURE;
}
}
#endif /* CROSS_COMPILE */
// PA-RISC is the only platform we try to support on which the stack
// grows towards higher addresses. Trying to detect it here has
// historically led to portability problems, which aren't worth it
// given the near consensus on stack growth direction.
printf("#ifdef __hppa\n"
"# define JS_STACK_GROWTH_DIRECTION (1)\n"
"#else\n"
"# define JS_STACK_GROWTH_DIRECTION (-1)\n"
"#endif\n");
printf("#endif /* js_cpucfg___ */\n");
return EXIT_SUCCESS;
}

View File

@ -68,16 +68,40 @@
#define JS_BITS_PER_WORD_LOG2 5
#define JS_ALIGN_OF_POINTER 4L
#else
#elif defined(__APPLE__)
#if __LITTLE_ENDIAN__
#define IS_LITTLE_ENDIAN 1
#undef IS_BIG_ENDIAN
#elif __BIG_ENDIAN__
#undef IS_LITTLE_ENDIAN
#define IS_BIG_ENDIAN 1
#endif
#error "This file is supposed to be auto-generated on most platforms, but the"
#error "static version for Windows and OS2 platforms is being used."
#error "Something's probably wrong with paths/headers/dependencies/Makefiles."
#elif defined(JS_HAVE_ENDIAN_H)
#include <endian.h>
#if defined(__BYTE_ORDER)
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define IS_LITTLE_ENDIAN 1
#undef IS_BIG_ENDIAN
#elif __BYTE_ORDER == __BIG_ENDIAN
#undef IS_LITTLE_ENDIAN
#define IS_BIG_ENDIAN 1
#endif
#else /* !defined(__BYTE_ORDER) */
#error "endian.h does not define __BYTE_ORDER. Cannot determine endianness."
#endif
#else /* !defined(HAVE_ENDIAN_H) */
#error "Cannot determine endianness of your platform. Please add support to jscpucfg.h."
#endif
#ifndef JS_STACK_GROWTH_DIRECTION
#define JS_STACK_GROWTH_DIRECTION (-1)
#ifdef __hppa
# define JS_STACK_GROWTH_DIRECTION (1)
#else
# define JS_STACK_GROWTH_DIRECTION (-1)
#endif
#endif
#endif /* js_cpucfg___ */

View File

@ -297,6 +297,9 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsid id,
AutoValueRooter idroot(cx);
if (JSID_IS_INT(id)) {
propid = id;
} else if (JSID_IS_OBJECT(id)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_WATCH_PROP);
return false;
} else {
if (!js_ValueToStringId(cx, IdToValue(id), &propid))
return false;
@ -328,7 +331,7 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsid id,
}
cx->compartment->watchpointMap = wpmap;
}
return wpmap->watch(cx, obj, id, handler, closure);
return wpmap->watch(cx, obj, propid, handler, closure);
}
JS_PUBLIC_API(JSBool)
@ -1046,9 +1049,6 @@ JS_GetScriptTotalSize(JSContext *cx, JSScript *script)
JSPrincipals *principals;
nbytes = sizeof *script;
if (script->u.object)
nbytes += JS_GetObjectTotalSize(cx, script->u.object);
nbytes += script->length * sizeof script->code[0];
nbytes += script->natoms * sizeof script->atoms[0];
for (size_t i = 0; i < script->natoms; i++)

View File

@ -1558,6 +1558,7 @@ js_XDRFunctionObject(JSXDRState *xdr, JSObject **objp)
uint32 flagsword; /* word for argument count and fun->flags */
cx = xdr->cx;
JSScript *script;
if (xdr->mode == JSXDR_ENCODE) {
fun = (*objp)->getFunctionPrivate();
if (!fun->isInterpreted()) {
@ -1570,12 +1571,14 @@ js_XDRFunctionObject(JSXDRState *xdr, JSObject **objp)
}
firstword = (fun->u.i.skipmin << 2) | !!fun->atom;
flagsword = (fun->nargs << 16) | fun->flags;
script = fun->script();
} else {
fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, NULL, NULL);
if (!fun)
return false;
fun->clearParent();
fun->clearType();
script = NULL;
}
AutoObjectRooter tvr(cx, fun);
@ -1587,28 +1590,20 @@ js_XDRFunctionObject(JSXDRState *xdr, JSObject **objp)
if (!JS_XDRUint32(xdr, &flagsword))
return false;
if (!js_XDRScript(xdr, &script))
return false;
if (xdr->mode == JSXDR_DECODE) {
fun->nargs = flagsword >> 16;
JS_ASSERT((flagsword & JSFUN_KINDMASK) >= JSFUN_INTERPRETED);
fun->flags = uint16(flagsword);
fun->u.i.skipmin = uint16(firstword >> 2);
}
/*
* Don't directly store into fun->u.i.script because we want this to happen
* at the same time as we set the script's owner.
*/
JSScript *script = fun->script();
if (!js_XDRScript(xdr, &script))
return false;
if (xdr->mode == JSXDR_DECODE) {
*objp = fun;
fun->setScript(script);
if (!fun->script()->typeSetFunction(cx, fun))
if (!script->typeSetFunction(cx, fun))
return false;
JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs());
js_CallNewScriptHook(cx, fun->script(), fun);
*objp = fun;
}
return true;
@ -1674,10 +1669,8 @@ fun_trace(JSTracer *trc, JSObject *obj)
if (fun->atom)
MarkString(trc, fun->atom, "atom");
if (fun->isInterpreted() && fun->script()) {
CheckScriptOwner(fun->script(), obj);
if (fun->isInterpreted() && fun->script())
MarkScript(trc, fun->script(), "script");
}
}
static void
@ -2421,19 +2414,18 @@ js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent,
JS_ASSERT(script);
JS_ASSERT(script->compartment() == fun->compartment());
JS_ASSERT(script->compartment() != cx->compartment);
JS_OPT_ASSERT(script->ownerObject == fun);
cfun->u.i.script_ = NULL;
JSScript *cscript = js_CloneScript(cx, script);
if (!cscript)
return NULL;
cscript->u.globalObject = cfun->getGlobal();
cfun->setScript(cscript);
if (!cfun->script()->typeSetFunction(cx, cfun))
if (!cscript->typeSetFunction(cx, cfun))
return NULL;
js_CallNewScriptHook(cx, cfun->script(), cfun);
Debugger::onNewScript(cx, cfun->script(), cfun, NULL);
Debugger::onNewScript(cx, cfun->script(), NULL);
}
}
return clone;

View File

@ -203,10 +203,9 @@ struct JSFunction : public JSObject_Slots2
void setScript(JSScript *script) {
JS_ASSERT(isInterpreted());
u.i.script_ = script;
script->setOwnerObject(this);
}
JSScript * maybeScript() const {
JSScript *maybeScript() const {
return isInterpreted() ? script() : NULL;
}

View File

@ -832,8 +832,8 @@ MarkChildren(JSTracer *trc, JSScript *script)
MarkValueRange(trc, constarray->length, constarray->vector, "consts");
}
if (!script->isCachedEval && script->u.object)
MarkObject(trc, *script->u.object, "object");
if (!script->isCachedEval && script->u.globalObject)
MarkObject(trc, *script->u.globalObject, "object");
if (IS_GC_MARKING_TRACER(trc) && script->filename)
js_MarkScriptFilename(script->filename);

View File

@ -1126,7 +1126,6 @@ class EvalScriptGuard
void setNewScript(JSScript *script) {
/* NewScriptFromCG has already called js_CallNewScriptHook. */
JS_ASSERT(!script_ && script);
script->setOwnerObject(JS_CACHED_SCRIPT);
script_ = script;
script_->isActiveEval = true;
}
@ -6751,25 +6750,21 @@ js_GetClassPrototype(JSContext *cx, JSObject *scopeobj, JSProtoKey protoKey,
JS_ASSERT(protoKey < JSProto_LIMIT);
if (protoKey != JSProto_Null) {
if (!scopeobj) {
if (cx->hasfp())
scopeobj = &cx->fp()->scopeChain();
if (!scopeobj) {
scopeobj = cx->globalObject;
if (!scopeobj) {
*protop = NULL;
return true;
}
}
}
scopeobj = scopeobj->getGlobal();
if (scopeobj->isGlobal()) {
const Value &v = scopeobj->getReservedSlot(JSProto_LIMIT + protoKey);
if (v.isObject()) {
*protop = &v.toObject();
GlobalObject *global;
if (scopeobj) {
global = scopeobj->getGlobal();
} else {
global = GetCurrentGlobal(cx);
if (!global) {
*protop = NULL;
return true;
}
}
const Value &v = global->getReservedSlot(JSProto_LIMIT + protoKey);
if (v.isObject()) {
*protop = &v.toObject();
return true;
}
}
return FindClassPrototype(cx, scopeobj, protoKey, protop, clasp);

View File

@ -1184,12 +1184,6 @@ struct JSObject : js::gc::Cell {
inline js::NativeIterator *getNativeIterator() const;
inline void setNativeIterator(js::NativeIterator *);
/*
* Script-related getters.
*/
inline JSScript *getScript() const;
/*
* XML-related getters and setters.
*/
@ -1465,7 +1459,6 @@ struct JSObject : js::gc::Cell {
inline bool isCall() const { return clasp == &js::CallClass; }
inline bool isDeclEnv() const { return clasp == &js::DeclEnvClass; }
inline bool isRegExp() const { return clasp == &js::RegExpClass; }
inline bool isScript() const { return clasp == &js::ScriptClass; }
inline bool isGenerator() const { return clasp == &js::GeneratorClass; }
inline bool isIterator() const { return clasp == &js::IteratorClass; }
inline bool isStopIteration() const { return clasp == &js::StopIterationClass; }

View File

@ -1472,6 +1472,13 @@ NewNativeClassInstance(JSContext *cx, Class *clasp, JSObject *proto, JSObject *p
return NewNativeClassInstance(cx, clasp, proto, parent, kind);
}
inline GlobalObject *
GetCurrentGlobal(JSContext *cx)
{
JSObject *scopeChain = (cx->hasfp()) ? &cx->fp()->scopeChain() : cx->globalObject;
return scopeChain ? scopeChain->getGlobal() : NULL;
}
bool
FindClassPrototype(JSContext *cx, JSObject *scope, JSProtoKey protoKey, JSObject **protop,
Class *clasp);

View File

@ -129,10 +129,13 @@ class MatchPairs;
enum RegExpFlag
{
IgnoreCaseFlag = JS_BIT(0),
GlobalFlag = JS_BIT(1),
MultilineFlag = JS_BIT(2),
StickyFlag = JS_BIT(3)
IgnoreCaseFlag = 0x01,
GlobalFlag = 0x02,
MultilineFlag = 0x04,
StickyFlag = 0x08,
NoFlags = 0x00,
AllFlags = 0x0f
};
enum RegExpExecType

View File

@ -2354,7 +2354,7 @@ ASTSerializer::comprehension(ParseNode *pn, Value *dst)
return false;
next = next->pn_kid2;
} else if (next->isKind(TOK_LC) && next->pn_count == 0) {
/* js_FoldConstants optimized away the push. */
/* FoldConstants optimized away the push. */
NodeVector empty(cx);
return builder.arrayExpression(empty, &pn->pn_pos, dst);
}

View File

@ -306,14 +306,6 @@ CheckScript(JSScript *script, JSScript *prev)
}
}
void
CheckScriptOwner(JSScript *script, JSObject *owner)
{
JS_OPT_ASSERT(script->ownerObject == owner);
if (owner != JS_NEW_SCRIPT && owner != JS_CACHED_SCRIPT)
JS_OPT_ASSERT(script->compartment() == owner->compartment());
}
#endif /* JS_CRASH_DIAGNOSTICS */
} /* namespace js */
@ -756,37 +748,6 @@ JSPCCounters::destroy(JSContext *cx)
}
}
static void
script_trace(JSTracer *trc, JSObject *obj)
{
JSScript *script = (JSScript *) obj->getPrivate();
if (script) {
CheckScriptOwner(script, obj);
MarkScript(trc, script, "script");
}
}
JS_FRIEND_DATA(Class) js::ScriptClass = {
"Script",
JSCLASS_HAS_PRIVATE |
JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
JS_PropertyStub, /* addProperty */
JS_PropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */
JS_StrictPropertyStub, /* setProperty */
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
NULL, /* finalize */
NULL, /* reserved0 */
NULL, /* checkAccess */
NULL, /* call */
NULL, /* construct */
NULL, /* xdrObject */
NULL, /* hasInstance */
script_trace
};
/*
* Shared script filename management.
*/
@ -965,7 +926,6 @@ JSScript::NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natom
PodZero(script);
#ifdef JS_CRASH_DIAGNOSTICS
script->cookie1[0] = script->cookie2[0] = JS_SCRIPT_COOKIE;
script->ownerObject = JS_NEW_SCRIPT;
#endif
#if JS_SCRIPT_INLINE_DATA_LIMIT
if (!data)
@ -1241,23 +1201,26 @@ JSScript::NewScriptFromCG(JSContext *cx, CodeGenerator *cg)
return NULL;
fun->setScript(script);
script->u.globalObject = fun->getParent() ? fun->getParent()->getGlobal() : NULL;
} else {
/*
* Initialize script->object, if necessary, so that the debugger has a
* valid holder object.
*/
if ((cg->flags & TCF_NEED_SCRIPT_OBJECT) && !js_NewScriptObject(cx, script))
return NULL;
if (cg->flags & TCF_NEED_SCRIPT_GLOBAL)
script->u.globalObject = GetCurrentGlobal(cx);
}
/* Tell the debugger about this compiled script. */
js_CallNewScriptHook(cx, script, fun);
if (!cg->parent) {
JSObject *owner = fun ? fun : script->u.object;
GlobalObject *compileAndGoGlobal = NULL;
if (script->compileAndGo)
compileAndGoGlobal = (owner ? owner : cg->scopeChain())->getGlobal();
Debugger::onNewScript(cx, script, owner, compileAndGoGlobal);
if (script->compileAndGo) {
compileAndGoGlobal = script->u.globalObject;
if (!compileAndGoGlobal)
compileAndGoGlobal = cg->scopeChain()->getGlobal();
}
Debugger::onNewScript(cx, script, compileAndGoGlobal);
}
return script;
@ -1288,15 +1251,6 @@ JSScript::dataSize(JSUsableSizeFun usf)
return usable ? usable : dataSize();
}
void
JSScript::setOwnerObject(JSObject *owner)
{
#ifdef JS_CRASH_DIAGNOSTICS
CheckScriptOwner(this, JS_NEW_SCRIPT);
ownerObject = owner;
#endif
}
/*
* Nb: srcnotes are variable-length. This function computes the number of
* srcnote *slots*, which may be greater than the number of srcnotes.
@ -1371,27 +1325,6 @@ JSScript::finalize(JSContext *cx)
}
}
JSObject *
js_NewScriptObject(JSContext *cx, JSScript *script)
{
JS_ASSERT(!script->u.object);
JSObject *obj = NewNonFunction<WithProto::Class>(cx, &ScriptClass, NULL, NULL);
if (!obj)
return NULL;
obj->setPrivate(script);
script->u.object = obj;
script->setOwnerObject(obj);
/*
* Clear the object's type/proto, to avoid entraining stuff. Once we no longer use the parent
* for security checks, then we can clear the parent, too.
*/
obj->clearType();
return obj;
}
namespace js {
static const uint32 GSN_CACHE_THRESHOLD = 100;

View File

@ -426,9 +426,6 @@ class JSPCCounters {
static const uint32 JS_SCRIPT_COOKIE = 0xc00cee;
static JSObject * const JS_NEW_SCRIPT = (JSObject *)0x12345678;
static JSObject * const JS_CACHED_SCRIPT = (JSObject *)0x12341234;
struct JSScript : public js::gc::Cell {
/*
* Two successively less primitive ways to make a new JSScript. The first
@ -561,19 +558,20 @@ struct JSScript : public js::gc::Cell {
union {
/*
* A script object of class ScriptClass, to ensure the script is GC'd.
* A global object for the script.
* - All scripts returned by JSAPI functions (JS_CompileScript,
* JS_CompileFile, etc.) have these objects.
* - Function scripts never have script objects; such scripts are owned
* by their function objects.
* JS_CompileFile, etc.) have a non-null globalObject.
* - A function script has a globalObject if the function comes from a
* compile-and-go script.
* - Temporary scripts created by obj_eval, JS_EvaluateScript, and
* similar functions never have these objects; such scripts are
* explicitly destroyed by the code that created them.
* similar functions never have the globalObject field set; for such
* scripts the global should be extracted from the JS frame that
* execute scripts.
*/
JSObject *object;
js::GlobalObject *globalObject;
/* Hash table chaining for JSCompartment::evalCache. */
JSScript *evalHashLink;
JSScript *evalHashLink;
} u;
uint32 *closedSlots; /* vector of closed slots; args first, then vars. */
@ -582,14 +580,10 @@ struct JSScript : public js::gc::Cell {
JSPCCounters pcCounters;
#ifdef JS_CRASH_DIAGNOSTICS
JSObject *ownerObject;
/* All diagnostic fields must be multiples of Cell::CellSize. */
uint32 cookie2[sizeof(JSObject *) == 4 ? 1 : 2];
uint32 cookie2[Cell::CellSize / sizeof(uint32)];
#endif
void setOwnerObject(JSObject *owner);
#ifdef DEBUG
/*
* Unique identifier within the compartment for this script, used for
@ -638,6 +632,11 @@ struct JSScript : public js::gc::Cell {
inline void clearNesting();
/* Return creation time global or null. */
js::GlobalObject *getGlobalObjectOrNull() const {
return isCachedEval ? NULL : u.globalObject;
}
private:
bool makeTypes(JSContext *cx, JSFunction *fun);
bool makeAnalysis(JSContext *cx);
@ -685,7 +684,7 @@ struct JSScript : public js::gc::Cell {
/* Size of the JITScript and all sections. (This method is implemented in MethodJIT.h.) */
JS_FRIEND_API(size_t) jitDataSize(JSUsableSizeFun usf);
#endif
jsbytecode *main() {
@ -803,7 +802,7 @@ struct JSScript : public js::gc::Cell {
* count-style interface.)
*/
bool setStepModeFlag(JSContext *cx, bool step);
/*
* Increment or decrement the single-step count. If the count is non-zero or
* the flag (set by setStepModeFlag) is set, then the script is in
@ -848,9 +847,6 @@ StackDepth(JSScript *script)
JS_END_MACRO
extern JSObject *
js_InitScriptClass(JSContext *cx, JSObject *obj);
extern void
js_MarkScriptFilename(const char *filename);
@ -873,19 +869,11 @@ namespace js {
#ifdef JS_CRASH_DIAGNOSTICS
void
CheckScriptOwner(JSScript *script, JSObject *owner);
void
CheckScript(JSScript *script, JSScript *prev);
#else
inline void
CheckScriptOwner(JSScript *script, JSObject *owner)
{
}
inline void
CheckScript(JSScript *script, JSScript *prev)
{
@ -895,9 +883,6 @@ CheckScript(JSScript *script, JSScript *prev)
} /* namespace js */
extern JSObject *
js_NewScriptObject(JSContext *cx, JSScript *script);
/*
* To perturb as little code as possible, we introduce a js_GetSrcNote lookup
* cache without adding an explicit cx parameter. Thus js_GetSrcNote becomes

View File

@ -215,11 +215,4 @@ JSScript::clearNesting()
}
}
inline JSScript *
JSObject::getScript() const
{
JS_ASSERT(isScript());
return static_cast<JSScript *>(getPrivate());
}
#endif /* jsscriptinlines_h___ */

View File

@ -290,11 +290,7 @@
#define JS_MIN(x,y) ((x)<(y)?(x):(y))
#define JS_MAX(x,y) ((x)>(y)?(x):(y))
#ifdef _MSC_VER
# include "jscpucfg.h" /* We can't auto-detect MSVC configuration */
#else
# include "jsautocfg.h" /* Use auto-detected configuration */
#endif
#include "jscpucfg.h"
/*
* Define JS_64BIT iff we are building in an environment with 64-bit

View File

@ -84,6 +84,8 @@ WatchpointMap::watch(JSContext *cx, JSObject *obj, jsid id,
JSWatchPointHandler handler, JSObject *closure)
{
JS_ASSERT(id == js_CheckForStringIndex(id));
JS_ASSERT(JSID_IS_STRING(id) || JSID_IS_INT(id));
obj->setWatched(cx);
Watchpoint w;
w.handler = handler;

View File

@ -723,10 +723,9 @@ JS_XDRScript(JSXDRState *xdr, JSScript **scriptp)
if (xdr->mode == JSXDR_DECODE) {
JS_ASSERT(!script->compileAndGo);
if (!js_NewScriptObject(xdr->cx, script))
return false;
script->u.globalObject = GetCurrentGlobal(xdr->cx);
js_CallNewScriptHook(xdr->cx, script, NULL);
Debugger::onNewScript(xdr->cx, script, script->u.object, NULL);
Debugger::onNewScript(xdr->cx, script, NULL);
*scriptp = script;
}

View File

@ -187,26 +187,6 @@ mjit::Compiler::jsop_bitop(JSOp op)
return;
}
bool lhsIntOrDouble = !(lhs->isNotType(JSVAL_TYPE_DOUBLE) &&
lhs->isNotType(JSVAL_TYPE_INT32));
/* Fast-path double to int conversion. */
if (!lhs->isConstant() && rhs->isConstant() && lhsIntOrDouble &&
rhs->isType(JSVAL_TYPE_INT32) && rhs->getValue().toInt32() == 0 &&
(op == JSOP_BITOR || op == JSOP_LSH)) {
ensureInteger(lhs, Uses(2));
RegisterID reg = frame.ownRegForData(lhs);
stubcc.leave();
OOL_STUBCALL(stub, REJOIN_FALLTHROUGH);
frame.popn(2);
frame.pushTypedPayload(JSVAL_TYPE_INT32, reg);
stubcc.rejoin(Changes(1));
return;
}
/* Convert a double RHS to integer if it's constant for the test below. */
if (rhs->isConstant() && rhs->getValue().isDouble())
rhs->convertConstantDoubleToInt32(cx);
@ -282,7 +262,7 @@ mjit::Compiler::jsop_bitop(JSOp op)
masm.and32(Imm32(rhsInt), reg);
else if (op == JSOP_BITXOR)
masm.xor32(Imm32(rhsInt), reg);
else
else if (rhsInt != 0)
masm.or32(Imm32(rhsInt), reg);
} else if (frame.shouldAvoidDataRemat(rhs)) {
Address rhsAddr = masm.payloadOf(frame.addressOf(rhs));

View File

@ -1562,9 +1562,7 @@ ValueToScript(JSContext *cx, jsval v, JSFunction **funp = NULL)
JSObject *obj = JSVAL_TO_OBJECT(v);
JSClass *clasp = JS_GET_CLASS(cx, obj);
if (clasp == Jsvalify(&ScriptClass)) {
script = (JSScript *) JS_GetPrivate(cx, obj);
} else if (clasp == Jsvalify(&GeneratorClass)) {
if (clasp == Jsvalify(&GeneratorClass)) {
JSGenerator *gen = (JSGenerator *) JS_GetPrivate(cx, obj);
fun = gen->floatingFrame()->fun();
script = fun->script();
@ -1624,8 +1622,7 @@ GetTrapArgs(JSContext *cx, uintN argc, jsval *argv, JSScript **scriptp,
v = argv[0];
intarg = 0;
if (!JSVAL_IS_PRIMITIVE(v) &&
(JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == Jsvalify(&FunctionClass) ||
JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == Jsvalify(&ScriptClass))) {
JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == Jsvalify(&FunctionClass)) {
script = ValueToScript(cx, v);
if (!script)
return JS_FALSE;

View File

@ -58,3 +58,4 @@ require-or(debugMode,skip) script regress-672804-2.js
require-or(debugMode,skip) script regress-672804-3.js
skip-if(!xulRuntime.shell) script regress-677589.js
script regress-677924.js
script regress-691746.js

View File

@ -0,0 +1,11 @@
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/licenses/publicdomain/
var obj = {};
try {
obj.watch(QName(), function () {});
} catch (exc) {
}
gc();
reportCompare(0, 0, 'ok');

View File

@ -88,7 +88,6 @@ extern Class DebuggerScript_class;
enum {
JSSLOT_DEBUGSCRIPT_OWNER,
JSSLOT_DEBUGSCRIPT_HOLDER, /* PrivateValue, cross-compartment pointer */
JSSLOT_DEBUGSCRIPT_COUNT
};
@ -125,7 +124,7 @@ ReportObjectRequired(JSContext *cx)
/*** Breakpoints *********************************************************************************/
BreakpointSite::BreakpointSite(JSScript *script, jsbytecode *pc)
: script(script), pc(pc), realOpcode(JSOp(*pc)), scriptObject(NULL), enabledCount(0),
: script(script), pc(pc), realOpcode(JSOp(*pc)), scriptGlobal(NULL), enabledCount(0),
trapHandler(NULL), trapClosure(UndefinedValue())
{
JS_ASSERT(realOpcode != JSOP_TRAP);
@ -136,11 +135,11 @@ BreakpointSite::BreakpointSite(JSScript *script, jsbytecode *pc)
* Precondition: script is live, meaning either it is a non-held script that is
* on the stack or a held script that hasn't been GC'd.
*/
static JSObject *
ScriptScope(JSContext *cx, JSScript *script, JSObject *holder)
static GlobalObject *
ScriptGlobal(JSContext *cx, JSScript *script, GlobalObject *scriptGlobal)
{
if (holder)
return holder;
if (scriptGlobal)
return scriptGlobal;
/*
* The referent is a non-held script. There is no direct reference from
@ -149,9 +148,9 @@ ScriptScope(JSContext *cx, JSScript *script, JSObject *holder)
for (AllFramesIter i(cx->stack.space()); ; ++i) {
JS_ASSERT(!i.done());
if (i.fp()->maybeScript() == script)
return &i.fp()->scopeChain();
return i.fp()->scopeChain().getGlobal();
}
JS_NOT_REACHED("ScriptScope: live non-held script not on stack");
JS_NOT_REACHED("ScriptGlobal: live non-held script not on stack");
}
bool
@ -161,7 +160,7 @@ BreakpointSite::recompile(JSContext *cx, bool forTrap)
if (script->hasJITCode()) {
Maybe<AutoCompartment> ac;
if (!forTrap) {
ac.construct(cx, ScriptScope(cx, script, scriptObject));
ac.construct(cx, ScriptGlobal(cx, script, scriptGlobal));
if (!ac.ref().enter())
return false;
}
@ -733,7 +732,7 @@ Debugger::fireEnterFrame(JSContext *cx)
}
void
Debugger::fireNewScript(JSContext *cx, JSScript *script, JSObject *obj)
Debugger::fireNewScript(JSContext *cx, JSScript *script)
{
JSObject *hook = getHook(OnNewScript);
JS_ASSERT(hook);
@ -743,7 +742,7 @@ Debugger::fireNewScript(JSContext *cx, JSScript *script, JSObject *obj)
if (!ac.enter())
return;
JSObject *dsobj = wrapScript(cx, script, obj);
JSObject *dsobj = wrapScript(cx, script);
if (!dsobj) {
handleUncaughtException(ac, NULL, false);
return;
@ -816,8 +815,7 @@ AddNewScriptRecipients(GlobalObject::DebuggerVector *src, AutoValueVector *dest)
}
void
Debugger::slowPathOnNewScript(JSContext *cx, JSScript *script, JSObject *obj,
GlobalObject *compileAndGoGlobal)
Debugger::slowPathOnNewScript(JSContext *cx, JSScript *script, GlobalObject *compileAndGoGlobal)
{
JS_ASSERT(script->compileAndGo == !!compileAndGoGlobal);
@ -849,7 +847,7 @@ Debugger::slowPathOnNewScript(JSContext *cx, JSScript *script, JSObject *obj,
Debugger *dbg = Debugger::fromJSObject(&p->toObject());
if ((!compileAndGoGlobal || dbg->debuggees.has(compileAndGoGlobal)) &&
dbg->enabled && dbg->getHook(OnNewScript)) {
dbg->fireNewScript(cx, script, obj);
dbg->fireNewScript(cx, script);
}
}
}
@ -1782,15 +1780,7 @@ static inline JSScript *
GetScriptReferent(JSObject *obj)
{
JS_ASSERT(obj->getClass() == &DebuggerScript_class);
return (JSScript *) obj->getPrivate();
}
static inline JSObject *
GetScriptHolder(JSObject *obj)
{
JS_ASSERT(obj->getClass() == &DebuggerScript_class);
Value v = obj->getReservedSlot(JSSLOT_DEBUGSCRIPT_HOLDER);
return (JSObject *) v.toPrivate();
return static_cast<JSScript *>(obj->getPrivate());
}
static void
@ -1799,11 +1789,6 @@ DebuggerScript_trace(JSTracer *trc, JSObject *obj)
if (!trc->context->runtime->gcCurrentCompartment) {
if (JSScript *script = GetScriptReferent(obj))
MarkScript(trc, script, "Debugger.Script referent");
Value v = obj->getReservedSlot(JSSLOT_DEBUGSCRIPT_HOLDER);
if (!v.isUndefined()) {
if (JSObject *obj = (JSObject *) v.toPrivate())
MarkObject(trc, *obj, "Debugger.Script referent holder");
}
}
}
@ -1821,7 +1806,7 @@ Class DebuggerScript_class = {
};
JSObject *
Debugger::newDebuggerScript(JSContext *cx, JSScript *script, JSObject *holder)
Debugger::newDebuggerScript(JSContext *cx, JSScript *script)
{
assertSameCompartment(cx, object);
@ -1832,21 +1817,18 @@ Debugger::newDebuggerScript(JSContext *cx, JSScript *script, JSObject *holder)
return NULL;
scriptobj->setPrivate(script);
scriptobj->setReservedSlot(JSSLOT_DEBUGSCRIPT_OWNER, ObjectValue(*object));
scriptobj->setReservedSlot(JSSLOT_DEBUGSCRIPT_HOLDER, PrivateValue(holder));
return scriptobj;
}
JSObject *
Debugger::wrapScript(JSContext *cx, JSScript *script, JSObject *obj)
Debugger::wrapScript(JSContext *cx, JSScript *script)
{
assertSameCompartment(cx, object);
JS_ASSERT(cx->compartment != script->compartment());
JS_ASSERT_IF(obj, script->compartment() == obj->compartment());
CellWeakMap::AddPtr p = scripts.lookupForAdd(script);
if (!p) {
JSObject *scriptobj = newDebuggerScript(cx, script, obj);
JSObject *scriptobj = newDebuggerScript(cx, script);
/* The allocation may have caused a GC, which can remove table entries. */
if (!scriptobj || !scripts.relookupOrAdd(p, script, scriptobj))
@ -1857,12 +1839,6 @@ Debugger::wrapScript(JSContext *cx, JSScript *script, JSObject *obj)
return p->value;
}
JSObject *
Debugger::wrapFunctionScript(JSContext *cx, JSFunction *fun)
{
return wrapScript(cx, fun->script(), fun);
}
static JSObject *
DebuggerScript_check(JSContext *cx, const Value &v, const char *clsname, const char *fnname)
{
@ -1879,15 +1855,14 @@ DebuggerScript_check(JSContext *cx, const Value &v, const char *clsname, const c
/*
* Check for Debugger.Script.prototype, which is of class DebuggerScript_class
* but whose holding object is undefined.
* but whose script is null.
*/
if (thisobj->getReservedSlot(JSSLOT_DEBUGSCRIPT_HOLDER).isUndefined()) {
if (!GetScriptReferent(thisobj)) {
JS_ASSERT(!GetScriptReferent(thisobj));
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
clsname, fnname, "prototype object");
return NULL;
}
JS_ASSERT(GetScriptReferent(thisobj));
return thisobj;
}
@ -1954,7 +1929,8 @@ DebuggerScript_getChildScripts(JSContext *cx, uintN argc, Value *vp)
for (uint32 i = script->savedCallerFun ? 1 : 0; i < objects->length; i++) {
JSObject *obj = objects->vector[i];
if (obj->isFunction()) {
JSObject *s = dbg->wrapFunctionScript(cx, (JSFunction *) obj);
JSFunction *fun = static_cast<JSFunction *>(obj);
JSObject *s = dbg->wrapScript(cx, fun->script());
if (!s || !js_NewbornArrayPush(cx, result, ObjectValue(*s)))
return false;
}
@ -2257,8 +2233,8 @@ DebuggerScript_setBreakpoint(JSContext *cx, uintN argc, Value *vp)
THIS_DEBUGSCRIPT_SCRIPT(cx, argc, vp, "setBreakpoint", args, obj, script);
Debugger *dbg = Debugger::fromChildJSObject(obj);
JSObject *holder = GetScriptHolder(obj);
if (!dbg->observesScope(ScriptScope(cx, script, holder))) {
GlobalObject *scriptGlobal = script->getGlobalObjectOrNull();
if (!dbg->observesGlobal(ScriptGlobal(cx, script, scriptGlobal))) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_DEBUG_NOT_DEBUGGING);
return false;
}
@ -2273,7 +2249,7 @@ DebuggerScript_setBreakpoint(JSContext *cx, uintN argc, Value *vp)
JSCompartment *comp = script->compartment();
jsbytecode *pc = script->code + offset;
BreakpointSite *site = comp->getOrCreateBreakpointSite(cx, script, pc, holder);
BreakpointSite *site = comp->getOrCreateBreakpointSite(cx, script, pc, scriptGlobal);
if (!site)
return false;
if (site->inc(cx)) {
@ -2628,7 +2604,7 @@ DebuggerFrame_getScript(JSContext *cx, uintN argc, Value *vp)
if (fp->isFunctionFrame() && !fp->isEvalFrame()) {
JSFunction *callee = fp->callee().getFunctionPrivate();
if (callee->isInterpreted()) {
scriptObject = debug->wrapFunctionScript(cx, callee);
scriptObject = debug->wrapScript(cx, callee->script());
if (!scriptObject)
return false;
}
@ -2638,8 +2614,7 @@ DebuggerFrame_getScript(JSContext *cx, uintN argc, Value *vp)
* frames.
*/
JSScript *script = fp->script();
scriptObject = debug->wrapScript(cx, script,
script->isCachedEval ? NULL : script->u.object);
scriptObject = debug->wrapScript(cx, script);
if (!scriptObject)
return false;
}
@ -2744,7 +2719,7 @@ EvaluateInScope(JSContext *cx, JSObject *scobj, StackFrame *fp, const jschar *ch
*/
JSScript *script = BytecodeCompiler::compileScript(cx, scobj, fp,
fp->scopeChain().principals(cx),
TCF_COMPILE_N_GO | TCF_NEED_SCRIPT_OBJECT,
TCF_COMPILE_N_GO | TCF_NEED_SCRIPT_GLOBAL,
chars, length, filename, lineno,
cx->findVersion(), NULL,
UpvarCookie::UPVAR_LEVEL_LIMIT);
@ -3056,7 +3031,7 @@ DebuggerObject_getScript(JSContext *cx, uintN argc, Value *vp)
if (!fun->isInterpreted())
return true;
JSObject *scriptObject = dbg->wrapFunctionScript(cx, fun);
JSObject *scriptObject = dbg->wrapScript(cx, fun->script());
if (!scriptObject)
return false;

View File

@ -201,7 +201,7 @@ class Debugger {
static void slowPathOnEnterFrame(JSContext *cx);
static void slowPathOnLeaveFrame(JSContext *cx);
static void slowPathOnNewScript(JSContext *cx, JSScript *script, JSObject *obj,
static void slowPathOnNewScript(JSContext *cx, JSScript *script,
GlobalObject *compileAndGoGlobal);
static JSTrapStatus dispatchHook(JSContext *cx, js::Value *vp, Hook which);
@ -210,18 +210,16 @@ class Debugger {
void fireEnterFrame(JSContext *cx);
/*
* Allocate and initialize a Debugger.Script instance whose referent is |script| and
* whose holder is |obj|. If |obj| is NULL, this creates a Debugger.Script whose holder
* is null, for non-held scripts.
* Allocate and initialize a Debugger.Script instance whose referent is
* |script|.
*/
JSObject *newDebuggerScript(JSContext *cx, JSScript *script, JSObject *obj);
JSObject *newDebuggerScript(JSContext *cx, JSScript *script);
/*
* Receive a "new script" event from the engine. A new script was compiled
* or deserialized. For eval scripts obj must be null, otherwise it must be
* a script object.
* or deserialized.
*/
void fireNewScript(JSContext *cx, JSScript *script, JSObject *obj);
void fireNewScript(JSContext *cx, JSScript *script);
static inline Debugger *fromLinks(JSCList *links);
inline Breakpoint *firstBreakpoint() const;
@ -262,7 +260,7 @@ class Debugger {
static inline void onLeaveFrame(JSContext *cx);
static inline JSTrapStatus onDebuggerStatement(JSContext *cx, js::Value *vp);
static inline JSTrapStatus onExceptionUnwind(JSContext *cx, js::Value *vp);
static inline void onNewScript(JSContext *cx, JSScript *script, JSObject *obj,
static inline void onNewScript(JSContext *cx, JSScript *script,
GlobalObject *compileAndGoGlobal);
static JSTrapStatus onTrap(JSContext *cx, Value *vp);
static JSTrapStatus onSingleStep(JSContext *cx, Value *vp);
@ -271,7 +269,7 @@ class Debugger {
inline bool observesEnterFrame() const;
inline bool observesNewScript() const;
inline bool observesScope(JSObject *obj) const;
inline bool observesGlobal(GlobalObject *global) const;
inline bool observesFrame(StackFrame *fp) const;
/*
@ -331,21 +329,12 @@ class Debugger {
*/
bool newCompletionValue(AutoCompartment &ac, bool ok, Value val, Value *vp);
/*
* Return the Debugger.Script object for |fun|'s script, or create a new
* one if needed. The context |cx| must be in the debugger compartment;
* |fun| must be a cross-compartment wrapper referring to the JSFunction in
* a debuggee compartment.
*/
JSObject *wrapFunctionScript(JSContext *cx, JSFunction *fun);
/*
* Return the Debugger.Script object for |script|, or create a new one if
* needed. The context |cx| must be in the debugger compartment; |script| must
* be a script in a debuggee compartment. |obj| is either the script holder or
* null for non-held scripts.
* needed. The context |cx| must be in the debugger compartment; |script|
* must be a script in a debuggee compartment.
*/
JSObject *wrapScript(JSContext *cx, JSScript *script, JSObject *obj);
JSObject *wrapScript(JSContext *cx, JSScript *script);
private:
/* Prohibit copying. */
@ -369,7 +358,7 @@ class BreakpointSite {
* cached eval scripts and for JSD1 traps. It is always non-null for JSD2
* breakpoints in held scripts.
*/
JSObject *scriptObject;
GlobalObject *scriptGlobal;
JSCList breakpoints; /* cyclic list of all js::Breakpoints at this instruction */
size_t enabledCount; /* number of breakpoints in the list that are enabled */
@ -383,7 +372,7 @@ class BreakpointSite {
Breakpoint *firstBreakpoint() const;
bool hasBreakpoint(Breakpoint *bp);
bool hasTrap() const { return !!trapHandler; }
JSObject *getScriptObject() const { return scriptObject; }
GlobalObject *getScriptGlobal() const { return scriptGlobal; }
bool inc(JSContext *cx);
void dec(JSContext *cx);
@ -475,15 +464,15 @@ Debugger::observesNewScript() const
}
bool
Debugger::observesScope(JSObject *obj) const
Debugger::observesGlobal(GlobalObject *global) const
{
return debuggees.has(obj->getGlobal());
return debuggees.has(global);
}
bool
Debugger::observesFrame(StackFrame *fp) const
{
return observesScope(&fp->scopeChain());
return observesGlobal(fp->scopeChain().getGlobal());
}
void
@ -517,13 +506,12 @@ Debugger::onExceptionUnwind(JSContext *cx, js::Value *vp)
}
void
Debugger::onNewScript(JSContext *cx, JSScript *script, JSObject *obj,
GlobalObject *compileAndGoGlobal)
Debugger::onNewScript(JSContext *cx, JSScript *script, GlobalObject *compileAndGoGlobal)
{
JS_ASSERT_IF(script->compileAndGo, compileAndGoGlobal);
JS_ASSERT_IF(!script->compileAndGo, !compileAndGoGlobal);
if (!script->compartment()->getDebuggees().empty())
slowPathOnNewScript(cx, script, obj, compileAndGoGlobal);
slowPathOnNewScript(cx, script, compileAndGoGlobal);
}
extern JSBool

View File

@ -373,7 +373,7 @@ js::GlobalObject *
JSObject::asGlobal()
{
JS_ASSERT(isGlobal());
return reinterpret_cast<js::GlobalObject *>(this);
return static_cast<js::GlobalObject *>(this);
}
#endif /* GlobalObject_h___ */

View File

@ -779,15 +779,6 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
if (si) {
JS_snprintf(name, sizeof(name), "JS Object (%s - %s)",
clazz->name, si->GetJSClass()->name);
} else if (clazz == &js::ScriptClass) {
JSScript* script = (JSScript*) xpc_GetJSPrivate(obj);
if (script->filename) {
JS_snprintf(name, sizeof(name),
"JS Object (Script - %s)",
script->filename);
} else {
JS_snprintf(name, sizeof(name), "JS Object (Script)");
}
} else if (clazz == &js::FunctionClass) {
JSFunction* fun = (JSFunction*) xpc_GetJSPrivate(obj);
JSString* str = JS_GetFunctionId(fun);

View File

@ -118,8 +118,6 @@ NS_IMETHODIMP xpcTestObjectReadWrite :: GetBooleanProperty(bool *aBooleanPropert
return NS_OK;
}
NS_IMETHODIMP xpcTestObjectReadWrite :: SetBooleanProperty(bool aBooleanProperty) {
NS_ENSURE_TRUE(aBooleanProperty == true || aBooleanProperty == false,
NS_ERROR_INVALID_ARG);
boolProperty = aBooleanProperty;
return NS_OK;
}

View File

@ -140,8 +140,6 @@ nsHTMLReflowState::nsHTMLReflowState(nsPresContext* aPresContext,
NS_PRECONDITION((aContainingBlockWidth == -1) ==
(aContainingBlockHeight == -1),
"cb width and height should only be non-default together");
NS_PRECONDITION(aInit == true || aInit == false,
"aInit out of range for bool");
NS_PRECONDITION(!mFlags.mSpecialHeightReflow ||
!NS_SUBTREE_DIRTY(aFrame),
"frame should be clean when getting special height reflow");

View File

@ -587,7 +587,6 @@ protected:
bool aIsRepeating);
void SetParsingCompoundProperty(bool aBool) {
NS_ASSERTION(aBool == true || aBool == false, "bad bool value");
mParsingCompoundProperty = aBool;
}
bool IsParsingCompoundProperty(void) const {
@ -792,7 +791,6 @@ CSSParserImpl::SetStyleSheet(nsCSSStyleSheet* aSheet)
nsresult
CSSParserImpl::SetQuirkMode(bool aQuirkMode)
{
NS_ASSERTION(aQuirkMode == true || aQuirkMode == false, "bad bool value");
mNavQuirkMode = aQuirkMode;
return NS_OK;
}
@ -800,8 +798,6 @@ CSSParserImpl::SetQuirkMode(bool aQuirkMode)
nsresult
CSSParserImpl::SetSVGMode(bool aSVGMode)
{
NS_ASSERTION(aSVGMode == true || aSVGMode == false,
"bad bool value");
mScanner.SetSVGMode(aSVGMode);
return NS_OK;
}
@ -1157,8 +1153,6 @@ CSSParserImpl::ParseMediaList(const nsSubstring& aBuffer,
InitScanner(aBuffer, aURI, aLineNumber, aURI, nsnull);
AssertInitialState();
NS_ASSERTION(aHTMLMode == true || aHTMLMode == false,
"invalid bool");
mHTMLMediaMode = aHTMLMode;
// XXXldb We need to make the scanner not skip CSS comments! (Or

View File

@ -147,8 +147,6 @@ class nsCSSScanner {
// Set whether or not we are processing SVG
void SetSVGMode(bool aSVGMode) {
NS_ASSERTION(aSVGMode == true || aSVGMode == false,
"bad bool value");
mSVGMode = aSVGMode;
}
bool IsSVGMode() const {

View File

@ -0,0 +1,23 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html class="reftest-print">
<style>
div.spacer{height:80px}
td { border: solid 1px blue}
table {border: solid 1px green}
</style>
<body>
<div class="spacer"> </div>
<table>
<tbody>
<tr>
<td height="50" ></td>
<td rowspan="2"><img height="120" width="60"></td>
</tr>
<tr>
<td height="500" width="70"></td>
</tr>
</tbody>
</table>
</body></html>

View File

@ -110,3 +110,4 @@ asserts(0-3) load 595758-1.xhtml # Bug 453871
load 595758-2.xhtml
load 678447-1.html
load 691824-1.xhtml
load 695430-1.html

View File

@ -1032,6 +1032,8 @@ nsTableRowGroupFrame::UndoContinuedRow(nsPresContext* aPresContext,
// will not have reflowed yet to pick up content from any overflow lines.
overflows->DestroyFrame(aRow);
if (overflows->IsEmpty())
return;
// Put the overflow rows into our child list
mFrames.InsertFrames(nsnull, rowBefore, *overflows);
}

View File

@ -1,5 +1,5 @@
/* -*- Mode: C; tab-width: 8; c-basic-offset: 8; indent-tabs-mode: t -*- */
/* vim:set softtabstop=8 shiftwidth=8: */
/* vim:set softtabstop=8 shiftwidth=8 noet: */
/*-
* Copyright (C) 2006-2008 Jason Evans <jasone@FreeBSD.org>.
* All rights reserved.
@ -105,6 +105,29 @@
#define _pthread_self() pthread_self()
#endif
/*
* On Linux, we use madvise(MADV_DONTNEED) to release memory back to the
* operating system. If we release 1MB of live pages with MADV_DONTNEED, our
* RSS will decrease by 1MB (almost) immediately.
*
* On Mac, we use madvise(MADV_FREE). Unlike MADV_DONTNEED on Linux, MADV_FREE
* on Mac doesn't cause the OS to release the specified pages immediately; the
* OS keeps them in our process until the machine comes under memory pressure.
*
* It's therefore difficult to measure the process's RSS on Mac, since, in the
* absence of memory pressure, the contribution from the heap to RSS will not
* decrease due to our madvise calls.
*
* We therefore define MALLOC_DOUBLE_PURGE on Mac. This causes jemalloc to
* track which pages have been MADV_FREE'd. You can then call
* jemalloc_purge_freed_pages(), which will force the OS to release those
* MADV_FREE'd pages, making the process's RSS reflect its true memory usage.
*
*/
#ifdef MOZ_MEMORY_DARWIN
#define MALLOC_DOUBLE_PURGE
#endif
/*
* MALLOC_PRODUCTION disables assertions and statistics gathering. It also
* defaults the A and J runtime options to off. These settings are appropriate
@ -354,6 +377,7 @@ __FBSDID("$FreeBSD: head/lib/libc/stdlib/malloc.c 180599 2008-07-18 19:35:44Z ja
#endif
#include "jemalloc.h"
#include "linkedlist.h"
/* Some tools, such as /dev/dsp wrappers, LD_PRELOAD libraries that
* happen to override mmap() and call dlsym() from their overridden
@ -605,6 +629,11 @@ static const bool __isthreaded = true;
/******************************************************************************/
/* MALLOC_DECOMMIT and MALLOC_DOUBLE_PURGE are mutually exclusive. */
#if defined(MALLOC_DECOMMIT) && defined(MALLOC_DOUBLE_PURGE)
#error MALLOC_DECOMMIT and MALLOC_DOUBLE_PURGE are mutually exclusive.
#endif
/*
* Mutexes based on spinlocks. We can't use normal pthread spinlocks in all
* places, because they require malloc()ed memory, which causes bootstrapping
@ -807,13 +836,14 @@ struct arena_chunk_map_s {
* Run address (or size) and various flags are stored together. The bit
* layout looks like (assuming 32-bit system):
*
* ???????? ???????? ????---- --ckdzla
* ???????? ???????? ????---- -mckdzla
*
* ? : Unallocated: Run address for first/last pages, unset for internal
* pages.
* Small: Run address.
* Large: Run size for first page, unset for trailing pages.
* - : Unused.
* m : MADV_FREE/MADV_DONTNEED'ed?
* c : decommitted?
* k : key?
* d : dirty?
@ -845,8 +875,27 @@ struct arena_chunk_map_s {
* -------- -------- -------- ------la
*/
size_t bits;
#if defined(MALLOC_DECOMMIT) || defined(MALLOC_STATS)
/* Note that CHUNK_MAP_DECOMMITTED's meaning varies depending on whether
* MALLOC_DECOMMIT and MALLOC_DOUBLE_PURGE are defined.
*
* If MALLOC_DECOMMIT is defined, a page which is CHUNK_MAP_DECOMMITTED must be
* re-committed with pages_commit() before it may be touched. If
* MALLOC_DECOMMIT is defined, MALLOC_DOUBLE_PURGE may not be defined.
*
* If neither MALLOC_DECOMMIT nor MALLOC_DOUBLE_PURGE is defined, pages which
* are madvised (with either MADV_DONTNEED or MADV_FREE) are marked with
* CHUNK_MAP_MADVISED.
*
* Otherwise, if MALLOC_DECOMMIT is not defined and MALLOC_DOUBLE_PURGE is
* defined, then a page which is madvised is marked as CHUNK_MAP_MADVISED.
* When it's finally freed with jemalloc_purge_freed_pages, the page is marked
* as CHUNK_MAP_DECOMMITTED.
*/
#if defined(MALLOC_DECOMMIT) || defined(MALLOC_STATS) || defined(MALLOC_DOUBLE_PURGE)
#define CHUNK_MAP_MADVISED ((size_t)0x40U)
#define CHUNK_MAP_DECOMMITTED ((size_t)0x20U)
#define CHUNK_MAP_MADVISED_OR_DECOMMITTED (CHUNK_MAP_MADVISED | CHUNK_MAP_DECOMMITTED)
#endif
#define CHUNK_MAP_KEY ((size_t)0x10U)
#define CHUNK_MAP_DIRTY ((size_t)0x08U)
@ -866,6 +915,16 @@ struct arena_chunk_s {
/* Linkage for the arena's chunks_dirty tree. */
rb_node(arena_chunk_t) link_dirty;
#ifdef MALLOC_DOUBLE_PURGE
/* If we're double-purging, we maintain a linked list of chunks which
* have pages which have been madvise(MADV_FREE)'d but not explicitly
* purged.
*
* We're currently lazy and don't remove a chunk from this list when
* all its madvised pages are recommitted. */
LinkedList chunks_madvised_elem;
#endif
/* Number of dirty pages. */
size_t ndirty;
@ -951,6 +1010,12 @@ struct arena_s {
/* Tree of dirty-page-containing chunks this arena manages. */
arena_chunk_tree_t chunks_dirty;
#ifdef MALLOC_DOUBLE_PURGE
/* Head of a linked list of MADV_FREE'd-page-containing chunks this
* arena manages. */
LinkedList chunks_madvised;
#endif
/*
* In order to avoid rapid chunk allocation/deallocation when an arena
* oscillates right on the cusp of needing a new chunk, cache the most
@ -1808,7 +1873,6 @@ malloc_printf(const char *format, ...)
/******************************************************************************/
#ifdef MALLOC_DECOMMIT
static inline void
pages_decommit(void *addr, size_t size)
{
@ -1834,7 +1898,6 @@ pages_commit(void *addr, size_t size)
abort();
# endif
}
#endif
static bool
base_pages_alloc_mmap(size_t minsize)
@ -3069,25 +3132,29 @@ arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool large,
}
for (i = 0; i < need_pages; i++) {
#if defined(MALLOC_DECOMMIT) || defined(MALLOC_STATS)
#if defined(MALLOC_DECOMMIT) || defined(MALLOC_STATS) || defined(MALLOC_DOUBLE_PURGE)
/*
* Commit decommitted pages if necessary. If a decommitted
* page is encountered, commit all needed adjacent decommitted
* pages in one operation, in order to reduce system call
* overhead.
*/
if (chunk->map[run_ind + i].bits & CHUNK_MAP_DECOMMITTED) {
if (chunk->map[run_ind + i].bits & CHUNK_MAP_MADVISED_OR_DECOMMITTED) {
size_t j;
/*
* Advance i+j to just past the index of the last page
* to commit. Clear CHUNK_MAP_DECOMMITTED along the
* way.
* to commit. Clear CHUNK_MAP_DECOMMITTED and
* CHUNK_MAP_MADVISED along the way.
*/
for (j = 0; i + j < need_pages && (chunk->map[run_ind +
i + j].bits & CHUNK_MAP_DECOMMITTED); j++) {
chunk->map[run_ind + i + j].bits ^=
CHUNK_MAP_DECOMMITTED;
i + j].bits & CHUNK_MAP_MADVISED_OR_DECOMMITTED); j++) {
/* DECOMMITTED and MADVISED are mutually exclusive. */
assert(!(chunk->map[run_ind + i + j].bits & CHUNK_MAP_DECOMMITTED &&
chunk->map[run_ind + i + j].bits & CHUNK_MAP_MADVISED));
chunk->map[run_ind + i + j].bits &=
~CHUNK_MAP_MADVISED_OR_DECOMMITTED;
}
# ifdef MALLOC_DECOMMIT
@ -3204,6 +3271,10 @@ arena_chunk_init(arena_t *arena, arena_chunk_t *chunk)
/* Insert the run into the runs_avail tree. */
arena_avail_tree_insert(&arena->runs_avail,
&chunk->map[arena_chunk_header_npages]);
#ifdef MALLOC_DOUBLE_PURGE
LinkedList_Init(&chunk->chunks_madvised_elem);
#endif
}
static void
@ -3219,6 +3290,12 @@ arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk)
arena->stats.committed -= arena->spare->ndirty;
#endif
}
#ifdef MALLOC_DOUBLE_PURGE
/* This is safe to do even if arena->spare is not in the list. */
LinkedList_Remove(&arena->spare->chunks_madvised_elem);
#endif
VALGRIND_FREELIKE_BLOCK(arena->spare, 0);
chunk_dealloc((void *)arena->spare, chunksize);
#ifdef MALLOC_STATS
@ -3322,6 +3399,9 @@ arena_purge(arena_t *arena)
* purged.
*/
while (arena->ndirty > (opt_dirty_max >> 1)) {
#ifdef MALLOC_DOUBLE_PURGE
bool madvised = false;
#endif
chunk = arena_chunk_tree_dirty_last(&arena->chunks_dirty);
assert(chunk != NULL);
@ -3329,17 +3409,23 @@ arena_purge(arena_t *arena)
assert(i >= arena_chunk_header_npages);
if (chunk->map[i].bits & CHUNK_MAP_DIRTY) {
#ifdef MALLOC_DECOMMIT
const size_t free_operation = CHUNK_MAP_DECOMMITTED;
#else
const size_t free_operation = CHUNK_MAP_MADVISED;
#endif
assert((chunk->map[i].bits &
CHUNK_MAP_DECOMMITTED) == 0);
chunk->map[i].bits ^= CHUNK_MAP_DECOMMITTED | CHUNK_MAP_DIRTY;
CHUNK_MAP_MADVISED_OR_DECOMMITTED) == 0);
chunk->map[i].bits ^= free_operation | CHUNK_MAP_DIRTY;
/* Find adjacent dirty run(s). */
for (npages = 1; i > arena_chunk_header_npages
&& (chunk->map[i - 1].bits &
CHUNK_MAP_DIRTY); npages++) {
for (npages = 1;
i > arena_chunk_header_npages &&
(chunk->map[i - 1].bits & CHUNK_MAP_DIRTY);
npages++) {
i--;
assert((chunk->map[i].bits &
CHUNK_MAP_DECOMMITTED) == 0);
chunk->map[i].bits ^= CHUNK_MAP_DECOMMITTED | CHUNK_MAP_DIRTY;
CHUNK_MAP_MADVISED_OR_DECOMMITTED) == 0);
chunk->map[i].bits ^= free_operation | CHUNK_MAP_DIRTY;
}
chunk->ndirty -= npages;
arena->ndirty -= npages;
@ -3361,6 +3447,9 @@ arena_purge(arena_t *arena)
madvise((void *)((uintptr_t)chunk + (i <<
pagesize_2pow)), (npages << pagesize_2pow),
MADV_FREE);
# ifdef MALLOC_DOUBLE_PURGE
madvised = true;
# endif
#endif
#ifdef MALLOC_STATS
arena->stats.nmadvise++;
@ -3375,6 +3464,14 @@ arena_purge(arena_t *arena)
arena_chunk_tree_dirty_remove(&arena->chunks_dirty,
chunk);
}
#ifdef MALLOC_DOUBLE_PURGE
if (madvised) {
/* The chunk might already be in the list, but this
* makes sure it's at the front. */
LinkedList_Remove(&chunk->chunks_madvised_elem);
LinkedList_InsertHead(&arena->chunks_madvised, &chunk->chunks_madvised_elem);
}
#endif
}
}
@ -4562,6 +4659,9 @@ arena_new(arena_t *arena)
/* Initialize chunks. */
arena_chunk_tree_dirty_new(&arena->chunks_dirty);
#ifdef MALLOC_DOUBLE_PURGE
LinkedList_Init(&arena->chunks_madvised);
#endif
arena->spare = NULL;
arena->ndirty = 0;
@ -6381,6 +6481,78 @@ jemalloc_stats(jemalloc_stats_t *stats)
assert(stats->committed >= stats->allocated);
}
#ifdef MALLOC_DOUBLE_PURGE
/* Explicitly remove all of this chunk's MADV_FREE'd pages from memory. */
static void
hard_purge_chunk(arena_chunk_t *chunk)
{
/* See similar logic in arena_purge(). */
size_t i;
for (i = arena_chunk_header_npages; i < chunk_npages; i++) {
/* Find all adjacent pages with CHUNK_MAP_MADVISED set. */
size_t npages;
for (npages = 0;
chunk->map[i + npages].bits & CHUNK_MAP_MADVISED && i + npages < chunk_npages;
npages++) {
/* Turn off the chunk's MADV_FREED bit and turn on its
* DECOMMITTED bit. */
assert(!(chunk->map[i + npages].bits & CHUNK_MAP_DECOMMITTED));
chunk->map[i + npages].bits ^= CHUNK_MAP_MADVISED_OR_DECOMMITTED;
}
/* We could use mincore to find out which pages are actually
* present, but it's not clear that's better. */
if (npages > 0) {
pages_decommit(((char*)chunk) + (i << pagesize_2pow), npages << pagesize_2pow);
pages_commit(((char*)chunk) + (i << pagesize_2pow), npages << pagesize_2pow);
}
i += npages;
}
}
/* Explicitly remove all of this arena's MADV_FREE'd pages from memory. */
static void
hard_purge_arena(arena_t *arena)
{
malloc_spin_lock(&arena->lock);
while (!LinkedList_IsEmpty(&arena->chunks_madvised)) {
LinkedList* next = arena->chunks_madvised.next;
arena_chunk_t *chunk =
LinkedList_Get(arena->chunks_madvised.next,
arena_chunk_t, chunks_madvised_elem);
hard_purge_chunk(chunk);
LinkedList_Remove(&chunk->chunks_madvised_elem);
}
malloc_spin_unlock(&arena->lock);
}
void
jemalloc_purge_freed_pages()
{
size_t i;
for (i = 0; i < narenas; i++) {
arena_t *arena = arenas[i];
if (arena != NULL)
hard_purge_arena(arena);
}
}
#else /* !defined MALLOC_DOUBLE_PURGE */
void
jemalloc_purge_freed_pages()
{
/* Do nothing. */
}
#endif /* defined MALLOC_DOUBLE_PURGE */
#ifdef MOZ_MEMORY_WINDOWS
void*
_recalloc(void *ptr, size_t count, size_t size)

View File

@ -80,6 +80,33 @@ size_t malloc_usable_size(const void *ptr);
void jemalloc_stats(jemalloc_stats_t *stats);
/*
* On some operating systems (Mac), we use madvise(MADV_FREE) to hand pages
* back to the operating system. On Mac, the operating system doesn't take
* this memory back immediately; instead, the OS takes it back only when the
* machine is running out of physical memory.
*
* This is great from the standpoint of efficiency, but it makes measuring our
* actual RSS difficult, because pages which we've MADV_FREE'd shouldn't count
* against our RSS.
*
* This function explicitly purges any MADV_FREE'd pages from physical memory,
* causing our reported RSS match the amount of memory we're actually using.
*
* Note that this call is expensive in two ways. First, it may be slow to
* execute, because it may make a number of slow syscalls to free memory. This
* function holds the big jemalloc locks, so basically all threads are blocked
* while this function runs.
*
* This function is also expensive in that the next time we go to access a page
* which we've just explicitly decommitted, the operating system has to attach
* to it a physical page! If we hadn't run this function, the OS would have
* less work to do.
*
* If MALLOC_DOUBLE_PURGE is not defined, this function does nothing.
*/
void jemalloc_purge_freed_pages();
#ifdef __cplusplus
} /* extern "C" */
#endif

View File

@ -0,0 +1,77 @@
/* -*- Mode: C; tab-width: 8; c-basic-offset: 8; indent-tabs-mode: t -*- */
/* vim:set softtabstop=8 shiftwidth=8 noet: */
/*-
* Copyright (C) the Mozilla Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice(s), this list of conditions and the following disclaimer as
* the first lines of this file unmodified other than the possible
* addition of one or more copyright notices.
* 2. Redistributions in binary form must reproduce the above copyright
* notice(s), this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************/
#ifndef linkedlist_h__
#define linkedlist_h__
#include <stddef.h>
typedef struct LinkedList_s LinkedList;
struct LinkedList_s {
LinkedList *next;
LinkedList *prev;
};
/* Convert from LinkedList* to foo*. */
#define LinkedList_Get(e, type, prop) \
(type*)((char*)(e) - offsetof(type, prop))
/* Insert |e| at the beginning of |l|. */
void LinkedList_InsertHead(LinkedList *l, LinkedList *e)
{
e->next = l;
e->prev = l->prev;
e->next->prev = e;
e->prev->next = e;
}
void LinkedList_Remove(LinkedList *e)
{
e->prev->next = e->next;
e->next->prev = e->prev;
e->next = e;
e->prev = e;
}
bool LinkedList_IsEmpty(LinkedList *e)
{
return e->next == e;
}
void LinkedList_Init(LinkedList *e)
{
e->next = e;
e->prev = e;
}
#endif

View File

@ -245,8 +245,9 @@ var Browser = {
let { x: x2, y: y2 } = Browser.getScrollboxPosition(Browser.pageScrollboxScroller);
let [,, leftWidth, rightWidth] = Browser.computeSidebarVisibility();
let shouldHideSidebars = Browser.controlsPosition ? Browser.controlsPosition.hideSidebars : true;
Browser.controlsPosition = { x: x1, y: y2, hideSidebars: shouldHideSidebars,
// hiddenSidebars counts how many times resizeHandler has called hideSidebars
let hiddenSidebars = Browser.controlsPosition ? Browser.controlsPosition.hiddenSidebars : 0;
Browser.controlsPosition = { x: x1, y: y2, hiddenSidebars: hiddenSidebars,
leftSidebar: leftWidth, rightSidebar: rightWidth };
}, true);
@ -276,8 +277,12 @@ var Browser = {
ViewableAreaObserver.update();
// Restore the previous scroll position
let restorePosition = Browser.controlsPosition || { hideSidebars: true };
if (restorePosition.hideSidebars) {
let restorePosition = Browser.controlsPosition || { hiddenSidebars: 0 };
// HACK: The first time we hide the sidebars during startup might be too
// early, before layout is completed. Make sure to hide the sidebars on
// the first *two* resize events (bug 691541).
if (restorePosition.hiddenSidebars < 2) {
// Since this happens early in the startup process, we need to make sure
// the UI has really responded
let x = {}, y = {};
@ -285,7 +290,7 @@ var Browser = {
Browser.controlsScrollboxScroller.getPosition(x, y);
if (x.value > 0) {
// Update the control position data so we are set correctly for the next resize
restorePosition.hideSidebars = false;
restorePosition.hiddenSidebars++;
restorePosition.x = x.value;
}
} else {

View File

@ -234,6 +234,11 @@ nsresult nsZipHandle::Init(nsZipArchive *zip, const char *entry,
return NS_OK;
}
PRInt64 nsZipHandle::SizeOfMapping()
{
return mLen;
}
nsZipHandle::~nsZipHandle()
{
if (mMap) {
@ -775,6 +780,14 @@ MOZ_WIN_MEM_TRY_BEGIN
MOZ_WIN_MEM_TRY_CATCH(return nsnull)
}
//---------------------------------------------
// nsZipArchive::SizeOfMapping
//---------------------------------------------
PRInt64 nsZipArchive::SizeOfMapping()
{
return mFd ? mFd->SizeOfMapping() : 0;
}
//------------------------------------------
// nsZipArchive constructor and destructor
//------------------------------------------

View File

@ -221,6 +221,12 @@ public:
*/
const PRUint8* GetData(nsZipItem* aItem);
/**
* Gets the amount of memory taken up by the archive's mapping.
* @return the size
*/
PRInt64 SizeOfMapping();
private:
//--- private members ---
@ -382,6 +388,8 @@ public:
NS_METHOD_(nsrefcnt) AddRef(void);
NS_METHOD_(nsrefcnt) Release(void);
PRInt64 SizeOfMapping();
protected:
const PRUint8 * mFileData; /* pointer to mmaped file */
PRUint32 mLen; /* length of file and memory mapped area */

View File

@ -49,6 +49,7 @@
#include "nsIClassInfo.h"
#include "nsIFile.h"
#include "nsILocalFile.h"
#include "nsIMemoryReporter.h"
#include "nsIObserver.h"
#include "nsIObserverService.h"
#include "nsIOutputStream.h"
@ -81,6 +82,22 @@
#define SC_WORDSIZE "8"
#endif
static PRInt64
GetStartupCacheSize()
{
mozilla::scache::StartupCache* sc = mozilla::scache::StartupCache::GetSingleton();
return sc ? sc->SizeOfMapping() : 0;
}
NS_MEMORY_REPORTER_IMPLEMENT(StartupCache,
"explicit/startup-cache",
KIND_NONHEAP,
nsIMemoryReporter::UNITS_BYTES,
GetStartupCacheSize,
"Memory used to hold the startup cache. This "
"memory is backed by a file and is likely to be "
"swapped out shortly after start-up.")
namespace mozilla {
namespace scache {
@ -120,7 +137,8 @@ StartupCache* StartupCache::gStartupCache;
bool StartupCache::gShutdownInitiated;
StartupCache::StartupCache()
: mArchive(NULL), mStartupWriteInitiated(false), mWriteThread(NULL) {}
: mArchive(NULL), mStartupWriteInitiated(false), mWriteThread(NULL),
mMemoryReporter(nsnull) { }
StartupCache::~StartupCache()
{
@ -134,6 +152,8 @@ StartupCache::~StartupCache()
WaitOnWriteThread();
WriteToDisk();
gStartupCache = nsnull;
(void)::NS_UnregisterMemoryReporter(mMemoryReporter);
mMemoryReporter = nsnull;
}
nsresult
@ -206,6 +226,10 @@ StartupCache::Init()
NS_WARNING("Failed to load startupcache file correctly, removing!");
InvalidateCache();
}
mMemoryReporter = new NS_MEMORY_REPORTER_NAME(StartupCache);
(void)::NS_RegisterMemoryReporter(mMemoryReporter);
return NS_OK;
}
@ -308,6 +332,12 @@ StartupCache::PutBuffer(const char* id, const char* inbuf, PRUint32 len)
return ResetStartupWriteTimer();
}
PRInt64
StartupCache::SizeOfMapping()
{
return mArchive ? mArchive->SizeOfMapping() : 0;
}
struct CacheWriteHolder
{
nsCOMPtr<nsIZipWriter> writer;

View File

@ -95,6 +95,8 @@
* provide some convenience in writing out data.
*/
class nsIMemoryReporter;
namespace mozilla {
namespace scache {
@ -148,6 +150,8 @@ public:
static StartupCache* GetSingleton();
static void DeleteSingleton();
PRInt64 SizeOfMapping();
private:
StartupCache();
~StartupCache();
@ -178,6 +182,8 @@ private:
#ifdef DEBUG
nsTHashtable<nsISupportsHashKey> mWriteObjectMap;
#endif
nsIMemoryReporter* mMemoryReporter;
};
// This debug outputstream attempts to detect if clients are writing multiple

View File

@ -84,6 +84,9 @@ HISTOGRAM(MEMORY_STORAGE_SQLITE, 1024, 512 * 1024, 50, EXPONENTIAL, "Memory used
HISTOGRAM(MEMORY_IMAGES_CONTENT_USED_UNCOMPRESSED, 1024, 1024 * 1024, 50, EXPONENTIAL, "Memory used for uncompressed, in-use content images (KB)")
HISTOGRAM(MEMORY_HEAP_ALLOCATED, 1024, 1024 * 1024, 50, EXPONENTIAL, "Heap memory allocated (KB)")
HISTOGRAM(MEMORY_EXPLICIT, 1024, 1024 * 1024, 50, EXPONENTIAL, "Explicit memory allocations (KB)")
#if defined(XP_MACOSX)
HISTOGRAM(MEMORY_FREE_PURGED_PAGES_MS, 1, 1024, 10, EXPONENTIAL, "Time(ms) to purge MADV_FREE'd heap pages.")
#endif
#if defined(XP_WIN)
HISTOGRAM(EARLY_GLUESTARTUP_READ_OPS, 1, 100, 12, LINEAR, "ProcessIoCounters.ReadOperationCount before glue startup")
HISTOGRAM(EARLY_GLUESTARTUP_READ_TRANSFER, 1, 50 * 1024, 12, EXPONENTIAL, "ProcessIoCounters.ReadTransferCount before glue startup (KB)")

View File

@ -40,6 +40,7 @@ const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/LightweightThemeManager.jsm");
// When modifying the payload in incompatible ways, please bump this version number
const PAYLOAD_VERSION = 1;
@ -191,8 +192,7 @@ function getMetadata(reason) {
* @return simple measurements as a dictionary.
*/
function getSimpleMeasurements() {
let si = Cc["@mozilla.org/toolkit/app-startup;1"].
getService(Ci.nsIAppStartup).getStartupInfo();
let si = Services.startup.getStartupInfo();
var ret = {
// uptime in minutes
@ -206,6 +206,7 @@ function getSimpleMeasurements() {
ret[field] = si[field] - si.process
}
}
ret.startupInterrupted = new Number(Services.startup.interrupted);
ret.js = Cc["@mozilla.org/js/xpc/XPConnect;1"]
.getService(Ci.nsIJSEngineTelemetryStats)
@ -230,6 +231,54 @@ TelemetryPing.prototype = {
h.add(val);
},
/**
* Descriptive metadata
*
* @param reason
* The reason for the telemetry ping, this will be included in the
* returned metadata,
* @return The metadata as a JS object
*/
getMetadata: function getMetadata(reason) {
let ai = Services.appinfo;
let ret = {
reason: reason,
OS: ai.OS,
appID: ai.ID,
appVersion: ai.version,
appName: ai.name,
appBuildID: ai.appBuildID,
platformBuildID: ai.platformBuildID,
};
// sysinfo fields are not always available, get what we can.
let sysInfo = Cc["@mozilla.org/system-info;1"].getService(Ci.nsIPropertyBag2);
let fields = ["cpucount", "memsize", "arch", "version", "device", "manufacturer", "hardware"];
for each (let field in fields) {
let value;
try {
value = sysInfo.getProperty(field);
} catch (e) {
continue
}
if (field == "memsize") {
// Send RAM size in megabytes. Rounding because sysinfo doesn't
// always provide RAM in multiples of 1024.
value = Math.round(value / 1024 / 1024)
}
ret[field] = value
}
let theme = LightweightThemeManager.currentTheme;
if (theme)
ret.persona = theme.id;
if (this._addons)
ret.addons = this._addons;
return ret;
},
/**
* Pull values from about:memory into corresponding histograms
*/
@ -296,10 +345,11 @@ TelemetryPing.prototype = {
this.gatherMemory();
let payload = {
ver: PAYLOAD_VERSION,
info: getMetadata(reason),
info: this.getMetadata(reason),
simpleMeasurements: getSimpleMeasurements(),
histograms: getHistograms()
};
let isTestPing = (reason == "test-ping");
// Generate a unique id once per session so the server can cope with duplicate submissions.
// Use a deterministic url for testing.
@ -405,6 +455,9 @@ TelemetryPing.prototype = {
var server = this._server;
switch (aTopic) {
case "Add-ons":
this._addons = aData;
break;
case "profile-after-change":
this.setup();
break;

View File

@ -10,6 +10,7 @@
do_load_httpd_js();
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/LightweightThemeManager.jsm");
const PATH = "/submit/telemetry/test-ping";
const SERVER = "http://localhost:4444";
@ -21,6 +22,7 @@ const BinaryInputStream = Components.Constructor(
"setInputStream");
var httpserver = new nsHttpServer();
var gFinished = false;
function telemetry_ping () {
const TelemetryPing = Cc["@mozilla.org/base/telemetry-ping;1"].getService(Ci.nsIObserver);
@ -43,34 +45,20 @@ function telemetryObserver(aSubject, aTopic, aData) {
httpserver.registerPathHandler(PATH, checkHistograms);
const Telemetry = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry);
Telemetry.newHistogram(IGNORE_HISTOGRAM, 1, 2, 3, Telemetry.HISTOGRAM_BOOLEAN);
Services.startup.interrupted = true;
telemetry_ping();
}
function run_test() {
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
Services.obs.addObserver(nonexistentServerObserver, "telemetry-test-xhr-complete", false);
telemetry_ping();
// spin the event loop
do_test_pending();
}
function readBytesFromInputStream(inputStream, count) {
if (!count) {
count = inputStream.available();
}
return new BinaryInputStream(inputStream).readBytes(count);
}
function checkHistograms(request, response) {
// do not need the http server anymore
httpserver.stop(do_test_finished);
let s = request.bodyInputStream
let s = request.bodyInputStream;
let payload = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON)
.decode(readBytesFromInputStream(s))
.decodeFromStream(s, s.available());
do_check_eq(request.getHeader("content-type"), "application/json; charset=UTF-8");
do_check_true(payload.simpleMeasurements.uptime >= 0)
do_check_true(payload.simpleMeasurements.startupInterrupted === 1);
// get rid of the non-deterministic field
const expected_info = {
reason: "test-ping",
@ -102,6 +90,7 @@ function checkHistograms(request, response) {
let tc = payload.histograms[TELEMETRY_SUCCESS]
do_check_eq(uneval(tc),
uneval(expected_tc));
gFinished = true;
}
// copied from toolkit/mozapps/extensions/test/xpcshell/head_addons.js
@ -152,3 +141,34 @@ function createAppInfo(id, name, version, platformVersion) {
registrar.registerFactory(XULAPPINFO_CID, "XULAppInfo",
XULAPPINFO_CONTRACTID, XULAppInfoFactory);
}
function dummyTheme(id) {
return {
id: id,
name: Math.random().toString(),
headerURL: "http://lwttest.invalid/a.png",
footerURL: "http://lwttest.invalid/b.png",
textcolor: Math.random().toString(),
accentcolor: Math.random().toString()
};
}
function run_test() {
// Addon manager needs a profile directory
do_get_profile();
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
// try to make LightweightThemeManager do stuff
let gInternalManager = Cc["@mozilla.org/addons/integration;1"]
.getService(Ci.nsIObserver)
.QueryInterface(Ci.nsITimerCallback);
gInternalManager.observe(null, "addons-startup", null);
LightweightThemeManager.currentTheme = dummyTheme("1234");
Services.obs.addObserver(nonexistentServerObserver, "telemetry-test-xhr-complete", false);
telemetry_ping();
// spin the event loop
do_test_pending();
// ensure that test runs to completion
do_register_cleanup(function () do_check_true(gFinished))
}

View File

@ -1762,6 +1762,9 @@ var XPIProvider = {
Services.appinfo.annotateCrashReport("Add-ons", data);
}
catch (e) { }
const TelemetryPing = Cc["@mozilla.org/base/telemetry-ping;1"].getService(Ci.nsIObserver);
TelemetryPing.observe(null, "Add-ons", data);
},
/**
@ -2550,6 +2553,7 @@ var XPIProvider = {
LOG("New add-on " + aId + " installed in " + aInstallLocation.name);
let newAddon = null;
let sameVersion = false;
// Check the updated manifests lists for the install location, If there
// is no manifest for the add-on ID then newAddon will be undefined
if (aInstallLocation.name in aManifests)
@ -2618,10 +2622,11 @@ var XPIProvider = {
// Some properties should only be migrated if the add-on hasn't changed.
// The version property isn't a perfect check for this but covers the
// vast majority of cases.
if (aMigrateData.version == newAddon.version &&
"targetApplications" in aMigrateData) {
if (aMigrateData.version == newAddon.version) {
LOG("Migrating compatibility info");
newAddon.applyCompatibilityUpdate(aMigrateData, true);
sameVersion = true;
if ("targetApplications" in aMigrateData)
newAddon.applyCompatibilityUpdate(aMigrateData, true);
}
// Since the DB schema has changed make sure softDisabled is correct
@ -2697,6 +2702,11 @@ var XPIProvider = {
let oldBootstrap = oldBootstrappedAddons[newAddon.id];
XPIProvider.bootstrappedAddons[newAddon.id] = oldBootstrap;
// If the old version is the same as the new version, don't call
// uninstall and install methods.
if (sameVersion)
return false;
installReason = Services.vc.compare(oldBootstrap.version, newAddon.version) < 0 ?
BOOTSTRAP_REASONS.ADDON_UPGRADE :
BOOTSTRAP_REASONS.ADDON_DOWNGRADE;

View File

@ -100,8 +100,11 @@ function run_test_1() {
do_check_false(a4.isActive);
do_check_false(isExtensionInAddonsList(profileDir, addon4.id));
// Prepare the add-on update
installAllFiles([do_get_addon("test_bug659772")], function() {
// Prepare the add-on update, and a bootstrapped addon (bug 693714)
installAllFiles([
do_get_addon("test_bug659772"),
do_get_addon("test_bootstrap1_1")
], function() {
shutdownManager();
// Make it look like the next time the app is started it has a new DB schema
@ -142,6 +145,9 @@ function run_test_1() {
converter.close();
stream.close();
Services.prefs.clearUserPref("bootstraptest.install_reason");
Services.prefs.clearUserPref("bootstraptest.uninstall_reason");
startupManager(false);
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
@ -179,6 +185,10 @@ function run_test_1() {
do_check_false(a4.isActive);
do_check_false(isExtensionInAddonsList(profileDir, addon4.id));
// Check that install and uninstall haven't been called on the bootstrapped adddon
do_check_false(Services.prefs.prefHasUserValue("bootstraptest.install_reason"));
do_check_false(Services.prefs.prefHasUserValue("bootstraptest.uninstall_reason"));
a1.uninstall();
a2.uninstall();
a3.uninstall();
@ -235,8 +245,11 @@ function run_test_2() {
do_check_false(a4.isActive);
do_check_false(isExtensionInAddonsList(profileDir, addon4.id));
// Prepare the add-on update
installAllFiles([do_get_addon("test_bug659772")], function() {
// Prepare the add-on update, and a bootstrapped addon (bug 693714)
installAllFiles([
do_get_addon("test_bug659772"),
do_get_addon("test_bootstrap1_1")
], function() {
shutdownManager();
// Make it look like the next time the app is started it has a new DB schema
@ -277,6 +290,9 @@ function run_test_2() {
converter.close();
stream.close();
Services.prefs.clearUserPref("bootstraptest.install_reason");
Services.prefs.clearUserPref("bootstraptest.uninstall_reason");
gAppInfo.version = "2";
startupManager(true);
@ -315,6 +331,10 @@ function run_test_2() {
do_check_true(a4.isActive);
do_check_true(isExtensionInAddonsList(profileDir, addon4.id));
// Check that install and uninstall haven't been called on the bootstrapped adddon
do_check_false(Services.prefs.prefHasUserValue("bootstraptest.install_reason"));
do_check_false(Services.prefs.prefHasUserValue("bootstraptest.uninstall_reason"));
a1.uninstall();
a2.uninstall();
a3.uninstall();

View File

@ -44,6 +44,7 @@
#include <objidl.h>
#endif
#include <oleidl.h>
#include <shldisp.h>
#include "nsCOMPtr.h"
#include "nsString.h"
@ -55,6 +56,13 @@
#include "nsCOMArray.h"
#include "nsITimer.h"
// The SDK shipping with VC11 has renamed IAsyncOperation to
// IDataObjectAsyncCapability. We try to detect this, and rename this in our
// code too to make sure that we pick the correct name when building.
#ifdef __IDataObjectAsyncCapability_INTERFACE_DEFINED__
#define IAsyncOperation IDataObjectAsyncCapability
#define IID_IAsyncOperation IID_IDataObjectAsyncCapability
#else
// XXX for older version of PSDK where IAsyncOperation and related stuff is not available
// but thisdefine should be removed when parocles config is updated
#ifndef __IAsyncOperation_INTERFACE_DEFINED__
@ -78,6 +86,7 @@ IAsyncOperation : public IUnknown
#endif
#endif // __IAsyncOperation_INTERFACE_DEFINED__
#endif // __IDataObjectAsyncCapability_INTERFACE_DEFINED__
/*
* CFSTR_SHELLURL is deprecated and doesn't have a Unicode version.

View File

@ -178,7 +178,6 @@
#include "nsNativeDragTarget.h"
#include <mmsystem.h> // needed for WIN32_LEAN_AND_MEAN
#include <zmouse.h>
#include <pbt.h>
#include <richedit.h>
#if defined(ACCESSIBILITY)

View File

@ -42,6 +42,27 @@
#include "nsMemoryReporterManager.h"
#include "nsArrayEnumerator.h"
#include "nsISimpleEnumerator.h"
#include "mozilla/Telemetry.h"
using namespace mozilla;
#if defined(MOZ_MEMORY)
# if defined(XP_WIN) || defined(SOLARIS) || defined(ANDROID) || defined(XP_MACOSX)
# define HAVE_JEMALLOC_STATS 1
# include "jemalloc.h"
# elif defined(XP_LINUX)
# define HAVE_JEMALLOC_STATS 1
# include "jemalloc_types.h"
// jemalloc is directly linked into firefox-bin; libxul doesn't link
// with it. So if we tried to use jemalloc_stats directly here, it
// wouldn't be defined. Instead, we don't include the jemalloc header
// and weakly link against jemalloc_stats.
extern "C" {
extern void jemalloc_stats(jemalloc_stats_t* stats)
NS_VISIBILITY_DEFAULT __attribute__((weak));
}
# endif // XP_LINUX
#endif // MOZ_MEMORY
#if defined(XP_LINUX) || defined(XP_MACOSX)
@ -125,6 +146,20 @@ static PRInt64 GetVsize()
static PRInt64 GetResident()
{
#ifdef HAVE_JEMALLOC_STATS
// If we're using jemalloc on Mac, we need to instruct jemalloc to purge
// the pages it has madvise(MADV_FREE)'d before we read our RSS. The OS
// will take away MADV_FREE'd pages when there's memory pressure, so they
// shouldn't count against our RSS.
//
// Purging these pages shouldn't take more than 10ms or so, but we want to
// keep an eye on it since GetResident() is called on each Telemetry ping.
{
Telemetry::AutoTimer<Telemetry::MEMORY_FREE_PURGED_PAGES_MS> timer;
jemalloc_purge_freed_pages();
}
#endif
task_basic_info ti;
return (PRInt64) (GetTaskBasicInfo(&ti) ? ti.resident_size : -1);
}
@ -255,24 +290,6 @@ NS_MEMORY_REPORTER_IMPLEMENT(Resident,
** at least -- on OSX, there are sometimes other zones in use).
**/
#if defined(MOZ_MEMORY)
# if defined(XP_WIN) || defined(SOLARIS) || defined(ANDROID) || defined(XP_MACOSX)
# define HAVE_JEMALLOC_STATS 1
# include "jemalloc.h"
# elif defined(XP_LINUX)
# define HAVE_JEMALLOC_STATS 1
# include "jemalloc_types.h"
// jemalloc is directly linked into firefox-bin; libxul doesn't link
// with it. So if we tried to use jemalloc_stats directly here, it
// wouldn't be defined. Instead, we don't include the jemalloc header
// and weakly link against jemalloc_stats.
extern "C" {
extern void jemalloc_stats(jemalloc_stats_t* stats)
NS_VISIBILITY_DEFAULT __attribute__((weak));
}
# endif // XP_LINUX
#endif // MOZ_MEMORY
#if HAVE_JEMALLOC_STATS
static PRInt64 GetHeapUnallocated()