--- a/dom/src/threads/nsDOMWorker.cpp
+++ b/dom/src/threads/nsDOMWorker.cpp
@@ -909,17 +909,16 @@ nsDOMWorkerScope::PostCreate(nsIXPConnec
return NS_OK;
}
NS_IMETHODIMP
nsDOMWorkerScope::Trace(nsIXPConnectWrappedNative* /* aWrapper */,
JSTracer* aTracer,
JSObject* /*aObj */)
{
- NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
nsDOMWorkerMessageHandler::Trace(aTracer);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWorkerScope::Finalize(nsIXPConnectWrappedNative* /* aWrapper */,
JSContext* /* aCx */,
JSObject* /* aObj */)
@@ -1504,18 +1503,16 @@ nsDOMWorker::PostCreate(nsIXPConnectWrap
return NS_OK;
}
NS_IMETHODIMP
nsDOMWorker::Trace(nsIXPConnectWrappedNative* /* aWrapper */,
JSTracer* aTracer,
JSObject* /*aObj */)
{
- NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-
PRBool canceled = PR_FALSE;
{
MutexAutoLock lock(mLock);
canceled = mStatus == eKilled;
}
if (!canceled) {
nsDOMWorkerMessageHandler::Trace(aTracer);
--- a/dom/src/threads/nsDOMWorkerXHR.cpp
+++ b/dom/src/threads/nsDOMWorkerXHR.cpp
@@ -425,18 +425,16 @@ NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(
#include "xpc_map_end.h"
NS_IMETHODIMP
nsDOMWorkerXHR::Trace(nsIXPConnectWrappedNative* /* aWrapper */,
JSTracer* aTracer,
JSObject* /*aObj */)
{
- NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-
if (!mCanceled) {
nsDOMWorkerMessageHandler::Trace(aTracer);
if (mUpload) {
mUpload->Trace(aTracer);
}
}
return NS_OK;
--- a/js/src/assembler/wtf/Platform.h
+++ b/js/src/assembler/wtf/Platform.h
@@ -1003,21 +1003,16 @@
#define ENABLE_REPAINT_THROTTLING 0
#endif
/* Disable the JIT on versions of GCC prior to 4.1 */
#if !defined(ENABLE_JIT) && WTF_COMPILER_GCC && !GCC_VERSION_AT_LEAST(4, 1, 0)
#define ENABLE_JIT 0
#endif
-/* JIT is not implemented for 64 bit on MSVC */
-#if !defined(ENABLE_JIT) && WTF_COMPILER_MSVC && WTF_CPU_X86_64
-#define ENABLE_JIT 0
-#endif
-
/* The JIT is enabled by default on all x86, x64-64, ARM & MIPS platforms. */
#if !defined(ENABLE_JIT) \
&& (WTF_CPU_X86 || WTF_CPU_X86_64 || WTF_CPU_ARM || WTF_CPU_MIPS) \
&& (WTF_OS_DARWIN || !WTF_COMPILER_GCC || GCC_VERSION_AT_LEAST(4, 1, 0)) \
&& !WTF_OS_WINCE
#define ENABLE_JIT 1
#endif
--- a/js/src/jit-test/jit_test.py
+++ b/js/src/jit-test/jit_test.py
@@ -322,17 +322,17 @@ def run_tests(tests, test_dir, lib_dir,
except IOError:
sys.stderr.write("Exception thrown trying to write failure file '%s'\n"%
OPTIONS.write_failures)
traceback.print_exc()
sys.stderr.write('---\n')
def show_test(test):
if OPTIONS.show_failed:
- print(' ' + subprocess.list2cmdline(get_test_cmd(test.path, test.jitflags, lib_dir)))
+ print(' ' + subprocess.list2cmdline(get_test_cmd(test.path, test.jitflags, lib_dir, shell_args)))
else:
print(' ' + ' '.join(test.jitflags + [ test.path ]))
print('FAILURES:')
for test, _, __, ___, timed_out in failures:
if not timed_out:
show_test(test)
@@ -489,30 +489,30 @@ def main(argv):
jitflags_list = parse_jitflags()
for test in test_list:
for jitflags in jitflags_list:
new_test = test.copy()
new_test.jitflags.extend(jitflags)
job_list.append(new_test)
+ shell_args = shlex.split(OPTIONS.shell_args)
+
if OPTIONS.debug:
if len(job_list) > 1:
print('Multiple tests match command line arguments, debugger can only run one')
for tc in job_list:
print(' %s'%tc.path)
sys.exit(1)
tc = job_list[0]
- cmd = [ 'gdb', '--args' ] + get_test_cmd(tc.path, tc.jitflags, lib_dir)
+ cmd = [ 'gdb', '--args' ] + get_test_cmd(tc.path, tc.jitflags, lib_dir, shell_args)
call(cmd)
sys.exit()
- shell_args = shlex.split(OPTIONS.shell_args)
-
try:
ok = run_tests(job_list, test_dir, lib_dir, shell_args)
if not ok:
sys.exit(2)
except OSError:
if not os.path.exists(JS):
print >> sys.stderr, "JS shell argument: file does not exist: '%s'"%JS
sys.exit(1)
--- a/js/src/jit-test/tests/basic/testBug614653.js
+++ b/js/src/jit-test/tests/basic/testBug614653.js
@@ -1,10 +1,10 @@
/* Bug 614653 - This test .2 seconds with the fix, 20 minutes without. */
-for (var i = 0; i < 100; ++i) {
+for (var i = 0; i < 10; ++i) {
var arr = [];
var s = "abcdefghijklmnop";
- for (var i = 0; i < 50000; ++i) {
+ for (var j = 0; j < 50000; ++j) {
s = "<" + s + ">";
arr.push(s);
}
gc();
}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testRopeMarking.js
@@ -0,0 +1,13 @@
+for (var i = 0; i < 10; ++i) {
+ var arr = [];
+ var s = "abcdefghijklmnop";
+ for (var j = 0; j < 5000; ++j) {
+ s = "<" + s + ">";
+ arr.push(s);
+ }
+ gc();
+ for (var j = 0; j < 5000; ++j) {
+ arr[j].search("a");
+ }
+ gc();
+}
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -422,16 +422,17 @@ struct JSRuntime {
js::GCMarker *gcMarkingTracer;
int64 gcJitReleaseTime;
JSGCMode gcMode;
volatile bool gcIsNeeded;
JSObject *gcWeakMapList;
/* Pre-allocated space for the GC mark stacks. Pointer type ensures alignment. */
void *gcMarkStackObjs[js::OBJECT_MARK_STACK_SIZE / sizeof(void *)];
+ void *gcMarkStackRopes[js::ROPES_MARK_STACK_SIZE / sizeof(void *)];
void *gcMarkStackXMLs[js::XML_MARK_STACK_SIZE / sizeof(void *)];
void *gcMarkStackLarges[js::LARGE_MARK_STACK_SIZE / sizeof(void *)];
/*
* Compartment that triggered GC. If more than one Compatment need GC,
* gcTriggerCompartment is reset to NULL and a global GC is performed.
*/
JSCompartment *gcTriggerCompartment;
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -1509,16 +1509,17 @@ namespace js {
* arenas to the stack as necessary while markDelayedChildren pops the arenas
* from the stack until it empties.
*/
GCMarker::GCMarker(JSContext *cx)
: color(0),
unmarkedArenaStackTop(MarkingDelay::stackBottom()),
objStack(cx->runtime->gcMarkStackObjs, sizeof(cx->runtime->gcMarkStackObjs)),
+ ropeStack(cx->runtime->gcMarkStackRopes, sizeof(cx->runtime->gcMarkStackRopes)),
xmlStack(cx->runtime->gcMarkStackXMLs, sizeof(cx->runtime->gcMarkStackXMLs)),
largeStack(cx->runtime->gcMarkStackLarges, sizeof(cx->runtime->gcMarkStackLarges))
{
JS_TRACER_INIT(this, cx, NULL);
#ifdef DEBUG
markLaterArenas = 0;
#endif
#ifdef JS_DUMP_CONSERVATIVE_GC_ROOTS
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -1180,16 +1180,17 @@ struct LargeMarkItem
{
JSObject *obj;
uintN markpos;
LargeMarkItem(JSObject *obj) : obj(obj), markpos(0) {}
};
static const size_t OBJECT_MARK_STACK_SIZE = 32768 * sizeof(JSObject *);
+static const size_t ROPES_MARK_STACK_SIZE = 1024 * sizeof(JSString *);
static const size_t XML_MARK_STACK_SIZE = 1024 * sizeof(JSXML *);
static const size_t LARGE_MARK_STACK_SIZE = 64 * sizeof(LargeMarkItem);
struct GCMarker : public JSTracer {
private:
/* The color is only applied to objects, functions and xml. */
uint32 color;
@@ -1207,16 +1208,17 @@ struct GCMarker : public JSTracer {
#ifdef JS_DUMP_CONSERVATIVE_GC_ROOTS
Vector<void *, 0, SystemAllocPolicy> conservativeRoots;
const char *conservativeDumpFileName;
void dumpConservativeRoots();
#endif
MarkStack<JSObject *> objStack;
+ MarkStack<JSRope *> ropeStack;
MarkStack<JSXML *> xmlStack;
MarkStack<LargeMarkItem> largeStack;
public:
explicit GCMarker(JSContext *cx);
~GCMarker();
uint32 getMarkColor() const {
@@ -1229,26 +1231,34 @@ struct GCMarker : public JSTracer {
color = newColor;
}
void delayMarkingChildren(const void *thing);
void markDelayedChildren();
bool isMarkStackEmpty() {
- return objStack.isEmpty() && xmlStack.isEmpty() && largeStack.isEmpty();
+ return objStack.isEmpty() &&
+ ropeStack.isEmpty() &&
+ xmlStack.isEmpty() &&
+ largeStack.isEmpty();
}
JS_FRIEND_API(void) drainMarkStack();
void pushObject(JSObject *obj) {
if (!objStack.push(obj))
delayMarkingChildren(obj);
}
+ void pushRope(JSRope *rope) {
+ if (!ropeStack.push(rope))
+ delayMarkingChildren(rope);
+ }
+
void pushXML(JSXML *xml) {
if (!xmlStack.push(xml))
delayMarkingChildren(xml);
}
};
void
MarkStackRangeConservatively(JSTracer *trc, Value *begin, Value *end);
--- a/js/src/jsgcmark.cpp
+++ b/js/src/jsgcmark.cpp
@@ -523,23 +523,57 @@ restart:
PushMarkStack(gcmarker, &shape->methodObject());
shape = shape->previous();
if (shape && shape->markIfUnmarked(gcmarker->getMarkColor()))
goto restart;
}
static inline void
+ScanRope(GCMarker *gcmarker, JSRope *rope)
+{
+ JS_ASSERT_IF(gcmarker->context->runtime->gcCurrentCompartment,
+ rope->compartment() == gcmarker->context->runtime->gcCurrentCompartment
+ || rope->compartment() == gcmarker->context->runtime->atomsCompartment);
+ JS_ASSERT(rope->isMarked());
+
+ JSString *leftChild = NULL;
+ do {
+ JSString *rightChild = rope->rightChild();
+
+ if (rightChild->isRope()) {
+ if (rightChild->markIfUnmarked())
+ gcmarker->pushRope(&rightChild->asRope());
+ } else {
+ rightChild->asLinear().mark(gcmarker);
+ }
+ leftChild = rope->leftChild();
+
+ if (leftChild->isLinear()) {
+ leftChild->asLinear().mark(gcmarker);
+ return;
+ }
+ rope = &leftChild->asRope();
+ } while (leftChild->markIfUnmarked());
+}
+
+static inline void
PushMarkStack(GCMarker *gcmarker, JSString *str)
{
JS_ASSERT_IF(gcmarker->context->runtime->gcCurrentCompartment,
str->compartment() == gcmarker->context->runtime->gcCurrentCompartment
|| str->compartment() == gcmarker->context->runtime->atomsCompartment);
- str->mark(gcmarker);
+ if (str->isLinear()) {
+ str->asLinear().mark(gcmarker);
+ } else {
+ JS_ASSERT(str->isRope());
+ if (str->markIfUnmarked())
+ ScanRope(gcmarker, &str->asRope());
+ }
}
static const uintN LARGE_OBJECT_CHUNK_SIZE = 2048;
static void
ScanObject(GCMarker *gcmarker, JSObject *obj)
{
/*
@@ -703,16 +737,19 @@ MarkChildren(JSTracer *trc, JSXML *xml)
#endif
} /* namespace gc */
void
GCMarker::drainMarkStack()
{
while (!isMarkStackEmpty()) {
+ while (!ropeStack.isEmpty())
+ ScanRope(this, ropeStack.pop());
+
while (!objStack.isEmpty())
ScanObject(this, objStack.pop());
while (!xmlStack.isEmpty())
MarkChildren(this, xmlStack.pop());
if (!largeStack.isEmpty()) {
LargeMarkItem &item = largeStack.peek();
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -108,102 +108,24 @@ JSString::isFixed() const
bool
JSString::isExternal() const
{
bool is_external = arenaHeader()->getThingKind() == FINALIZE_EXTERNAL_STRING;
JS_ASSERT_IF(is_external, isFixed());
return is_external;
}
-static JS_ALWAYS_INLINE JSString *
-Tag(JSRope *str)
-{
- JS_ASSERT(!(size_t(str) & 1));
- return (JSString *)(size_t(str) | 1);
-}
-
-static JS_ALWAYS_INLINE bool
-Tagged(JSString *str)
-{
- return (size_t(str) & 1) != 0;
-}
-
-static JS_ALWAYS_INLINE JSRope *
-Untag(JSString *str)
-{
- JS_ASSERT((size_t(str) & 1) == 1);
- return (JSRope *)(size_t(str) & ~size_t(1));
-}
-
void
JSLinearString::mark(JSTracer *)
{
JSLinearString *str = this;
while (!str->isStaticAtom() && str->markIfUnmarked() && str->isDependent())
str = str->asDependent().base();
}
-void
-JSString::mark(JSTracer *trc)
-{
- if (isLinear()) {
- asLinear().mark(trc);
- return;
- }
-
- /*
- * This function must not fail, so a simple stack-based traversal must not
- * be used (since it may oom if the stack grows large). Instead, strings
- * are temporarily mutated to embed parent pointers as they are traversed.
- * This algorithm is homomorphic to JSString::flatten.
- */
- JSRope *str = &asRope();
- JSRope *parent = NULL;
- first_visit_node: {
- if (!str->markIfUnmarked())
- goto finish_node;
- JS_ASSERT(!Tagged(str->d.u1.left) && !Tagged(str->d.s.u2.right));
- JSString *left = str->d.u1.left;
- if (left->isRope()) {
- str->d.u1.left = Tag(parent);
- parent = str;
- str = &left->asRope();
- goto first_visit_node;
- }
- left->asLinear().mark(trc);
- }
- visit_right_child: {
- JSString *right = str->d.s.u2.right;
- if (right->isRope()) {
- str->d.s.u2.right = Tag(parent);
- parent = str;
- str = &right->asRope();
- goto first_visit_node;
- }
- right->asLinear().mark(trc);
- }
- finish_node: {
- if (!parent)
- return;
- if (Tagged(parent->d.u1.left)) {
- JS_ASSERT(!Tagged(parent->d.s.u2.right));
- JSRope *nextParent = Untag(parent->d.u1.left);
- parent->d.u1.left = str;
- str = parent;
- parent = nextParent;
- goto visit_right_child;
- }
- JSRope *nextParent = Untag(parent->d.s.u2.right);
- parent->d.s.u2.right = str;
- str = parent;
- parent = nextParent;
- goto finish_node;
- }
-}
-
static JS_ALWAYS_INLINE size_t
RopeCapacityFor(size_t length)
{
static const size_t ROPE_DOUBLING_MAX = 1024 * 1024;
/*
* Grow by 12.5% if the buffer is very large. Otherwise, round up to the
* next power of 2. This is similar to what we do with arrays; see
--- a/js/src/jsstr.h
+++ b/js/src/jsstr.h
@@ -366,20 +366,16 @@ class JSString : public js::gc::Cell
bool isStaticAtom() const {
return (d.lengthAndFlags & FLAGS_MASK) == STATIC_ATOM_FLAGS;
}
/* Only called by the GC for strings with the FINALIZE_STRING kind. */
inline void finalize(JSContext *cx);
- /* Called during GC for any string. */
-
- void mark(JSTracer *trc);
-
/* Offsets for direct field from jit code. */
static size_t offsetOfLengthAndFlags() {
return offsetof(JSString, d.lengthAndFlags);
}
static size_t offsetOfChars() {
return offsetof(JSString, d.u1.chars);
@@ -408,19 +404,20 @@ class JSRope : public JSString
}
};
JS_STATIC_ASSERT(sizeof(JSRope) == sizeof(JSString));
class JSLinearString : public JSString
{
friend class JSString;
+
+ public:
void mark(JSTracer *trc);
- public:
JS_ALWAYS_INLINE
const jschar *chars() const {
JS_ASSERT(isLinear());
return d.u1.chars;
}
};
JS_STATIC_ASSERT(sizeof(JSLinearString) == sizeof(JSString));
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -1964,17 +1964,17 @@ stubs::DecGlobalName(VMFrame &f, JSAtom
JSObject *obj = f.fp()->scopeChain().getGlobal();
if (!NameIncDec<-1, false, strict>(f, obj, atom))
THROW();
}
template void JS_FASTCALL stubs::DecGlobalName<true>(VMFrame &f, JSAtom *atom);
template void JS_FASTCALL stubs::DecGlobalName<false>(VMFrame &f, JSAtom *atom);
-static bool JS_FASTCALL
+static bool JS_ALWAYS_INLINE
InlineGetProp(VMFrame &f)
{
JSContext *cx = f.cx;
FrameRegs ®s = f.regs;
Value *vp = &f.regs.sp[-1];
if (vp->isMagic(JS_LAZY_ARGUMENTS)) {
--- a/js/src/xpconnect/src/XPCWrapper.cpp
+++ b/js/src/xpconnect/src/XPCWrapper.cpp
@@ -130,17 +130,17 @@ Unwrap(JSContext *cx, JSObject *wrapper)
return nsnull;
return wrapper->unwrap();
}
return nsnull;
}
JSObject *
-UnsafeUnwrapSecurityWrapper(JSContext *cx, JSObject *obj)
+UnsafeUnwrapSecurityWrapper(JSObject *obj)
{
if (obj->isProxy()) {
return obj->unwrap();
}
return obj;
}
--- a/js/src/xpconnect/src/XPCWrapper.h
+++ b/js/src/xpconnect/src/XPCWrapper.h
@@ -91,14 +91,14 @@ IsSecurityWrapper(JSObject *wrapper)
* Since this is meant to be called from functions like
* XPCWrappedNative::GetWrappedNativeOfJSObject, it does not set an
* exception on |cx|.
*/
JSObject *
Unwrap(JSContext *cx, JSObject *wrapper);
JSObject *
-UnsafeUnwrapSecurityWrapper(JSContext *cx, JSObject *obj);
+UnsafeUnwrapSecurityWrapper(JSObject *obj);
} // namespace XPCWrapper
#endif
--- a/js/src/xpconnect/src/xpccomponents.cpp
+++ b/js/src/xpconnect/src/xpccomponents.cpp
@@ -3012,17 +3012,17 @@ SandboxImport(JSContext *cx, uintN argc,
funname = JS_ValueToString(cx, argv[1]);
if (!funname)
return JS_FALSE;
argv[1] = STRING_TO_JSVAL(funname);
} else {
// NB: funobj must only be used to get the JSFunction out.
JSObject *funobj = JSVAL_TO_OBJECT(argv[0]);
if (funobj->isProxy()) {
- funobj = XPCWrapper::UnsafeUnwrapSecurityWrapper(cx, funobj);
+ funobj = XPCWrapper::UnsafeUnwrapSecurityWrapper(funobj);
}
JSAutoEnterCompartment ac;
if (!ac.enter(cx, funobj)) {
return JS_FALSE;
}
JSFunction *fun = JS_ValueToFunction(cx, OBJECT_TO_JSVAL(funobj));
@@ -3555,17 +3555,17 @@ xpc_EvalInSandbox(JSContext *cx, JSObjec
if (fp && !system) {
ssm->IsCapabilityEnabled("UniversalXPConnect", &system);
NS_ASSERTION(system, "Bad caller!");
}
}
}
#endif
- sandbox = XPCWrapper::UnsafeUnwrapSecurityWrapper(cx, sandbox);
+ sandbox = XPCWrapper::UnsafeUnwrapSecurityWrapper(sandbox);
if (!sandbox || sandbox->getJSClass() != &SandboxClass) {
return NS_ERROR_INVALID_ARG;
}
nsIScriptObjectPrincipal *sop =
(nsIScriptObjectPrincipal*)xpc_GetJSPrivate(sandbox);
NS_ASSERTION(sop, "Invalid sandbox passed");
nsCOMPtr<nsIPrincipal> prin = sop->GetPrincipal();
--- a/js/src/xpconnect/src/xpcprivate.h
+++ b/js/src/xpconnect/src/xpcprivate.h
@@ -1437,20 +1437,16 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JS
// XPC_WN_Shared_Proto_Enumerate or something rather than checking for
// 4 classes?
#define IS_PROTO_CLASS(clazz) \
((clazz) == &XPC_WN_NoMods_WithCall_Proto_JSClass || \
(clazz) == &XPC_WN_NoMods_NoCall_Proto_JSClass || \
(clazz) == &XPC_WN_ModsAllowed_WithCall_Proto_JSClass || \
(clazz) == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass)
-// Comes from xpcwrappednativeops.cpp
-extern void
-xpc_TraceForValidWrapper(JSTracer *trc, XPCWrappedNative* wrapper);
-
/***************************************************************************/
namespace XPCWrapper {
enum WrapperType {
UNKNOWN = 0,
NONE = 0,
XPCNW_IMPLICIT = 1 << 0,
@@ -2574,16 +2570,18 @@ public:
GetUsedOnly(XPCCallContext& ccx,
nsISupports* Object,
XPCWrappedNativeScope* Scope,
XPCNativeInterface* Interface,
XPCWrappedNative** wrapper);
// If pobj2 is not null and *pobj2 is not null after the call then *pobj2
// points to an object for which IS_SLIM_WRAPPER_OBJECT is true.
+ // cx is null when invoked from the marking phase of the GC. In this case
+ // fubobj must be null as well.
static XPCWrappedNative*
GetWrappedNativeOfJSObject(JSContext* cx, JSObject* obj,
JSObject* funobj = nsnull,
JSObject** pobj2 = nsnull,
XPCWrappedNativeTearOff** pTearOff = nsnull);
static XPCWrappedNative*
GetAndMorphWrappedNativeOfJSObject(JSContext* cx, JSObject* obj)
{
--- a/js/src/xpconnect/src/xpcwrappednative.cpp
+++ b/js/src/xpconnect/src/xpcwrappednative.cpp
@@ -1746,16 +1746,22 @@ XPCWrappedNative*
XPCWrappedNative::GetWrappedNativeOfJSObject(JSContext* cx,
JSObject* obj,
JSObject* funobj,
JSObject** pobj2,
XPCWrappedNativeTearOff** pTearOff)
{
NS_PRECONDITION(obj, "bad param");
+ // fubobj must be null if called without cx.
+ NS_PRECONDITION(cx || !funobj, "bad param");
+
+ // *pTeaorOff must be null if pTearOff is given
+ NS_PRECONDITION(!pTearOff || !*pTearOff, "bad param");
+
JSObject* cur;
XPCWrappedNativeProto* proto = nsnull;
nsIClassInfo* protoClassInfo = nsnull;
// If we were passed a function object then we need to find the correct
// wrapper out of those that might be in the callee obj's proto chain.
@@ -1765,17 +1771,17 @@ XPCWrappedNative::GetWrappedNativeOfJSOb
OBJ_TO_INNER_OBJECT(cx, funObjParent);
NS_ASSERTION(funObjParent, "funobj has no parent");
js::Class* funObjParentClass = funObjParent->getClass();
if(IS_PROTO_CLASS(funObjParentClass))
{
NS_ASSERTION(funObjParent->getParent(), "funobj's parent (proto) is global");
- proto = (XPCWrappedNativeProto*) xpc_GetJSPrivate(funObjParent);
+ proto = (XPCWrappedNativeProto*) funObjParent->getPrivate();
if(proto)
protoClassInfo = proto->GetClassInfo();
}
else if(IS_WRAPPER_CLASS(funObjParentClass))
{
cur = funObjParent;
goto return_wrapper;
}
@@ -1787,28 +1793,29 @@ XPCWrappedNative::GetWrappedNativeOfJSOb
}
else
{
NS_ERROR("function object has parent of unknown class!");
return nsnull;
}
}
+ restart:
for(cur = obj; cur; cur = cur->getProto())
{
// this is on two lines to make the compiler happy given the goto.
js::Class* clazz;
clazz = cur->getClass();
if(IS_WRAPPER_CLASS(clazz))
{
return_wrapper:
JSBool isWN = IS_WN_WRAPPER_OBJECT(cur);
XPCWrappedNative* wrapper =
- isWN ? (XPCWrappedNative*) xpc_GetJSPrivate(cur) : nsnull;
+ isWN ? (XPCWrappedNative*) cur->getPrivate() : nsnull;
if(proto)
{
XPCWrappedNativeProto* wrapper_proto =
isWN ? wrapper->GetProto() : GetSlimWrapperProto(cur);
if(proto != wrapper_proto &&
(!protoClassInfo || !wrapper_proto ||
protoClassInfo != wrapper_proto->GetClassInfo()))
continue;
@@ -1817,38 +1824,41 @@ return_wrapper:
*pobj2 = isWN ? nsnull : cur;
return wrapper;
}
if(IS_TEAROFF_CLASS(clazz))
{
return_tearoff:
XPCWrappedNative* wrapper =
- (XPCWrappedNative*) xpc_GetJSPrivate(cur->getParent());
+ (XPCWrappedNative*) cur->getParent()->getPrivate();
if(proto && proto != wrapper->GetProto() &&
(proto->GetScope() != wrapper->GetScope() ||
!protoClassInfo || !wrapper->GetProto() ||
protoClassInfo != wrapper->GetProto()->GetClassInfo()))
continue;
if(pobj2)
*pobj2 = nsnull;
- XPCWrappedNativeTearOff* to =
- (XPCWrappedNativeTearOff*) xpc_GetJSPrivate(cur);
+ XPCWrappedNativeTearOff* to = (XPCWrappedNativeTearOff*) cur->getPrivate();
if(!to)
return nsnull;
if(pTearOff)
*pTearOff = to;
return wrapper;
}
// Unwrap any wrapper wrappers.
- JSObject *unsafeObj;
- if((unsafeObj = XPCWrapper::Unwrap(cx, cur)))
- return GetWrappedNativeOfJSObject(cx, unsafeObj, funobj, pobj2,
- pTearOff);
+ JSObject *unsafeObj = cx
+ ? XPCWrapper::Unwrap(cx, cur)
+ : XPCWrapper::UnsafeUnwrapSecurityWrapper(cur);
+ if(unsafeObj)
+ {
+ obj = unsafeObj;
+ goto restart;
+ }
}
if(pobj2)
*pobj2 = nsnull;
return nsnull;
}
JSBool
--- a/js/src/xpconnect/src/xpcwrappednativejsops.cpp
+++ b/js/src/xpconnect/src/xpcwrappednativejsops.cpp
@@ -708,18 +708,18 @@ TraceScopeJSObjects(JSTracer *trc, XPCWr
obj = scope->GetPrototypeJSFunction();
if(obj)
{
JS_CALL_OBJECT_TRACER(trc, obj,
"XPCWrappedNativeScope::mPrototypeJSFunction");
}
}
-void
-xpc_TraceForValidWrapper(JSTracer *trc, XPCWrappedNative* wrapper)
+static void
+TraceForValidWrapper(JSTracer *trc, XPCWrappedNative* wrapper)
{
// NOTE: It might be nice to also do the wrapper->Mark() call here too
// when we are called during the marking phase of JS GC to mark the
// wrapper's and wrapper's proto's interface sets.
//
// We currently do that in the GC callback code. The reason we don't do that
// here is because the bits used in that marking do unpleasant things to the
// member counts in the interface and interface set objects. Those counts
@@ -738,34 +738,46 @@ xpc_TraceForValidWrapper(JSTracer *trc,
// need to use the JSClass. So, some marking is required for protection.
wrapper->TraceJS(trc);
TraceScopeJSObjects(trc, wrapper->GetScope());
}
static void
-XPC_WN_Shared_Trace(JSTracer *trc, JSObject *obj)
+MarkWrappedNative(JSTracer *trc, JSObject *obj, bool helper)
{
JSObject *obj2;
+
+ // Pass null for the first JSContext* parameter to skip any security
+ // checks and to avoid potential state change there.
XPCWrappedNative* wrapper =
- XPCWrappedNative::GetWrappedNativeOfJSObject(trc->context, obj, nsnull,
- &obj2);
+ XPCWrappedNative::GetWrappedNativeOfJSObject(nsnull, obj, nsnull, &obj2);
if(wrapper)
{
if(wrapper->IsValid())
- xpc_TraceForValidWrapper(trc, wrapper);
+ {
+ if(helper)
+ wrapper->GetScriptableCallback()->Trace(wrapper, trc, obj);
+ TraceForValidWrapper(trc, wrapper);
+ }
}
else if(obj2)
{
GetSlimWrapperProto(obj2)->TraceJS(trc);
}
}
+static void
+XPC_WN_Shared_Trace(JSTracer *trc, JSObject *obj)
+{
+ MarkWrappedNative(trc, obj, false);
+}
+
static JSBool
XPC_WN_NoHelper_Resolve(JSContext *cx, JSObject *obj, jsid id)
{
MORPH_SLIM_WRAPPER(cx, obj);
XPCCallContext ccx(JS_CALLER, cx, obj, nsnull, id);
XPCWrappedNative* wrapper = ccx.GetWrapper();
THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
@@ -1093,32 +1105,17 @@ XPC_WN_Helper_Finalize(JSContext *cx, JS
return;
wrapper->GetScriptableCallback()->Finalize(wrapper, cx, obj);
wrapper->FlatJSObjectFinalized(cx);
}
static void
XPC_WN_Helper_Trace(JSTracer *trc, JSObject *obj)
{
- JSObject *obj2;
- XPCWrappedNative* wrapper =
- XPCWrappedNative::GetWrappedNativeOfJSObject(trc->context, obj, nsnull,
- &obj2);
- if(wrapper)
- {
- if(wrapper->IsValid())
- {
- wrapper->GetScriptableCallback()->Trace(wrapper, trc, obj);
- xpc_TraceForValidWrapper(trc, wrapper);
- }
- }
- else if(obj2)
- {
- GetSlimWrapperProto(obj2)->TraceJS(trc);
- }
+ MarkWrappedNative(trc, obj, true);
}
static JSBool
XPC_WN_Helper_NewResolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
JSObject **objp)
{
nsresult rv = NS_OK;
JSBool retval = JS_TRUE;
--- a/js/src/yarr/YarrJIT.cpp
+++ b/js/src/yarr/YarrJIT.cpp
@@ -77,20 +77,27 @@ class YarrGenerator : private MacroAssem
static const RegisterID length = X86Registers::ecx;
static const RegisterID output = X86Registers::edi;
static const RegisterID regT0 = X86Registers::ebx;
static const RegisterID regT1 = X86Registers::esi;
static const RegisterID returnRegister = X86Registers::eax;
#elif WTF_CPU_X86_64
+#if WTF_PLATFORM_WIN
+ static const RegisterID input = X86Registers::ecx;
+ static const RegisterID index = X86Registers::edx;
+ static const RegisterID length = X86Registers::r8;
+ static const RegisterID output = X86Registers::r9;
+#else
static const RegisterID input = X86Registers::edi;
static const RegisterID index = X86Registers::esi;
static const RegisterID length = X86Registers::edx;
static const RegisterID output = X86Registers::ecx;
+#endif
static const RegisterID regT0 = X86Registers::eax;
static const RegisterID regT1 = X86Registers::ebx;
static const RegisterID returnRegister = X86Registers::eax;
#endif
void optimizeAlternative(PatternAlternative* alternative)
--- a/mobile/build.mk
+++ b/mobile/build.mk
@@ -63,17 +63,16 @@ tier_app_dirs += \
mobile \
$(NULL)
installer:
@$(MAKE) -C mobile/installer installer
package:
- rm -rf dist/fennec*
@$(MAKE) -C mobile/installer
install::
@echo "Mobile can't be installed directly."
@exit 1
deb: package
@$(MAKE) -C mobile/installer deb