mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central to mozilla-inbound
This commit is contained in:
commit
57042802ec
@ -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:
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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___ */
|
||||
|
@ -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++)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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; }
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -215,11 +215,4 @@ JSScript::clearNesting()
|
||||
}
|
||||
}
|
||||
|
||||
inline JSScript *
|
||||
JSObject::getScript() const
|
||||
{
|
||||
JS_ASSERT(isScript());
|
||||
return static_cast<JSScript *>(getPrivate());
|
||||
}
|
||||
|
||||
#endif /* jsscriptinlines_h___ */
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
11
js/src/tests/js1_8_5/extensions/regress-691746.js
Normal file
11
js/src/tests/js1_8_5/extensions/regress-691746.js
Normal 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');
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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___ */
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
23
layout/tables/crashtests/695430-1.html
Normal file
23
layout/tables/crashtests/695430-1.html
Normal 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>
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
77
memory/jemalloc/linkedlist.h
Normal file
77
memory/jemalloc/linkedlist.h
Normal 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
|
@ -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 {
|
||||
|
@ -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
|
||||
//------------------------------------------
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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)")
|
||||
|
@ -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;
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user