From 8f66a758c7c29e02722534a22027fedae22216ef Mon Sep 17 00:00:00 2001 From: Tom Schuster Date: Wed, 6 Nov 2013 16:26:50 +0100 Subject: [PATCH] Bug 934557 - Handlify JS::ToBoolean and remove JS_ValueToBoolean. r=terrence --- js/src/builtin/TestingFunctions.cpp | 6 +- js/src/ctypes/CTypes.cpp | 5 +- js/src/jit/AsmJS.cpp | 4 +- js/src/jit/Lowering.cpp | 4 +- js/src/jit/MIR.cpp | 8 +-- js/src/jit/MIR.h | 4 ++ js/src/jit/UnreachableCodeElimination.cpp | 3 +- js/src/jsapi.cpp | 12 +--- js/src/jsapi.h | 7 +-- js/src/jsbool.cpp | 2 +- js/src/jsproxy.cpp | 2 +- js/src/shell/js.cpp | 76 ++++++++--------------- js/src/vm/Interpreter.cpp | 2 +- js/xpconnect/src/dictionary_helper_gen.py | 4 +- js/xpconnect/src/qsgen.py | 3 +- 15 files changed, 52 insertions(+), 90 deletions(-) diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index 714b6ff0295..008cd821025 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -522,14 +522,14 @@ DeterministicGC(JSContext *cx, unsigned argc, jsval *vp) { CallArgs args = CallArgsFromVp(argc, vp); - if (argc != 1) { + if (args.length() != 1) { RootedObject callee(cx, &args.callee()); ReportUsageError(cx, callee, "Wrong number of arguments"); return false; } - gc::SetDeterministicGC(cx, ToBoolean(vp[2])); - *vp = JSVAL_VOID; + gc::SetDeterministicGC(cx, ToBoolean(args[0])); + args.rval().setUndefined(); return true; } #endif /* JS_GC_ZEAL */ diff --git a/js/src/ctypes/CTypes.cpp b/js/src/ctypes/CTypes.cpp index 630c382b520..ca4f05f5231 100644 --- a/js/src/ctypes/CTypes.cpp +++ b/js/src/ctypes/CTypes.cpp @@ -2645,10 +2645,7 @@ ExplicitConvert(JSContext* cx, HandleValue val, HandleObject targetType, void* b switch (type) { case TYPE_bool: { - // Convert according to the ECMAScript ToBoolean() function. - bool result; - ASSERT_OK(JS_ValueToBoolean(cx, val, &result)); - *static_cast(buffer) = result != false; + *static_cast(buffer) = ToBoolean(val); break; } #define DEFINE_INT_TYPE(name, type, ffiType) \ diff --git a/js/src/jit/AsmJS.cpp b/js/src/jit/AsmJS.cpp index a15a4dfd2f8..03d75992e9f 100644 --- a/js/src/jit/AsmJS.cpp +++ b/js/src/jit/AsmJS.cpp @@ -2410,7 +2410,7 @@ class FunctionCompiler MBasicBlock *body; if (!newBlock(curBlock_, &body, bodyPn)) return false; - if (cond->isConstant() && ToBoolean(cond->toConstant()->value())) { + if (cond->isConstant() && cond->toConstant()->valueToBoolean()) { *afterLoop = nullptr; curBlock_->end(MGoto::New(body)); } else { @@ -2468,7 +2468,7 @@ class FunctionCompiler if (curBlock_) { JS_ASSERT(curBlock_->loopDepth() == loopStack_.length() + 1); if (cond->isConstant()) { - if (ToBoolean(cond->toConstant()->value())) { + if (cond->toConstant()->valueToBoolean()) { curBlock_->end(MGoto::New(loopEntry)); if (!loopEntry->setBackedgeAsmJS(curBlock_)) return false; diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp index 2bea6b0ba2c..a5158f790aa 100644 --- a/js/src/jit/Lowering.cpp +++ b/js/src/jit/Lowering.cpp @@ -657,13 +657,13 @@ LIRGenerator::visitTest(MTest *test) // Constant Double operand. if (opd->type() == MIRType_Double && opd->isConstant()) { - bool result = ToBoolean(opd->toConstant()->value()); + bool result = opd->toConstant()->valueToBoolean(); return add(new LGoto(result ? ifTrue : ifFalse)); } // Constant Float32 operand. if (opd->type() == MIRType_Float32 && opd->isConstant()) { - bool result = ToBoolean(opd->toConstant()->value()); + bool result = opd->toConstant()->valueToBoolean(); return add(new LGoto(result ? ifTrue : ifFalse)); } diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp index eedb4ba969c..b0d0784bd88 100644 --- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -2459,12 +2459,12 @@ MNot::foldsTo(bool useValueNumbers) { // Fold if the input is constant if (operand()->isConstant()) { - const Value &v = operand()->toConstant()->value(); + bool result = operand()->toConstant()->valueToBoolean(); if (type() == MIRType_Int32) - return MConstant::New(Int32Value(!ToBoolean(v))); + return MConstant::New(Int32Value(!result)); - // ToBoolean can cause no side effects, so this is safe. - return MConstant::New(BooleanValue(!ToBoolean(v))); + // ToBoolean can't cause side effects, so this is safe. + return MConstant::New(BooleanValue(!result)); } // NOT of an undefined or null value is always true diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index 5a3f628dc28..ab0ccc53db2 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -969,6 +969,10 @@ class MConstant : public MNullaryInstruction const js::Value *vp() const { return &value_; } + const bool valueToBoolean() const { + // A hack to avoid this wordy pattern everywhere in the JIT. + return ToBoolean(HandleValue::fromMarkedLocation(&value_)); + } void printOpcode(FILE *fp) const; diff --git a/js/src/jit/UnreachableCodeElimination.cpp b/js/src/jit/UnreachableCodeElimination.cpp index f72329b650f..6312e7234c5 100644 --- a/js/src/jit/UnreachableCodeElimination.cpp +++ b/js/src/jit/UnreachableCodeElimination.cpp @@ -123,8 +123,7 @@ UnreachableCodeElimination::optimizableSuccessor(MBasicBlock *block) if (!v->isConstant()) return nullptr; - const Value &val = v->toConstant()->value(); - BranchDirection bdir = ToBoolean(val) ? TRUE_BRANCH : FALSE_BRANCH; + BranchDirection bdir = v->toConstant()->valueToBoolean() ? TRUE_BRANCH : FALSE_BRANCH; return testIns->branchSuccessor(bdir); } diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index fb38ad6f532..d548b4da050 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -242,7 +242,7 @@ JS_ConvertArgumentsVA(JSContext *cx, unsigned argc, jsval *argv, const char *for RootedValue arg(cx, *sp); switch (c) { case 'b': - *va_arg(ap, bool *) = ToBoolean(*sp); + *va_arg(ap, bool *) = ToBoolean(arg); break; case 'c': if (!ToUint16(cx, arg, va_arg(ap, uint16_t *))) @@ -444,16 +444,6 @@ JS_DoubleToUint32(double d) return ToUint32(d); } -JS_PUBLIC_API(bool) -JS_ValueToBoolean(JSContext *cx, jsval value, bool *bp) -{ - AssertHeapIsIdle(cx); - CHECK_REQUEST(cx); - assertSameCompartment(cx, value); - *bp = ToBoolean(value); - return true; -} - JS_PUBLIC_API(JSType) JS_TypeOfValue(JSContext *cx, jsval valueArg) { diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 9b4b43ac51b..69a6af98676 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -1056,7 +1056,7 @@ ToNumberSlow(JSContext *cx, JS::Value v, double *dp); * DO NOT CALL THIS. Use JS::ToBoolean */ extern JS_PUBLIC_API(bool) -ToBooleanSlow(const JS::Value &v); +ToBooleanSlow(JS::HandleValue v); } /* namespace js */ namespace JS { @@ -1079,7 +1079,7 @@ ToNumber(JSContext *cx, Handle v, double *out) } JS_ALWAYS_INLINE bool -ToBoolean(const Value &v) +ToBoolean(HandleValue v) { if (v.isBoolean()) return v.toBoolean(); @@ -1203,9 +1203,6 @@ ToUint64(JSContext *cx, JS::Handle v, uint64_t *out) } /* namespace JS */ -extern JS_PUBLIC_API(bool) -JS_ValueToBoolean(JSContext *cx, jsval v, bool *bp); - extern JS_PUBLIC_API(JSType) JS_TypeOfValue(JSContext *cx, jsval v); diff --git a/js/src/jsbool.cpp b/js/src/jsbool.cpp index 0acfc41f743..9c6c00f94d3 100644 --- a/js/src/jsbool.cpp +++ b/js/src/jsbool.cpp @@ -182,7 +182,7 @@ js_BooleanToString(ExclusiveContext *cx, bool b) } JS_PUBLIC_API(bool) -js::ToBooleanSlow(const Value &v) +js::ToBooleanSlow(HandleValue v) { if (v.isString()) return v.toString()->length() != 0; diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index 0f47f1d57ef..871510bbc40 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -692,7 +692,7 @@ IndicatePropertyNotFound(MutableHandle desc) } static bool -ValueToBool(const Value &v, bool *bp) +ValueToBool(HandleValue v, bool *bp) { *bp = ToBoolean(v); return true; diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index ca475d319a9..bf6aadf1600 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -917,36 +917,24 @@ Evaluate(JSContext *cx, unsigned argc, jsval *vp) if (!JS_GetProperty(cx, opts, "newContext", &v)) return false; - if (!JSVAL_IS_VOID(v)) { - bool b; - if (!JS_ValueToBoolean(cx, v, &b)) - return false; - newContext = b; - } + if (!v.isUndefined()) + newContext = ToBoolean(v); if (!JS_GetProperty(cx, opts, "compileAndGo", &v)) return false; - if (!JSVAL_IS_VOID(v)) { - bool b; - if (!JS_ValueToBoolean(cx, v, &b)) - return false; - compileAndGo = b; - } + if (!v.isUndefined()) + compileAndGo = ToBoolean(v); if (!JS_GetProperty(cx, opts, "noScriptRval", &v)) return false; - if (!JSVAL_IS_VOID(v)) { - bool b; - if (!JS_ValueToBoolean(cx, v, &b)) - return false; - noScriptRval = b; - } + if (!v.isUndefined()) + noScriptRval = ToBoolean(v); if (!JS_GetProperty(cx, opts, "fileName", &v)) return false; - if (JSVAL_IS_NULL(v)) { + if (v.isNull()) { fileName = nullptr; - } else if (!JSVAL_IS_VOID(v)) { + } else if (!v.isUndefined()) { JSString *s = JS_ValueToString(cx, v); if (!s) return false; @@ -957,12 +945,12 @@ Evaluate(JSContext *cx, unsigned argc, jsval *vp) if (!JS_GetProperty(cx, opts, "element", &v)) return false; - if (!JSVAL_IS_PRIMITIVE(v)) - element = JSVAL_TO_OBJECT(v); + if (v.isObject()) + element = &v.toObject(); if (!JS_GetProperty(cx, opts, "sourceURL", &v)) return false; - if (!JSVAL_IS_VOID(v)) { + if (!v.isUndefined()) { sourceURL = JS_ValueToString(cx, v); if (!sourceURL) return false; @@ -970,7 +958,7 @@ Evaluate(JSContext *cx, unsigned argc, jsval *vp) if (!JS_GetProperty(cx, opts, "sourceMapURL", &v)) return false; - if (!JSVAL_IS_VOID(v)) { + if (!v.isUndefined()) { sourceMapURL = JS_ValueToString(cx, v); if (!sourceMapURL) return false; @@ -978,7 +966,7 @@ Evaluate(JSContext *cx, unsigned argc, jsval *vp) if (!JS_GetProperty(cx, opts, "lineNumber", &v)) return false; - if (!JSVAL_IS_VOID(v)) { + if (!v.isUndefined()) { uint32_t u; if (!ToUint32(cx, v, &u)) return false; @@ -987,10 +975,9 @@ Evaluate(JSContext *cx, unsigned argc, jsval *vp) if (!JS_GetProperty(cx, opts, "global", &v)) return false; - if (!JSVAL_IS_VOID(v)) { - global = JSVAL_IS_PRIMITIVE(v) ? nullptr : JSVAL_TO_OBJECT(v); - if (global) { - global = js::UncheckedUnwrap(global); + if (!v.isUndefined()) { + if (v.isObject()) { + global = js::UncheckedUnwrap(&v.toObject()); if (!global) return false; } @@ -1003,25 +990,17 @@ Evaluate(JSContext *cx, unsigned argc, jsval *vp) if (!JS_GetProperty(cx, opts, "catchTermination", &v)) return false; - if (!JSVAL_IS_VOID(v)) { - bool b; - if (!JS_ValueToBoolean(cx, v, &b)) - return false; - catchTermination = b; - } + if (!v.isUndefined()) + catchTermination = ToBoolean(v); if (!JS_GetProperty(cx, opts, "saveFrameChain", &v)) return false; - if (!JSVAL_IS_VOID(v)) { - bool b; - if (!JS_ValueToBoolean(cx, v, &b)) - return false; - saveFrameChain = b; - } + if (!v.isUndefined()) + saveFrameChain = ToBoolean(v); if (!JS_GetProperty(cx, opts, "sourcePolicy", &v)) return false; - if (!JSVAL_IS_VOID(v)) { + if (!v.isUndefined()) { JSString *s = JS_ValueToString(cx, v); if (!s) return false; @@ -2454,13 +2433,14 @@ static bool sandbox_enumerate(JSContext *cx, HandleObject obj) { RootedValue v(cx); - bool b; if (!JS_GetProperty(cx, obj, "lazy", &v)) return false; - JS_ValueToBoolean(cx, v, &b); - return !b || JS_EnumerateStandardClasses(cx, obj); + if (!ToBoolean(v)) + return true; + + return JS_EnumerateStandardClasses(cx, obj); } static bool @@ -2468,13 +2448,11 @@ sandbox_resolve(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, MutableHandleObject objp) { RootedValue v(cx); - bool b, resolved; - if (!JS_GetProperty(cx, obj, "lazy", &v)) return false; - JS_ValueToBoolean(cx, v, &b); - if (b) { + if (ToBoolean(v)) { + bool resolved; if (!JS_ResolveStandardClass(cx, obj, id, &resolved)) return false; if (resolved) { diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index d30282ee644..470b053d1ec 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -73,7 +73,7 @@ static bool #endif ToBooleanOp(const FrameRegs ®s) { - return ToBoolean(regs.sp[-1]); + return ToBoolean(regs.stackHandleAt(-1)); } template diff --git a/js/xpconnect/src/dictionary_helper_gen.py b/js/xpconnect/src/dictionary_helper_gen.py index 857b04e394f..fd88d182f72 100644 --- a/js/xpconnect/src/dictionary_helper_gen.py +++ b/js/xpconnect/src/dictionary_helper_gen.py @@ -282,9 +282,7 @@ def write_getter(a, iface, fd): if realtype.count("JS::Value"): fd.write(" aDict.%s = v;\n" % a.name) elif realtype.count("bool"): - fd.write(" bool b;\n") - fd.write(" MOZ_ALWAYS_TRUE(JS_ValueToBoolean(aCx, v, &b));\n") - fd.write(" aDict.%s = b;\n" % a.name) + fd.write(" aDict.%s = JS::ToBoolean(v);\n" % a.name) elif realtype.count("uint16_t"): fd.write(" uint32_t u;\n") fd.write(" NS_ENSURE_STATE(JS::ToUint32(aCx, v, &u));\n") diff --git a/js/xpconnect/src/qsgen.py b/js/xpconnect/src/qsgen.py index 990ba41e7cb..04be318801e 100644 --- a/js/xpconnect/src/qsgen.py +++ b/js/xpconnect/src/qsgen.py @@ -433,8 +433,7 @@ argumentUnboxingTemplates = { " return false;\n", 'boolean': - " bool ${name};\n" - " JS_ValueToBoolean(cx, ${argVal}, &${name});\n", + " bool ${name} = JS::ToBoolean(${argVal});\n", '[astring]': " xpc_qsAString ${name}(cx, ${argVal}, ${argPtr}, ${notPassed});\n"