diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js
index 822666b7fc8..a74ee534588 100644
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -734,19 +734,11 @@ pref("urlclassifier.gethashtables", "goog-phish-shavar,goog-malware-shavar");
// the database.
pref("urlclassifier.confirm-age", 2700);
-#ifdef MOZ_WIDGET_GTK2
-#define RESTRICT_CACHEMAX
-#endif
-#ifdef XP_OS2
-#define RESTRICT_CACHEMAX
-#endif
-
// Maximum size of the sqlite3 cache during an update, in bytes
-#ifdef RESTRICT_CACHEMAX
-pref("urlclassifier.updatecachemax", 104857600);
-#else
-pref("urlclassifier.updatecachemax", -1);
-#endif
+pref("urlclassifier.updatecachemax", 41943040);
+
+// Maximum size of the sqlite3 cache for lookups, in bytes
+pref("urlclassifier.lookupcachemax", 1048576);
// URL for checking the reason for a malware warning.
pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
diff --git a/embedding/android/AndroidManifest.xml.in b/embedding/android/AndroidManifest.xml.in
index 510c007e34e..3b7eb366196 100644
--- a/embedding/android/AndroidManifest.xml.in
+++ b/embedding/android/AndroidManifest.xml.in
@@ -10,7 +10,7 @@
#endif
>
+ android:targetSdkVersion="11"/>
diff --git a/embedding/android/resources/layout/notification_icon_text.xml b/embedding/android/resources/layout/notification_icon_text.xml
index 2a33012460d..d420cbd354c 100644
--- a/embedding/android/resources/layout/notification_icon_text.xml
+++ b/embedding/android/resources/layout/notification_icon_text.xml
@@ -15,20 +15,20 @@
android:layout_height="25dp"
android:scaleType="fitCenter" />
+ />
+ />
diff --git a/embedding/android/resources/layout/notification_progress.xml b/embedding/android/resources/layout/notification_progress.xml
index 75cae9bd317..59633c3017a 100644
--- a/embedding/android/resources/layout/notification_progress.xml
+++ b/embedding/android/resources/layout/notification_progress.xml
@@ -16,16 +16,15 @@
android:layout_height="25dp"
android:scaleType="fitCenter" />
+ />
+ />
+ />
+ />
diff --git a/ipc/chromium/src/base/histogram.cc b/ipc/chromium/src/base/histogram.cc
index 06e264ae849..8831bcfea5e 100644
--- a/ipc/chromium/src/base/histogram.cc
+++ b/ipc/chromium/src/base/histogram.cc
@@ -130,6 +130,17 @@ void Histogram::Add(int value) {
Accumulate(value, 1, index);
}
+void Histogram::Subtract(int value) {
+ if (value > kSampleType_MAX - 1)
+ value = kSampleType_MAX - 1;
+ if (value < 0)
+ value = 0;
+ size_t index = BucketIndex(value);
+ DCHECK_GE(value, ranges(index));
+ DCHECK_LT(value, ranges(index + 1));
+ Accumulate(value, -1, index);
+}
+
void Histogram::AddBoolean(bool value) {
DCHECK(false);
}
diff --git a/ipc/chromium/src/base/histogram.h b/ipc/chromium/src/base/histogram.h
index 0b5e77e361e..0219dd510fc 100644
--- a/ipc/chromium/src/base/histogram.h
+++ b/ipc/chromium/src/base/histogram.h
@@ -381,6 +381,7 @@ class Histogram {
Flags flags);
void Add(int value);
+ void Subtract(int value);
// This method is an interface, used only by BooleanHistogram.
virtual void AddBoolean(bool value);
diff --git a/js/src/Makefile.in b/js/src/Makefile.in
index 3c022ffed53..70e585ca5fb 100644
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -155,6 +155,7 @@ CPPSRCS = \
jsxml.cpp \
prmjtime.cpp \
sharkctl.cpp \
+ CallObject.cpp \
Debugger.cpp \
GlobalObject.cpp \
Stack.cpp \
@@ -247,6 +248,7 @@ EXPORTS_NAMESPACES = vm
EXPORTS_vm = \
ArgumentsObject.h \
+ CallObject.h \
GlobalObject.h \
Stack.h \
String.h \
diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp
index 4d053627e95..d6a2f6bf4df 100644
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -72,6 +72,7 @@
#include "jsexn.h"
#include "jsstaticcheck.h"
#include "jstracer.h"
+#include "vm/CallObject.h"
#include "vm/Debugger.h"
#if JS_HAS_GENERATORS
@@ -91,7 +92,7 @@
#include "jsinferinlines.h"
#include "jsobjinlines.h"
#include "jsscriptinlines.h"
-
+#include "vm/CallObject-inl.h"
#include "vm/ArgumentsObject-inl.h"
#include "vm/Stack-inl.h"
@@ -283,7 +284,7 @@ js_GetArgsObject(JSContext *cx, StackFrame *fp)
if (argsobj->isStrictArguments())
fp->forEachCanonicalActualArg(PutArg(argsobj->data()->slots));
else
- argsobj->setPrivate(fp);
+ argsobj->setStackFrame(fp);
fp->setArgsObj(*argsobj);
return argsobj;
@@ -294,11 +295,11 @@ js_PutArgsObject(StackFrame *fp)
{
ArgumentsObject &argsobj = fp->argsObj();
if (argsobj.isNormalArguments()) {
- JS_ASSERT(argsobj.getPrivate() == fp);
+ JS_ASSERT(argsobj.maybeStackFrame() == fp);
fp->forEachCanonicalActualArg(PutArg(argsobj.data()->slots));
- argsobj.setPrivate(NULL);
+ argsobj.setStackFrame(NULL);
} else {
- JS_ASSERT(!argsobj.getPrivate());
+ JS_ASSERT(!argsobj.maybeStackFrame());
}
}
@@ -319,9 +320,9 @@ js_NewArgumentsOnTrace(JSContext *cx, uint32 argc, JSObject *callee)
* Strict mode callers must copy arguments into the created arguments
* object. The trace-JITting code is in TraceRecorder::newArguments.
*/
- JS_ASSERT(!argsobj->getPrivate());
+ JS_ASSERT(!argsobj->maybeStackFrame());
} else {
- argsobj->setPrivate(JS_ARGUMENTS_OBJECT_ON_TRACE);
+ argsobj->setOnTrace();
}
return argsobj;
@@ -335,7 +336,7 @@ js_PutArgumentsOnTrace(JSContext *cx, JSObject *obj, Value *argv)
{
NormalArgumentsObject *argsobj = obj->asNormalArguments();
- JS_ASSERT(argsobj->getPrivate() == JS_ARGUMENTS_OBJECT_ON_TRACE);
+ JS_ASSERT(argsobj->onTrace());
/*
* TraceRecorder::putActivationObjects builds a single, contiguous array of
@@ -349,7 +350,7 @@ js_PutArgumentsOnTrace(JSContext *cx, JSObject *obj, Value *argv)
*dst = *src;
}
- argsobj->setPrivate(NULL);
+ argsobj->clearOnTrace();
return true;
}
JS_DEFINE_CALLINFO_3(extern, BOOL, js_PutArgumentsOnTrace, CONTEXT, OBJECT, VALUEPTR, 0,
@@ -390,7 +391,7 @@ ArgGetter(JSContext *cx, JSObject *obj, jsid id, Value *vp)
uintN arg = uintN(JSID_TO_INT(id));
if (arg < argsobj->initialLength()) {
JS_ASSERT(!argsobj->element(arg).isMagic(JS_ARGS_HOLE));
- if (StackFrame *fp = reinterpret_cast(argsobj->getPrivate()))
+ if (StackFrame *fp = argsobj->maybeStackFrame())
*vp = fp->canonicalActualArg(arg);
else
*vp = argsobj->element(arg);
@@ -427,7 +428,7 @@ ArgSetter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
if (JSID_IS_INT(id)) {
uintN arg = uintN(JSID_TO_INT(id));
if (arg < argsobj->initialLength()) {
- if (StackFrame *fp = reinterpret_cast(argsobj->getPrivate())) {
+ if (StackFrame *fp = argsobj->maybeStackFrame()) {
JSScript *script = fp->functionScript();
if (script->usesArguments) {
if (arg < fp->numFormalArgs())
@@ -673,7 +674,7 @@ static void
args_trace(JSTracer *trc, JSObject *obj)
{
ArgumentsObject *argsobj = obj->asArguments();
- if (argsobj->getPrivate() == JS_ARGUMENTS_OBJECT_ON_TRACE) {
+ if (argsobj->onTrace()) {
JS_ASSERT(!argsobj->isStrictArguments());
return;
}
@@ -757,57 +758,6 @@ Class js::DeclEnvClass = {
ConvertStub
};
-/*
- * Construct a call object for the given bindings. If this is a call object
- * for a function invocation, callee should be the function being called.
- * Otherwise it must be a call object for eval of strict mode code, and callee
- * must be null.
- */
-static JSObject *
-NewCallObject(JSContext *cx, JSScript *script, JSObject &scopeChain, JSObject *callee)
-{
- Bindings &bindings = script->bindings;
- size_t argsVars = bindings.countArgsAndVars();
- size_t slots = JSObject::CALL_RESERVED_SLOTS + argsVars;
- gc::AllocKind kind = gc::GetGCObjectKind(slots);
-
- /*
- * Make sure that the arguments and variables in the call object all end up
- * in a contiguous range of slots. We need this to be able to embed the
- * args/vars arrays in the TypeScriptNesting for the function, after the
- * call object's frame has finished.
- */
- if (cx->typeInferenceEnabled() && gc::GetGCKindSlots(kind) < slots) {
- kind = gc::GetGCObjectKind(JSObject::CALL_RESERVED_SLOTS);
- JS_ASSERT(gc::GetGCKindSlots(kind) == JSObject::CALL_RESERVED_SLOTS);
- }
-
- JSObject *callobj = js_NewGCObject(cx, kind);
- if (!callobj)
- return NULL;
-
- /* Init immediately to avoid GC seeing a half-init'ed object. */
- callobj->initCall(cx, bindings, &scopeChain);
- callobj->makeVarObj();
-
- /* This must come after callobj->lastProp has been set. */
- if (!callobj->ensureInstanceReservedSlots(cx, argsVars))
- return NULL;
-
-#ifdef DEBUG
- for (Shape::Range r = callobj->lastProp; !r.empty(); r.popFront()) {
- const Shape &s = r.front();
- if (s.slot != SHAPE_INVALID_SLOT) {
- JS_ASSERT(s.slot + 1 == callobj->slotSpan());
- break;
- }
- }
-#endif
-
- callobj->setCallObjCallee(callee);
- return callobj;
-}
-
static inline JSObject *
NewDeclEnvObject(JSContext *cx, StackFrame *fp)
{
@@ -826,7 +776,7 @@ NewDeclEnvObject(JSContext *cx, StackFrame *fp)
namespace js {
-JSObject *
+CallObject *
CreateFunCallObject(JSContext *cx, StackFrame *fp)
{
JS_ASSERT(fp->isNonEvalFunctionFrame());
@@ -852,23 +802,23 @@ CreateFunCallObject(JSContext *cx, StackFrame *fp)
}
}
- JSObject *callobj = NewCallObject(cx, fp->script(), *scopeChain, &fp->callee());
+ CallObject *callobj = CallObject::create(cx, fp->script(), *scopeChain, &fp->callee());
if (!callobj)
return NULL;
- callobj->setPrivate(fp);
+ callobj->setStackFrame(fp);
fp->setScopeChainWithOwnCallObj(*callobj);
return callobj;
}
-JSObject *
+CallObject *
CreateEvalCallObject(JSContext *cx, StackFrame *fp)
{
- JSObject *callobj = NewCallObject(cx, fp->script(), fp->scopeChain(), NULL);
+ CallObject *callobj = CallObject::create(cx, fp->script(), fp->scopeChain(), NULL);
if (!callobj)
return NULL;
- callobj->setPrivate(fp);
+ callobj->setStackFrame(fp);
fp->setScopeChainWithOwnCallObj(*callobj);
return callobj;
}
@@ -881,52 +831,44 @@ js_CreateCallObjectOnTrace(JSContext *cx, JSFunction *fun, JSObject *callee, JSO
JS_ASSERT(!js_IsNamedLambda(fun));
JS_ASSERT(scopeChain);
JS_ASSERT(callee);
- return NewCallObject(cx, fun->script(), *scopeChain, callee);
+ return CallObject::create(cx, fun->script(), *scopeChain, callee);
}
JS_DEFINE_CALLINFO_4(extern, OBJECT, js_CreateCallObjectOnTrace, CONTEXT, FUNCTION, OBJECT, OBJECT,
0, nanojit::ACCSET_STORE_ANY)
-inline static void
-CopyValuesToCallObject(JSObject &callobj, uintN nargs, Value *argv, uintN nvars, Value *slots)
-{
- JS_ASSERT(callobj.numSlots() >= JSObject::CALL_RESERVED_SLOTS + nargs + nvars);
- callobj.copySlotRange(JSObject::CALL_RESERVED_SLOTS, argv, nargs);
- callobj.copySlotRange(JSObject::CALL_RESERVED_SLOTS + nargs, slots, nvars);
-}
-
void
js_PutCallObject(StackFrame *fp)
{
- JSObject &callobj = fp->callObj();
- JS_ASSERT(callobj.getPrivate() == fp);
+ CallObject &callobj = fp->callObj().asCall();
+ JS_ASSERT(callobj.maybeStackFrame() == fp);
JS_ASSERT_IF(fp->isEvalFrame(), fp->isStrictEvalFrame());
- JS_ASSERT(fp->isEvalFrame() == callobj.callIsForEval());
+ JS_ASSERT(fp->isEvalFrame() == callobj.isForEval());
/* Get the arguments object to snapshot fp's actual argument values. */
if (fp->hasArgsObj()) {
if (!fp->hasOverriddenArgs())
- callobj.setCallObjArguments(ObjectValue(fp->argsObj()));
+ callobj.setArguments(ObjectValue(fp->argsObj()));
js_PutArgsObject(fp);
}
JSScript *script = fp->script();
Bindings &bindings = script->bindings;
- if (callobj.callIsForEval()) {
+ if (callobj.isForEval()) {
JS_ASSERT(script->strictModeCode);
JS_ASSERT(bindings.countArgs() == 0);
/* This could be optimized as below, but keep it simple for now. */
- CopyValuesToCallObject(callobj, 0, NULL, bindings.countVars(), fp->slots());
+ callobj.copyValues(0, NULL, bindings.countVars(), fp->slots());
} else {
JSFunction *fun = fp->fun();
- JS_ASSERT(fun == callobj.getCallObjCalleeFunction());
+ JS_ASSERT(fun == callobj.getCalleeFunction());
JS_ASSERT(script == fun->script());
uintN n = bindings.countArgsAndVars();
if (n > 0) {
- JS_ASSERT(JSObject::CALL_RESERVED_SLOTS + n <= callobj.numSlots());
+ JS_ASSERT(CallObject::RESERVED_SLOTS + n <= callobj.numSlots());
uint32 nvars = bindings.countVars();
uint32 nargs = bindings.countArgs();
@@ -939,7 +881,7 @@ js_PutCallObject(StackFrame *fp)
|| script->debugMode
#endif
) {
- CopyValuesToCallObject(callobj, nargs, fp->formalArgs(), nvars, fp->slots());
+ callobj.copyValues(nargs, fp->formalArgs(), nvars, fp->slots());
} else {
/*
* For each arg & var that is closed over, copy it from the stack
@@ -948,13 +890,13 @@ js_PutCallObject(StackFrame *fp)
uint32 nclosed = script->nClosedArgs;
for (uint32 i = 0; i < nclosed; i++) {
uint32 e = script->getClosedArg(i);
- callobj.setSlot(JSObject::CALL_RESERVED_SLOTS + e, fp->formalArg(e));
+ callobj.setArg(e, fp->formalArg(e));
}
nclosed = script->nClosedVars;
for (uint32 i = 0; i < nclosed; i++) {
uint32 e = script->getClosedVar(i);
- callobj.setSlot(JSObject::CALL_RESERVED_SLOTS + nargs + e, fp->slots()[e]);
+ callobj.setVar(e, fp->slots()[e]);
}
}
@@ -964,8 +906,8 @@ js_PutCallObject(StackFrame *fp)
*/
types::TypeScriptNesting *nesting = script->nesting();
if (nesting && script->isOuterFunction) {
- nesting->argArray = callobj.callObjArgArray();
- nesting->varArray = callobj.callObjVarArray();
+ nesting->argArray = callobj.argArray();
+ nesting->varArray = callobj.varArray();
}
}
@@ -979,19 +921,19 @@ js_PutCallObject(StackFrame *fp)
}
}
- callobj.setPrivate(NULL);
+ callobj.setStackFrame(NULL);
}
JSBool JS_FASTCALL
-js_PutCallObjectOnTrace(JSObject *callobj, uint32 nargs, Value *argv,
+js_PutCallObjectOnTrace(JSObject *obj, uint32 nargs, Value *argv,
uint32 nvars, Value *slots)
{
- JS_ASSERT(callobj->isCall());
- JS_ASSERT(!callobj->getPrivate());
+ CallObject &callobj = obj->asCall();
+ JS_ASSERT(!callobj.maybeStackFrame());
uintN n = nargs + nvars;
if (n != 0)
- CopyValuesToCallObject(*callobj, nargs, argv, nvars, slots);
+ callobj.copyValues(nargs, argv, nvars, slots);
return true;
}
@@ -1004,14 +946,16 @@ namespace js {
static JSBool
GetCallArguments(JSContext *cx, JSObject *obj, jsid id, Value *vp)
{
- StackFrame *fp = obj->maybeCallObjStackFrame();
+ CallObject &callobj = obj->asCall();
+
+ StackFrame *fp = callobj.maybeStackFrame();
if (fp && !fp->hasOverriddenArgs()) {
JSObject *argsobj = js_GetArgsObject(cx, fp);
if (!argsobj)
return false;
vp->setObject(*argsobj);
} else {
- *vp = obj->getCallObjArguments();
+ *vp = callobj.getArguments();
}
return true;
}
@@ -1019,37 +963,41 @@ GetCallArguments(JSContext *cx, JSObject *obj, jsid id, Value *vp)
static JSBool
SetCallArguments(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
{
- if (StackFrame *fp = obj->maybeCallObjStackFrame())
+ CallObject &callobj = obj->asCall();
+
+ if (StackFrame *fp = callobj.maybeStackFrame())
fp->setOverriddenArgs();
- obj->setCallObjArguments(*vp);
+ callobj.setArguments(*vp);
return true;
}
JSBool
GetCallArg(JSContext *cx, JSObject *obj, jsid id, Value *vp)
{
+ CallObject &callobj = obj->asCall();
JS_ASSERT((int16) JSID_TO_INT(id) == JSID_TO_INT(id));
uintN i = (uint16) JSID_TO_INT(id);
- if (StackFrame *fp = obj->maybeCallObjStackFrame())
+ if (StackFrame *fp = callobj.maybeStackFrame())
*vp = fp->formalArg(i);
else
- *vp = obj->callObjArg(i);
+ *vp = callobj.arg(i);
return true;
}
JSBool
SetCallArg(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
{
+ CallObject &callobj = obj->asCall();
JS_ASSERT((int16) JSID_TO_INT(id) == JSID_TO_INT(id));
uintN i = (uint16) JSID_TO_INT(id);
- if (StackFrame *fp = obj->maybeCallObjStackFrame())
+ if (StackFrame *fp = callobj.maybeStackFrame())
fp->formalArg(i) = *vp;
else
- obj->setCallObjArg(i, *vp);
+ callobj.setArg(i, *vp);
- JSFunction *fun = obj->getCallObjCalleeFunction();
+ JSFunction *fun = callobj.getCalleeFunction();
JSScript *script = fun->script();
if (!script->ensureHasTypes(cx, fun))
return false;
@@ -1062,40 +1010,43 @@ SetCallArg(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
JSBool
GetCallUpvar(JSContext *cx, JSObject *obj, jsid id, Value *vp)
{
+ CallObject &callobj = obj->asCall();
JS_ASSERT((int16) JSID_TO_INT(id) == JSID_TO_INT(id));
uintN i = (uint16) JSID_TO_INT(id);
- *vp = obj->getCallObjCallee()->getFlatClosureUpvar(i);
+ *vp = callobj.getCallee()->getFlatClosureUpvar(i);
return true;
}
JSBool
SetCallUpvar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
{
+ CallObject &callobj = obj->asCall();
JS_ASSERT((int16) JSID_TO_INT(id) == JSID_TO_INT(id));
uintN i = (uint16) JSID_TO_INT(id);
- obj->getCallObjCallee()->setFlatClosureUpvar(i, *vp);
+ callobj.getCallee()->setFlatClosureUpvar(i, *vp);
return true;
}
JSBool
GetCallVar(JSContext *cx, JSObject *obj, jsid id, Value *vp)
{
+ CallObject &callobj = obj->asCall();
JS_ASSERT((int16) JSID_TO_INT(id) == JSID_TO_INT(id));
uintN i = (uint16) JSID_TO_INT(id);
- if (StackFrame *fp = obj->maybeCallObjStackFrame())
+ if (StackFrame *fp = callobj.maybeStackFrame())
*vp = fp->varSlot(i);
else
- *vp = obj->callObjVar(i);
+ *vp = callobj.var(i);
return true;
}
JSBool
SetCallVar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
{
- JS_ASSERT(obj->isCall());
+ CallObject &callobj = obj->asCall();
JS_ASSERT((int16) JSID_TO_INT(id) == JSID_TO_INT(id));
uintN i = (uint16) JSID_TO_INT(id);
@@ -1115,12 +1066,12 @@ SetCallVar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
}
#endif
- if (StackFrame *fp = obj->maybeCallObjStackFrame())
+ if (StackFrame *fp = callobj.maybeStackFrame())
fp->varSlot(i) = *vp;
else
- obj->setCallObjVar(i, *vp);
+ callobj.setVar(i, *vp);
- JSFunction *fun = obj->getCallObjCalleeFunction();
+ JSFunction *fun = callobj.getCalleeFunction();
JSScript *script = fun->script();
if (!script->ensureHasTypes(cx, fun))
return false;
@@ -1153,16 +1104,14 @@ JS_DEFINE_CALLINFO_4(extern, BOOL, js_SetCallVar, CONTEXT, OBJECT, JSID, VALUE,
#endif
static JSBool
-call_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
- JSObject **objp)
+call_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject **objp)
{
- JS_ASSERT(obj->isCall());
JS_ASSERT(!obj->getProto());
if (!JSID_IS_ATOM(id))
return true;
- JSObject *callee = obj->getCallObjCallee();
+ JSObject *callee = obj->asCall().getCallee();
#ifdef DEBUG
if (callee) {
JSScript *script = callee->getFunctionPrivate()->script();
@@ -1204,7 +1153,7 @@ call_trace(JSTracer *trc, JSObject *obj)
JS_PUBLIC_DATA(Class) js::CallClass = {
"Call",
JSCLASS_HAS_PRIVATE |
- JSCLASS_HAS_RESERVED_SLOTS(JSObject::CALL_RESERVED_SLOTS) |
+ JSCLASS_HAS_RESERVED_SLOTS(CallObject::RESERVED_SLOTS) |
JSCLASS_NEW_RESOLVE | JSCLASS_IS_ANONYMOUS,
PropertyStub, /* addProperty */
PropertyStub, /* delProperty */
diff --git a/js/src/jsfun.h b/js/src/jsfun.h
index 83e806045b4..a151de52a14 100644
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -503,10 +503,10 @@ js_PutCallObjectOnTrace(JSObject *scopeChain, uint32 nargs, js::Value *argv,
namespace js {
-JSObject *
+CallObject *
CreateFunCallObject(JSContext *cx, StackFrame *fp);
-JSObject *
+CallObject *
CreateEvalCallObject(JSContext *cx, StackFrame *fp);
extern JSBool
diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp
index 57ac9b0f38e..4ffd69921e5 100644
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -95,6 +95,7 @@
#include "jsobjinlines.h"
#include "vm/String-inl.h"
+#include "vm/CallObject-inl.h"
#ifdef MOZ_VALGRIND
# define JS_VALGRIND
diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp
index c9503c8a47a..e070c1645ad 100644
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -5055,8 +5055,8 @@ TypeScript::SetScope(JSContext *cx, JSScript *script, JSObject *scope)
* The scope object must be the initial one for the script, before any call
* object has been created in the heavyweight case.
*/
- JS_ASSERT_IF(scope && scope->isCall() && !scope->callIsForEval(),
- scope->getCallObjCalleeFunction() != fun);
+ JS_ASSERT_IF(scope && scope->isCall() && !scope->asCall().isForEval(),
+ scope->asCall().getCalleeFunction() != fun);
if (!script->compileAndGo) {
script->types->global = NULL;
@@ -5089,11 +5089,13 @@ TypeScript::SetScope(JSContext *cx, JSScript *script, JSObject *scope)
while (!scope->isCall())
scope = scope->getParent();
+ CallObject &call = scope->asCall();
+
/* The isInnerFunction test ensures there is no intervening strict eval call object. */
- JS_ASSERT(!scope->callIsForEval());
+ JS_ASSERT(!call.isForEval());
/* Don't track non-heavyweight parents, NAME ops won't reach into them. */
- JSFunction *parentFun = scope->getCallObjCalleeFunction();
+ JSFunction *parentFun = call.getCalleeFunction();
if (!parentFun || !parentFun->isHeavyweight())
return true;
JSScript *parent = parentFun->script();
@@ -5121,8 +5123,8 @@ TypeScript::SetScope(JSContext *cx, JSScript *script, JSObject *scope)
if (!SetScope(cx, parent, scope->getParent()))
return false;
parent->nesting()->activeCall = scope;
- parent->nesting()->argArray = scope->callObjArgArray();
- parent->nesting()->varArray = scope->callObjVarArray();
+ parent->nesting()->argArray = call.argArray();
+ parent->nesting()->varArray = call.varArray();
}
JS_ASSERT(!script->types->nesting);
@@ -5212,7 +5214,7 @@ CheckNestingParent(JSContext *cx, JSObject *scope, JSScript *script)
JSScript *parent = script->nesting()->parent;
JS_ASSERT(parent);
- while (!scope->isCall() || scope->getCallObjCalleeFunction()->script() != parent)
+ while (!scope->isCall() || scope->asCall().getCalleeFunction()->script() != parent)
scope = scope->getParent();
if (scope != parent->nesting()->activeCall) {
diff --git a/js/src/jsinfer.h b/js/src/jsinfer.h
index 4889a15f47e..81d95ca028b 100644
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -55,7 +55,7 @@ namespace js {
namespace analyze {
class ScriptAnalysis;
}
- struct GlobalObject;
+ class GlobalObject;
}
namespace js {
diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp
index c27597d21b4..5b84020c0ae 100644
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -3900,7 +3900,7 @@ BEGIN_CASE(JSOP_GETELEM)
if (arg < argsobj->initialLength()) {
copyFrom = &argsobj->element(arg);
if (!copyFrom->isMagic(JS_ARGS_HOLE)) {
- if (StackFrame *afp = reinterpret_cast(argsobj->getPrivate()))
+ if (StackFrame *afp = argsobj->maybeStackFrame())
copyFrom = &afp->canonicalActualArg(arg);
goto end_getelem;
}
diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp
index 0647561d34d..ce59ee432f6 100644
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -4491,7 +4491,7 @@ JSObject::growSlots(JSContext *cx, size_t newcap)
* stack (and an eval, DEFFUN, etc. happens). We thus do not need to
* worry about updating any active outer function args/vars.
*/
- JS_ASSERT_IF(isCall(), maybeCallObjStackFrame() != NULL);
+ JS_ASSERT_IF(isCall(), asCall().maybeStackFrame() != NULL);
/*
* When an object with CAPACITY_DOUBLING_MAX or fewer slots needs to
diff --git a/js/src/jsobj.h b/js/src/jsobj.h
index fed22716823..ed164dc8d1d 100644
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -66,6 +66,7 @@ namespace js {
class AutoPropDescArrayRooter;
class JSProxyHandler;
class RegExp;
+class CallObject;
struct GCMarker;
struct NativeIterator;
@@ -733,6 +734,8 @@ struct JSObject : js::gc::Cell {
private:
inline js::Value* fixedSlots() const;
+
+ protected:
inline bool hasContiguousSlots(size_t start, size_t count) const;
public:
@@ -1065,58 +1068,10 @@ struct JSObject : js::gc::Cell {
inline js::NormalArgumentsObject *asNormalArguments();
inline js::StrictArgumentsObject *asStrictArguments();
- private:
- /*
- * Reserved slot structure for Call objects:
- *
- * private - the stack frame corresponding to the Call object
- * until js_PutCallObject or its on-trace analog
- * is called, null thereafter
- * JSSLOT_CALL_CALLEE - callee function for the stack frame, or null if
- * the stack frame is for strict mode eval code
- * JSSLOT_CALL_ARGUMENTS - arguments object for non-strict mode eval stack
- * frames (not valid for strict mode eval frames)
- */
- static const uint32 JSSLOT_CALL_CALLEE = 0;
- static const uint32 JSSLOT_CALL_ARGUMENTS = 1;
+ public:
+ inline js::CallObject &asCall();
public:
- /* Number of reserved slots. */
- static const uint32 CALL_RESERVED_SLOTS = 2;
-
- /* True if this is for a strict mode eval frame or for a function call. */
- inline bool callIsForEval() const;
-
- /* The stack frame for this Call object, if the frame is still active. */
- inline js::StackFrame *maybeCallObjStackFrame() const;
-
- /*
- * The callee function if this Call object was created for a function
- * invocation, or null if it was created for a strict mode eval frame.
- */
- inline JSObject *getCallObjCallee() const;
- inline JSFunction *getCallObjCalleeFunction() const;
- inline void setCallObjCallee(JSObject *callee);
-
- inline const js::Value &getCallObjArguments() const;
- inline void setCallObjArguments(const js::Value &v);
-
- /* Returns the formal argument at the given index. */
- inline const js::Value &callObjArg(uintN i) const;
- inline void setCallObjArg(uintN i, const js::Value &v);
-
- /* Returns the variable at the given index. */
- inline const js::Value &callObjVar(uintN i) const;
- inline void setCallObjVar(uintN i, const js::Value &v);
-
- /*
- * Get the actual arrays of arguments and variables. Only call if type
- * inference is enabled, where we ensure that call object variables are in
- * contiguous slots (see NewCallObject).
- */
- inline js::Value *callObjArgArray();
- inline js::Value *callObjVarArray();
-
/*
* Date-specific getters and setters.
*/
@@ -1926,10 +1881,7 @@ IsCacheableNonGlobalScope(JSObject *obj)
{
JS_ASSERT(obj->getParent());
- js::Class *clasp = obj->getClass();
- bool cacheable = (clasp == &CallClass ||
- clasp == &BlockClass ||
- clasp == &DeclEnvClass);
+ bool cacheable = (obj->isCall() || obj->isBlock() || obj->isDeclEnv());
JS_ASSERT_IF(cacheable, !obj->getOps()->lookupProperty);
return cacheable;
diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h
index 0fe99af49e3..95dea5f366b 100644
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -540,112 +540,6 @@ JSObject::denseArrayHasInlineSlots() const
return slots == fixedSlots();
}
-inline bool
-JSObject::callIsForEval() const
-{
- JS_ASSERT(isCall());
- JS_ASSERT(getFixedSlot(JSSLOT_CALL_CALLEE).isObjectOrNull());
- JS_ASSERT_IF(getFixedSlot(JSSLOT_CALL_CALLEE).isObject(),
- getFixedSlot(JSSLOT_CALL_CALLEE).toObject().isFunction());
- return getFixedSlot(JSSLOT_CALL_CALLEE).isNull();
-}
-
-inline js::StackFrame *
-JSObject::maybeCallObjStackFrame() const
-{
- JS_ASSERT(isCall());
- return reinterpret_cast(getPrivate());
-}
-
-inline void
-JSObject::setCallObjCallee(JSObject *callee)
-{
- JS_ASSERT(isCall());
- JS_ASSERT_IF(callee, callee->isFunction());
- setFixedSlot(JSSLOT_CALL_CALLEE, js::ObjectOrNullValue(callee));
-}
-
-inline JSObject *
-JSObject::getCallObjCallee() const
-{
- JS_ASSERT(isCall());
- return getFixedSlot(JSSLOT_CALL_CALLEE).toObjectOrNull();
-}
-
-inline JSFunction *
-JSObject::getCallObjCalleeFunction() const
-{
- JS_ASSERT(isCall());
- return getFixedSlot(JSSLOT_CALL_CALLEE).toObject().getFunctionPrivate();
-}
-
-inline const js::Value &
-JSObject::getCallObjArguments() const
-{
- JS_ASSERT(isCall());
- JS_ASSERT(!callIsForEval());
- return getFixedSlot(JSSLOT_CALL_ARGUMENTS);
-}
-
-inline void
-JSObject::setCallObjArguments(const js::Value &v)
-{
- JS_ASSERT(isCall());
- JS_ASSERT(!callIsForEval());
- setFixedSlot(JSSLOT_CALL_ARGUMENTS, v);
-}
-
-inline const js::Value &
-JSObject::callObjArg(uintN i) const
-{
- JS_ASSERT(isCall());
- JS_ASSERT(i < getCallObjCalleeFunction()->nargs);
- return getSlot(JSObject::CALL_RESERVED_SLOTS + i);
-}
-
-inline void
-JSObject::setCallObjArg(uintN i, const js::Value &v)
-{
- JS_ASSERT(isCall());
- JS_ASSERT(i < getCallObjCalleeFunction()->nargs);
- setSlot(JSObject::CALL_RESERVED_SLOTS + i, v);
-}
-
-inline js::Value *
-JSObject::callObjArgArray()
-{
- js::DebugOnly fun = getCallObjCalleeFunction();
- JS_ASSERT(hasContiguousSlots(JSObject::CALL_RESERVED_SLOTS, fun->nargs));
- return getSlotAddress(JSObject::CALL_RESERVED_SLOTS);
-}
-
-inline const js::Value &
-JSObject::callObjVar(uintN i) const
-{
- JSFunction *fun = getCallObjCalleeFunction();
- JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs());
- JS_ASSERT(i < fun->script()->bindings.countVars());
- return getSlot(JSObject::CALL_RESERVED_SLOTS + fun->nargs + i);
-}
-
-inline void
-JSObject::setCallObjVar(uintN i, const js::Value &v)
-{
- JSFunction *fun = getCallObjCalleeFunction();
- JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs());
- JS_ASSERT(i < fun->script()->bindings.countVars());
- setSlot(JSObject::CALL_RESERVED_SLOTS + fun->nargs + i, v);
-}
-
-inline js::Value *
-JSObject::callObjVarArray()
-{
- JSFunction *fun = getCallObjCalleeFunction();
- JS_ASSERT(hasContiguousSlots(JSObject::CALL_RESERVED_SLOTS + fun->nargs,
- fun->script()->bindings.countVars()));
- return getSlotAddress(JSObject::CALL_RESERVED_SLOTS + fun->nargs);
-}
-
namespace js {
/*
diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp
index d8205eceef9..6741c4bc220 100644
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -120,7 +120,7 @@ Bindings::add(JSContext *cx, JSAtom *name, BindingKind kind)
uint16 *indexp;
PropertyOp getter;
StrictPropertyOp setter;
- uint32 slot = JSObject::CALL_RESERVED_SLOTS;
+ uint32 slot = CallObject::RESERVED_SLOTS;
if (kind == ARGUMENT) {
JS_ASSERT(nvars == 0);
diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp
index d4c51c4f8a0..9303a7e65b4 100644
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -93,6 +93,7 @@
#include "jsopcodeinlines.h"
#include "jstypedarrayinlines.h"
+#include "vm/CallObject-inl.h"
#include "vm/Stack-inl.h"
#ifdef JS_METHODJIT
@@ -3286,9 +3287,9 @@ public:
JS_ASSERT_IF(fp->hasArgsObj(), frameobj == &fp->argsObj());
fp->setArgsObj(*frameobj->asArguments());
if (frameobj->isNormalArguments())
- frameobj->setPrivate(fp);
+ frameobj->asArguments()->setStackFrame(fp);
else
- JS_ASSERT(!frameobj->getPrivate());
+ JS_ASSERT(!frameobj->asArguments()->maybeStackFrame());
debug_only_printf(LC_TMTracer,
"argsobj<%p> ",
(void *)frameobj);
@@ -3301,12 +3302,12 @@ public:
} else {
JS_ASSERT(p == fp->addressOfScopeChain());
if (frameobj->isCall() &&
- !frameobj->getPrivate() &&
- fp->maybeCalleev().toObjectOrNull() == frameobj->getCallObjCallee())
+ !frameobj->asCall().maybeStackFrame() &&
+ fp->maybeCalleev().toObjectOrNull() == frameobj->asCall().getCallee())
{
JS_ASSERT(&fp->scopeChain() == StackFrame::sInvalidScopeChain);
- frameobj->setPrivate(fp);
- fp->setScopeChainWithOwnCallObj(*frameobj);
+ frameobj->asCall().setStackFrame(fp);
+ fp->setScopeChainWithOwnCallObj(frameobj->asCall());
} else {
fp->setScopeChainNoCallObj(*frameobj);
}
@@ -3539,7 +3540,7 @@ GetFromClosure(JSContext* cx, JSObject* call, const ClosureVarInfo* cv, double*
// We already guarded on trace that we aren't touching an outer tree's entry frame
VOUCH_DOES_NOT_REQUIRE_STACK();
- StackFrame* fp = (StackFrame*) call->getPrivate();
+ StackFrame* fp = call->asCall().maybeStackFrame();
JS_ASSERT(fp != cx->fp());
Value v;
@@ -3577,12 +3578,12 @@ struct ArgClosureTraits
// Get the offset of our object slots from the object's slots pointer.
static inline uint32 slot_offset(JSObject* obj) {
- return JSObject::CALL_RESERVED_SLOTS;
+ return CallObject::RESERVED_SLOTS;
}
// Get the maximum slot index of this type that should be allowed
static inline uint16 slot_count(JSObject* obj) {
- return obj->getCallObjCalleeFunction()->nargs;
+ return obj->asCall().getCalleeFunction()->nargs;
}
private:
@@ -3608,12 +3609,12 @@ struct VarClosureTraits
}
static inline uint32 slot_offset(JSObject* obj) {
- return JSObject::CALL_RESERVED_SLOTS +
- obj->getCallObjCalleeFunction()->nargs;
+ return CallObject::RESERVED_SLOTS +
+ obj->asCall().getCalleeFunction()->nargs;
}
static inline uint16 slot_count(JSObject* obj) {
- return obj->getCallObjCalleeFunction()->script()->bindings.countVars();
+ return obj->asCall().getCalleeFunction()->script()->bindings.countVars();
}
private:
@@ -8149,9 +8150,10 @@ TraceRecorder::entryFrameIns() const
* filled in with the depth of the call object's frame relevant to cx->fp().
*/
JS_REQUIRES_STACK StackFrame*
-TraceRecorder::frameIfInRange(JSObject* obj, unsigned* depthp) const
+TraceRecorder::frameIfInRange(JSObject *obj, unsigned* depthp) const
{
- StackFrame* ofp = (StackFrame*) obj->getPrivate();
+ JS_ASSERT(obj->isCall() || obj->isArguments());
+ StackFrame* ofp = (StackFrame *) obj->getPrivate();
StackFrame* fp = cx->fp();
for (unsigned depth = 0; depth <= callDepth; ++depth) {
if (fp == ofp) {
@@ -8264,7 +8266,8 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, const Value*&
uintN slot = uint16(shape->shortid);
vp = NULL;
- StackFrame* cfp = (StackFrame*) obj->getPrivate();
+ CallObject &callobj = obj->asCall();
+ StackFrame* cfp = callobj.maybeStackFrame();
if (cfp) {
if (shape->getterOp() == GetCallArg) {
JS_ASSERT(slot < cfp->numFormalArgs());
@@ -8281,7 +8284,7 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, const Value*&
// Now assert that our use of shape->shortid was in fact kosher.
JS_ASSERT(shape->hasShortID());
- if (frameIfInRange(obj)) {
+ if (frameIfInRange(&callobj)) {
// At this point we are guaranteed to be looking at an active call oject
// whose properties are stored in the corresponding StackFrame.
ins = get(vp);
@@ -12299,11 +12302,13 @@ TraceRecorder::setUpwardTrackedVar(Value* stackVp, const Value &v, LIns* v_ins)
}
JS_REQUIRES_STACK RecordingStatus
-TraceRecorder::setCallProp(JSObject *callobj, LIns *callobj_ins, const Shape *shape,
+TraceRecorder::setCallProp(JSObject *obj, LIns *callobj_ins, const Shape *shape,
LIns *v_ins, const Value &v)
{
+ CallObject &callobj = obj->asCall();
+
// Set variables in on-trace-stack call objects by updating the tracker.
- StackFrame *fp = frameIfInRange(callobj);
+ StackFrame *fp = frameIfInRange(&callobj);
if (fp) {
if (shape->setterOp() == SetCallArg) {
JS_ASSERT(shape->hasShortID());
@@ -12322,7 +12327,7 @@ TraceRecorder::setCallProp(JSObject *callobj, LIns *callobj_ins, const Shape *sh
RETURN_STOP("can't trace special CallClass setter");
}
- if (!callobj->getPrivate()) {
+ if (!callobj.maybeStackFrame()) {
// Because the parent guard in guardCallee ensures this Call object
// will be the same object now and on trace, and because once a Call
// object loses its frame it never regains one, on trace we will also
@@ -12330,11 +12335,11 @@ TraceRecorder::setCallProp(JSObject *callobj, LIns *callobj_ins, const Shape *sh
// write the value to the Call object's slot.
intN slot = uint16(shape->shortid);
if (shape->setterOp() == SetCallArg) {
- JS_ASSERT(slot < ArgClosureTraits::slot_count(callobj));
- slot += ArgClosureTraits::slot_offset(callobj);
+ JS_ASSERT(slot < ArgClosureTraits::slot_count(&callobj));
+ slot += ArgClosureTraits::slot_offset(obj);
} else if (shape->setterOp() == SetCallVar) {
- JS_ASSERT(slot < VarClosureTraits::slot_count(callobj));
- slot += VarClosureTraits::slot_offset(callobj);
+ JS_ASSERT(slot < VarClosureTraits::slot_count(&callobj));
+ slot += VarClosureTraits::slot_offset(obj);
} else {
RETURN_STOP("can't trace special CallClass setter");
}
@@ -12345,7 +12350,7 @@ TraceRecorder::setCallProp(JSObject *callobj, LIns *callobj_ins, const Shape *sh
JS_ASSERT(shape->hasShortID());
LIns* slots_ins = NULL;
- stobj_set_slot(callobj, callobj_ins, slot, slots_ins, v, v_ins);
+ stobj_set_slot(&callobj, callobj_ins, slot, slots_ins, v, v_ins);
return RECORD_CONTINUE;
}
@@ -14997,7 +15002,7 @@ static inline bool
IsFindableCallObj(JSObject *obj)
{
return obj->isCall() &&
- (obj->callIsForEval() || obj->getCallObjCalleeFunction()->isHeavyweight());
+ (obj->asCall().isForEval() || obj->asCall().getCalleeFunction()->isHeavyweight());
}
/*
@@ -15134,8 +15139,7 @@ TraceRecorder::record_JSOP_BINDNAME()
* it. For now just don't trace this case.
*/
if (obj != globalObj) {
- JS_ASSERT(obj->isCall());
- JS_ASSERT(obj->callIsForEval());
+ JS_ASSERT(obj->asCall().isForEval());
RETURN_STOP_A("BINDNAME within strict eval code");
}
diff --git a/js/src/jstracer.h b/js/src/jstracer.h
index 952ee653313..c7dd7706d37 100644
--- a/js/src/jstracer.h
+++ b/js/src/jstracer.h
@@ -1272,7 +1272,7 @@ class TraceRecorder
JS_REQUIRES_STACK nanojit::LIns* scopeChain();
JS_REQUIRES_STACK nanojit::LIns* entryScopeChain() const;
JS_REQUIRES_STACK nanojit::LIns* entryFrameIns() const;
- JS_REQUIRES_STACK StackFrame* frameIfInRange(JSObject* obj, unsigned* depthp = NULL) const;
+ JS_REQUIRES_STACK StackFrame* frameIfInRange(JSObject *obj, unsigned* depthp = NULL) const;
JS_REQUIRES_STACK RecordingStatus traverseScopeChain(JSObject *obj, nanojit::LIns *obj_ins, JSObject *obj2, nanojit::LIns *&obj2_ins);
JS_REQUIRES_STACK AbortableRecordingStatus scopeChainProp(JSObject* obj, const Value*& vp, nanojit::LIns*& ins, NameResult& nr, JSObject **scopeObjp = NULL);
JS_REQUIRES_STACK RecordingStatus callProp(JSObject* obj, JSProperty* shape, jsid id, const Value*& vp, nanojit::LIns*& ins, NameResult& nr);
diff --git a/js/src/methodjit/PolyIC.cpp b/js/src/methodjit/PolyIC.cpp
index cc4524bd08c..992205fd1c5 100644
--- a/js/src/methodjit/PolyIC.cpp
+++ b/js/src/methodjit/PolyIC.cpp
@@ -54,6 +54,8 @@
#include "jsinterpinlines.h"
#include "jsautooplen.h"
+#include "vm/CallObject-inl.h"
+
#if defined JS_POLYIC
using namespace js;
@@ -421,7 +423,7 @@ class SetPropCompiler : public PICStubCompiler
// \\ V and getters, and
// \===/ 2. arguments and locals have different getters
// then we can rely on fun->nargs remaining invariant.
- JSFunction *fun = obj->getCallObjCalleeFunction();
+ JSFunction *fun = obj->asCall().getCalleeFunction();
uint16 slot = uint16(shape->shortid);
/* Guard that the call object has a frame. */
@@ -441,7 +443,7 @@ class SetPropCompiler : public PICStubCompiler
if (shape->setterOp() == SetCallVar)
slot += fun->nargs;
- slot += JSObject::CALL_RESERVED_SLOTS;
+ slot += CallObject::RESERVED_SLOTS;
Address address = masm.objPropAddress(obj, pic.objReg, slot);
masm.storeValue(pic.u.vr, address);
@@ -691,7 +693,7 @@ class SetPropCompiler : public PICStubCompiler
* objects may differ due to eval(), DEFFUN, etc.).
*/
RecompilationMonitor monitor(cx);
- JSFunction *fun = obj->getCallObjCalleeFunction();
+ JSFunction *fun = obj->asCall().getCalleeFunction();
JSScript *script = fun->script();
uint16 slot = uint16(shape->shortid);
if (!script->ensureHasTypes(cx, fun))
@@ -1504,7 +1506,7 @@ class ScopeNameCompiler : public PICStubCompiler
/* Get callobj's stack frame. */
masm.loadObjPrivate(pic.objReg, pic.shapeReg);
- JSFunction *fun = getprop.holder->getCallObjCalleeFunction();
+ JSFunction *fun = getprop.holder->asCall().getCalleeFunction();
uint16 slot = uint16(shape->shortid);
Jump skipOver;
@@ -1525,7 +1527,7 @@ class ScopeNameCompiler : public PICStubCompiler
if (kind == VAR)
slot += fun->nargs;
- slot += JSObject::CALL_RESERVED_SLOTS;
+ slot += CallObject::RESERVED_SLOTS;
Address address = masm.objPropAddress(obj, pic.objReg, slot);
/* Safe because type is loaded first. */
diff --git a/js/src/methodjit/StubCalls.cpp b/js/src/methodjit/StubCalls.cpp
index fc304b7abb5..78989586e90 100644
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -482,7 +482,7 @@ stubs::GetElem(VMFrame &f)
if (arg < argsobj->initialLength()) {
copyFrom = &argsobj->element(arg);
if (!copyFrom->isMagic()) {
- if (StackFrame *afp = (StackFrame *) argsobj->getPrivate())
+ if (StackFrame *afp = argsobj->maybeStackFrame())
copyFrom = &afp->canonicalActualArg(arg);
goto end_getelem;
}
diff --git a/js/src/vm/ArgumentsObject-inl.h b/js/src/vm/ArgumentsObject-inl.h
index 3e55cc13679..9103151c6fa 100644
--- a/js/src/vm/ArgumentsObject-inl.h
+++ b/js/src/vm/ArgumentsObject-inl.h
@@ -110,6 +110,37 @@ ArgumentsObject::setElement(uint32 i, const js::Value &v)
data()->slots[i] = v;
}
+inline js::StackFrame *
+ArgumentsObject::maybeStackFrame() const
+{
+ return reinterpret_cast(getPrivate());
+}
+
+inline void
+ArgumentsObject::setStackFrame(StackFrame *frame)
+{
+ return setPrivate(frame);
+}
+
+#define JS_ARGUMENTS_OBJECT_ON_TRACE ((void *)0xa126)
+inline bool
+ArgumentsObject::onTrace() const
+{
+ return getPrivate() == JS_ARGUMENTS_OBJECT_ON_TRACE;
+}
+
+inline void
+ArgumentsObject::setOnTrace()
+{
+ return setPrivate(JS_ARGUMENTS_OBJECT_ON_TRACE);
+}
+
+inline void
+ArgumentsObject::clearOnTrace()
+{
+ return setPrivate(NULL);
+}
+
inline const js::Value &
NormalArgumentsObject::callee() const
{
diff --git a/js/src/vm/ArgumentsObject.h b/js/src/vm/ArgumentsObject.h
index 7e401db8f66..7b64716f1cb 100644
--- a/js/src/vm/ArgumentsObject.h
+++ b/js/src/vm/ArgumentsObject.h
@@ -47,8 +47,6 @@
class GetPropCompiler;
#endif
-#define JS_ARGUMENTS_OBJECT_ON_TRACE ((void *)0xa126)
-
#ifdef JS_TRACER
namespace nanojit {
class ValidateWriter;
@@ -229,6 +227,14 @@ class ArgumentsObject : public ::JSObject
inline const js::Value &element(uint32 i) const;
inline const js::Value *elements() const;
inline void setElement(uint32 i, const js::Value &v);
+
+ /* The stack frame for this ArgumentsObject, if the frame is still active. */
+ inline js::StackFrame *maybeStackFrame() const;
+ inline void setStackFrame(js::StackFrame *frame);
+
+ inline bool onTrace() const;
+ inline void setOnTrace();
+ inline void clearOnTrace();
};
/*
diff --git a/js/src/vm/CallObject-inl.h b/js/src/vm/CallObject-inl.h
new file mode 100644
index 00000000000..b869853fb5a
--- /dev/null
+++ b/js/src/vm/CallObject-inl.h
@@ -0,0 +1,161 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** 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 SpiderMonkey call object code.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Paul Biggar (original author)
+ *
+ * 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 ***** */
+
+#ifndef CallObject_inl_h___
+#define CallObject_inl_h___
+
+#include "CallObject.h"
+
+namespace js {
+
+inline bool
+CallObject::isForEval() const
+{
+ JS_ASSERT(getFixedSlot(CALLEE_SLOT).isObjectOrNull());
+ JS_ASSERT_IF(getFixedSlot(CALLEE_SLOT).isObject(),
+ getFixedSlot(CALLEE_SLOT).toObject().isFunction());
+ return getFixedSlot(CALLEE_SLOT).isNull();
+}
+
+inline js::StackFrame *
+CallObject::maybeStackFrame() const
+{
+ return reinterpret_cast(getPrivate());
+}
+
+inline void
+CallObject::setStackFrame(StackFrame *frame)
+{
+ return setPrivate(frame);
+}
+
+inline void
+CallObject::setCallee(JSObject *callee)
+{
+ JS_ASSERT_IF(callee, callee->isFunction());
+ setFixedSlot(CALLEE_SLOT, js::ObjectOrNullValue(callee));
+}
+
+inline JSObject *
+CallObject::getCallee() const
+{
+ return getFixedSlot(CALLEE_SLOT).toObjectOrNull();
+}
+
+inline JSFunction *
+CallObject::getCalleeFunction() const
+{
+ return getFixedSlot(CALLEE_SLOT).toObject().getFunctionPrivate();
+}
+
+inline const js::Value &
+CallObject::getArguments() const
+{
+ JS_ASSERT(!isForEval());
+ return getFixedSlot(ARGUMENTS_SLOT);
+}
+
+inline void
+CallObject::setArguments(const js::Value &v)
+{
+ JS_ASSERT(!isForEval());
+ setFixedSlot(ARGUMENTS_SLOT, v);
+}
+
+inline const js::Value &
+CallObject::arg(uintN i) const
+{
+ JS_ASSERT(i < getCalleeFunction()->nargs);
+ return getSlot(RESERVED_SLOTS + i);
+}
+
+inline void
+CallObject::setArg(uintN i, const js::Value &v)
+{
+ JS_ASSERT(i < getCalleeFunction()->nargs);
+ setSlot(RESERVED_SLOTS + i, v);
+}
+
+inline const js::Value &
+CallObject::var(uintN i) const
+{
+ JSFunction *fun = getCalleeFunction();
+ JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs());
+ JS_ASSERT(i < fun->script()->bindings.countVars());
+ return getSlot(RESERVED_SLOTS + fun->nargs + i);
+}
+
+inline void
+CallObject::setVar(uintN i, const js::Value &v)
+{
+ JSFunction *fun = getCalleeFunction();
+ JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs());
+ JS_ASSERT(i < fun->script()->bindings.countVars());
+ setSlot(RESERVED_SLOTS + fun->nargs + i, v);
+}
+
+inline void
+CallObject::copyValues(uintN nargs, Value *argv, uintN nvars, Value *slots)
+{
+ JS_ASSERT(numSlots() >= RESERVED_SLOTS + nargs + nvars);
+ copySlotRange(RESERVED_SLOTS, argv, nargs);
+ copySlotRange(RESERVED_SLOTS + nargs, slots, nvars);
+}
+
+inline js::Value *
+CallObject::argArray()
+{
+ js::DebugOnly fun = getCalleeFunction();
+ JS_ASSERT(hasContiguousSlots(RESERVED_SLOTS, fun->nargs));
+ return getSlotAddress(RESERVED_SLOTS);
+}
+
+inline js::Value *
+CallObject::varArray()
+{
+ JSFunction *fun = getCalleeFunction();
+ JS_ASSERT(hasContiguousSlots(RESERVED_SLOTS + fun->nargs,
+ fun->script()->bindings.countVars()));
+ return getSlotAddress(RESERVED_SLOTS + fun->nargs);
+}
+
+}
+
+#endif /* CallObject_inl_h___ */
diff --git a/js/src/vm/CallObject.cpp b/js/src/vm/CallObject.cpp
new file mode 100644
index 00000000000..63174325a08
--- /dev/null
+++ b/js/src/vm/CallObject.cpp
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** 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 SpiderMonkey call object code.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Paul Biggar (original author)
+ *
+ * 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 ***** */
+
+#include "jsobjinlines.h"
+#include "CallObject.h"
+
+#include "CallObject-inl.h"
+
+namespace js {
+
+/*
+ * Construct a call object for the given bindings. If this is a call object
+ * for a function invocation, callee should be the function being called.
+ * Otherwise it must be a call object for eval of strict mode code, and callee
+ * must be null.
+ */
+CallObject *
+CallObject::create(JSContext *cx, JSScript *script, JSObject &scopeChain, JSObject *callee)
+{
+ Bindings &bindings = script->bindings;
+ size_t argsVars = bindings.countArgsAndVars();
+ size_t slots = RESERVED_SLOTS + argsVars;
+ gc::AllocKind kind = gc::GetGCObjectKind(slots);
+
+ /*
+ * Make sure that the arguments and variables in the call object all end up
+ * in a contiguous range of slots. We need this to be able to embed the
+ * args/vars arrays in the TypeScriptNesting for the function, after the
+ * call object's frame has finished.
+ */
+ if (cx->typeInferenceEnabled() && gc::GetGCKindSlots(kind) < slots) {
+ kind = gc::GetGCObjectKind(RESERVED_SLOTS);
+ JS_ASSERT(gc::GetGCKindSlots(kind) == RESERVED_SLOTS);
+ }
+
+ JSObject *obj = js_NewGCObject(cx, kind);
+ if (!obj)
+ return NULL;
+
+ /* Init immediately to avoid GC seeing a half-init'ed object. */
+ obj->initCall(cx, bindings, &scopeChain);
+ obj->makeVarObj();
+
+ /* This must come after callobj->lastProp has been set. */
+ if (!obj->ensureInstanceReservedSlots(cx, argsVars))
+ return NULL;
+
+#ifdef DEBUG
+ for (Shape::Range r = obj->lastProp; !r.empty(); r.popFront()) {
+ const Shape &s = r.front();
+ if (s.slot != SHAPE_INVALID_SLOT) {
+ JS_ASSERT(s.slot + 1 == obj->slotSpan());
+ break;
+ }
+ }
+#endif
+
+ CallObject &callobj = obj->asCall();
+ callobj.setCallee(callee);
+ return &callobj;
+}
+
+}
diff --git a/js/src/vm/CallObject.h b/js/src/vm/CallObject.h
new file mode 100644
index 00000000000..d4c4e89fdc7
--- /dev/null
+++ b/js/src/vm/CallObject.h
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** 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 SpiderMonkey call object code.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Paul Biggar (original author)
+ *
+ * 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 ***** */
+
+#ifndef CallObject_h___
+#define CallObject_h___
+
+namespace js {
+
+class CallObject : public ::JSObject
+{
+ /*
+ * Reserved slot structure for Call objects:
+ *
+ * private - the stack frame corresponding to the Call object
+ * until js_PutCallObject or its on-trace analog
+ * is called, null thereafter
+ * JSSLOT_CALL_CALLEE - callee function for the stack frame, or null if
+ * the stack frame is for strict mode eval code
+ * JSSLOT_CALL_ARGUMENTS - arguments object for non-strict mode eval stack
+ * frames (not valid for strict mode eval frames)
+ */
+ static const uint32 CALLEE_SLOT = 0;
+ static const uint32 ARGUMENTS_SLOT = 1;
+
+public:
+ /* Create a CallObject for the given callee function. */
+ static CallObject *
+ create(JSContext *cx, JSScript *script, JSObject &scopeChain, JSObject *callee);
+
+ static const uint32 RESERVED_SLOTS = 2;
+
+ /* True if this is for a strict mode eval frame or for a function call. */
+ inline bool isForEval() const;
+
+ /* The stack frame for this CallObject, if the frame is still active. */
+ inline js::StackFrame *maybeStackFrame() const;
+ inline void setStackFrame(js::StackFrame *frame);
+
+ /*
+ * The callee function if this CallObject was created for a function
+ * invocation, or null if it was created for a strict mode eval frame.
+ */
+ inline JSObject *getCallee() const;
+ inline JSFunction *getCalleeFunction() const;
+ inline void setCallee(JSObject *callee);
+
+ /* Returns the callee's arguments object. */
+ inline const js::Value &getArguments() const;
+ inline void setArguments(const js::Value &v);
+
+ /* Returns the formal argument at the given index. */
+ inline const js::Value &arg(uintN i) const;
+ inline void setArg(uintN i, const js::Value &v);
+
+ /* Returns the variable at the given index. */
+ inline const js::Value &var(uintN i) const;
+ inline void setVar(uintN i, const js::Value &v);
+
+ /*
+ * Get the actual arrays of arguments and variables. Only call if type
+ * inference is enabled, where we ensure that call object variables are in
+ * contiguous slots (see NewCallObject).
+ */
+ inline js::Value *argArray();
+ inline js::Value *varArray();
+
+ inline void copyValues(uintN nargs, Value *argv, uintN nvars, Value *slots);
+};
+
+}
+
+js::CallObject &
+JSObject::asCall()
+{
+ JS_ASSERT(isCall());
+ return *reinterpret_cast(this);
+}
+
+#endif /* CallObject_h___ */
diff --git a/js/src/vm/Stack-inl.h b/js/src/vm/Stack-inl.h
index 15619de28d8..104425fdb4e 100644
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -48,6 +48,8 @@
#include "jsscriptinlines.h"
#include "ArgumentsObject-inl.h"
+#include "CallObject-inl.h"
+
#include "methodjit/MethodJIT.h"
namespace js {
@@ -340,15 +342,15 @@ StackFrame::setScopeChainNoCallObj(JSObject &obj)
}
inline void
-StackFrame::setScopeChainWithOwnCallObj(JSObject &obj)
+StackFrame::setScopeChainWithOwnCallObj(CallObject &obj)
{
JS_ASSERT(&obj != NULL);
- JS_ASSERT(!hasCallObj() && obj.isCall() && obj.getPrivate() == this);
+ JS_ASSERT(!hasCallObj() && obj.maybeStackFrame() == this);
scopeChain_ = &obj;
flags_ |= HAS_SCOPECHAIN | HAS_CALL_OBJ;
}
-inline JSObject &
+inline CallObject &
StackFrame::callObj() const
{
JS_ASSERT_IF(isNonEvalFunctionFrame() || isStrictEvalFrame(), hasCallObj());
@@ -358,7 +360,7 @@ StackFrame::callObj() const
JS_ASSERT(IsCacheableNonGlobalScope(pobj) || pobj->isWith());
pobj = pobj->getParent();
}
- return *pobj;
+ return pobj->asCall();
}
inline bool
@@ -415,11 +417,11 @@ inline void
StackFrame::markFunctionEpilogueDone(bool activationOnly)
{
if (flags_ & (HAS_ARGS_OBJ | HAS_CALL_OBJ)) {
- if (hasArgsObj() && !argsObj().getPrivate()) {
+ if (hasArgsObj() && !argsObj().maybeStackFrame()) {
args.nactual = args.obj->initialLength();
flags_ &= ~HAS_ARGS_OBJ;
}
- if (hasCallObj() && !callObj().getPrivate()) {
+ if (hasCallObj() && !callObj().maybeStackFrame()) {
/*
* For function frames, the call object may or may not have have an
* enclosing DeclEnv object, so we use the callee's parent, since
@@ -687,8 +689,7 @@ ArgumentsObject::getElement(uint32 i, Value *vp)
* If this arguments object was created on trace the actual argument value
* could be in a register or something, so we can't optimize.
*/
- StackFrame *fp = reinterpret_cast(getPrivate());
- if (fp == JS_ARGUMENTS_OBJECT_ON_TRACE)
+ if (onTrace())
return false;
/*
@@ -696,6 +697,7 @@ ArgumentsObject::getElement(uint32 i, Value *vp)
* the canonical argument value. Note that strict arguments objects do not
* alias named arguments and never have a stack frame.
*/
+ StackFrame *fp = maybeStackFrame();
JS_ASSERT_IF(isStrictArguments(), !fp);
if (fp)
*vp = fp->canonicalActualArg(i);
@@ -711,7 +713,7 @@ ArgumentsObject::getElements(uint32 start, uint32 count, Value *vp)
if (start > length || start + count > length)
return false;
- StackFrame *fp = reinterpret_cast(getPrivate());
+ StackFrame *fp = maybeStackFrame();
/* If there's no stack frame for this, argument values are in elements(). */
if (!fp) {
@@ -727,7 +729,7 @@ ArgumentsObject::getElements(uint32 start, uint32 count, Value *vp)
}
/* If we're on trace, there's no canonical location for elements: fail. */
- if (fp == JS_ARGUMENTS_OBJECT_ON_TRACE)
+ if (onTrace())
return false;
/* Otherwise, element values are on the stack. */
diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp
index 32c0d8e542d..44d592fad65 100644
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -159,9 +159,9 @@ StackFrame::stealFrameAndSlots(Value *vp, StackFrame *otherfp,
if (hasArgsObj()) {
ArgumentsObject &argsobj = argsObj();
if (argsobj.isNormalArguments())
- argsobj.setPrivate(this);
+ argsobj.setStackFrame(this);
else
- JS_ASSERT(!argsobj.getPrivate());
+ JS_ASSERT(!argsobj.maybeStackFrame());
otherfp->flags_ &= ~HAS_ARGS_OBJ;
}
}
diff --git a/js/src/vm/Stack.h b/js/src/vm/Stack.h
index 0412df61e6c..57bf06913d7 100644
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -851,9 +851,9 @@ class StackFrame
return ret;
}
- inline JSObject &callObj() const;
+ inline CallObject &callObj() const;
inline void setScopeChainNoCallObj(JSObject &obj);
- inline void setScopeChainWithOwnCallObj(JSObject &obj);
+ inline void setScopeChainWithOwnCallObj(CallObject &obj);
/*
* Prologue for function frames: make a call object for heavyweight
diff --git a/mobile/chrome/content/AnimatedZoom.js b/mobile/chrome/content/AnimatedZoom.js
index 9ea9a90ea90..95635653d48 100644
--- a/mobile/chrome/content/AnimatedZoom.js
+++ b/mobile/chrome/content/AnimatedZoom.js
@@ -76,6 +76,7 @@ const AnimatedZoom = {
start: function start() {
this.tab = Browser.selectedTab;
this.browser = this.tab.browser;
+ this.bcr = this.browser.getBoundingClientRect();
this.zoomFrom = this.zoomRect || this.getStartRect();
this.startScale = this.browser.scale;
this.beginTime = mozAnimationStartTime;
@@ -84,14 +85,13 @@ const AnimatedZoom = {
/** Get the visible rect, in device pixels relative to the content origin. */
getStartRect: function getStartRect() {
let browser = this.browser;
- let bcr = browser.getBoundingClientRect();
let scroll = browser.getRootView().getPosition();
- return new Rect(scroll.x, scroll.y, bcr.width, bcr.height);
+ return new Rect(scroll.x, scroll.y, this.bcr.width, this.bcr.height);
},
/** Update the visible rect, in device pixels relative to the content origin. */
updateTo: function(nextRect) {
- let zoomRatio = window.innerWidth / nextRect.width;
+ let zoomRatio = this.bcr.width / nextRect.width;
let scale = this.startScale * zoomRatio;
let scrollX = nextRect.left * zoomRatio;
let scrollY = nextRect.top * zoomRatio;
diff --git a/mobile/chrome/content/Util.js b/mobile/chrome/content/Util.js
index 72542987619..1b5b94fdf16 100644
--- a/mobile/chrome/content/Util.js
+++ b/mobile/chrome/content/Util.js
@@ -161,15 +161,29 @@ let Util = {
return (!appInfo || appInfo.getService(Ci.nsIXULRuntime).processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT);
},
- isTablet: function isTablet() {
+ isTablet: function isTablet(options) {
+ let forceUpdate = options && 'forceUpdate' in options && options.forceUpdate;
+
+ if ('_isTablet' in this && !forceUpdate)
+ return this._isTablet;
+
+ let tabletPref = Services.prefs.getIntPref("browser.ui.layout.tablet");
+
+ // Act according to user prefs if tablet mode has been
+ // explicitly disabled or enabled.
+ if (tabletPref == 0)
+ return this._isTablet = false;
+ else if (tabletPref == 1)
+ return this._isTablet = true;
+
let dpi = this.displayDPI;
if (dpi <= 96)
- return (window.innerWidth > 1024);
+ return this._isTablet = (window.innerWidth > 1024);
// See the tablet_panel_minwidth from mobile/themes/core/defines.inc
let tablet_panel_minwidth = 124;
let dpmm = 25.4 * window.innerWidth / dpi;
- return (dpmm >= tablet_panel_minwidth);
+ return this._isTablet = (dpmm >= tablet_panel_minwidth);
},
isPortrait: function isPortrait() {
diff --git a/mobile/chrome/content/browser-ui.js b/mobile/chrome/content/browser-ui.js
index d7acdf7293e..6280f21ca7b 100644
--- a/mobile/chrome/content/browser-ui.js
+++ b/mobile/chrome/content/browser-ui.js
@@ -186,6 +186,8 @@ var BrowserUI = {
},
lockToolbar: function lockToolbar() {
+ if (Util.isTablet())
+ return;
this._toolbarLocked++;
document.getElementById("toolbar-moveable-container").top = "0";
if (this._toolbarLocked == 1)
@@ -379,11 +381,6 @@ var BrowserUI = {
return this._toolbarH;
},
- get sidebarW() {
- delete this._sidebarW;
- return this._sidebarW = Elements.controls.getBoundingClientRect().width;
- },
-
sizeControls: function(windowW, windowH) {
// tabs
document.getElementById("tabs").resize();
@@ -552,11 +549,27 @@ var BrowserUI = {
},
updateTabletLayout: function updateTabletLayout() {
- let tabletPref = Services.prefs.getIntPref("browser.ui.layout.tablet");
- if (tabletPref == 1 || (tabletPref == -1 && Util.isTablet()))
+ if (Util.isTablet({ forceUpdate: true })) {
+ this.unlockToolbar();
Elements.urlbarState.setAttribute("tablet", "true");
- else
+ } else {
Elements.urlbarState.removeAttribute("tablet");
+ }
+
+ // Tablet mode changes the size of the thumbnails
+ // in the tabs container. Hence we have to force a
+ // thumbnail update on all tabs.
+ setTimeout(function(self) {
+ self._updateAllTabThumbnails();
+ }, 0, this);
+ },
+
+ _updateAllTabThumbnails: function() {
+ let tabs = Browser.tabs;
+
+ tabs.forEach(function(tab) {
+ tab.updateThumbnail({ force: true });
+ });
},
update: function(aState) {
diff --git a/mobile/chrome/content/browser.js b/mobile/chrome/content/browser.js
index 277a000f298..5d4157a8b6c 100644
--- a/mobile/chrome/content/browser.js
+++ b/mobile/chrome/content/browser.js
@@ -1038,7 +1038,7 @@ var Browser = {
},
tryFloatToolbar: function tryFloatToolbar(dx, dy) {
- if (this.floatedWhileDragging)
+ if (this.floatedWhileDragging || Util.isTablet())
return;
let [leftvis, ritevis, leftw, ritew] = Browser.computeSidebarVisibility(dx, dy);
@@ -1289,7 +1289,7 @@ Browser.MainDragger.prototype = {
let bcr = browser.getBoundingClientRect();
this._contentView = browser.getViewAt(clientX - bcr.left, clientY - bcr.top);
this._stopAtSidebar = 0;
- this._panToolbars = !Elements.urlbarState.getAttribute("tablet");
+ this._panToolbars = !Util.isTablet();
if (this._sidebarTimeout) {
clearTimeout(this._sidebarTimeout);
this._sidebarTimeout = null;
@@ -1908,7 +1908,7 @@ const ContentTouchHandler = {
// or if the urlbar is showing
this.canCancelPan = (aX >= rect.left + kSafetyX) && (aX <= rect.right - kSafetyX) &&
(aY >= rect.top + kSafetyY) &&
- (bcr.top == 0 || Elements.urlbarState.getAttribute("tablet"));
+ (bcr.top == 0 || Util.isTablet());
},
tapDown: function tapDown(aX, aY) {
@@ -2899,7 +2899,6 @@ Tab.prototype = {
let notification = this._notification = document.createElement("notificationbox");
notification.classList.add("inputHandler");
- // Create the browser using the current width the dynamically size the height
let browser = this._browser = document.createElement("browser");
browser.setAttribute("class", "viewable-width viewable-height");
this._chromeTab.linkedBrowser = browser;
@@ -3155,15 +3154,18 @@ function rendererFactory(aBrowser, aCanvas) {
*/
var ViewableAreaObserver = {
get width() {
- return this._width || window.innerWidth;
+ let width = this._width || window.innerWidth;
+ if (Util.isTablet()) {
+ let sidebarWidth = Math.round(Elements.tabs.getBoundingClientRect().width);
+ width -= sidebarWidth;
+ }
+ return width;
},
get height() {
let height = (this._height || window.innerHeight);
- if (Elements.urlbarState.getAttribute("tablet")) {
- let toolbarHeight = Math.round(document.getElementById("toolbar-main").getBoundingClientRect().height);
- height -= toolbarHeight;
- }
+ if (Util.isTablet())
+ height -= BrowserUI.toolbarH;
return height;
},
diff --git a/mobile/chrome/content/browser.xul b/mobile/chrome/content/browser.xul
index 2efe83dcd27..06820f9641c 100644
--- a/mobile/chrome/content/browser.xul
+++ b/mobile/chrome/content/browser.xul
@@ -198,22 +198,22 @@