Commit c05ddf61 authored by Ed Morley's avatar Ed Morley
Browse files

Backout 564d554c4318 (bug 792220) for M2 JS assertions on a CLOSED TREE

parent 20012318
Loading
Loading
Loading
Loading
+21 −31
Original line number Diff line number Diff line
@@ -561,12 +561,17 @@ GetSharedForGreedyStar(JSContext *cx, JSAtom *source, RegExpFlag flags, RegExpGu
    return cx->compartment->regExps.getHack(cx, source, hackedSource, flags, g);
}

bool
js::ExecuteRegExp(JSContext *cx, RegExpExecType execType, HandleObject regexp,
                  HandleString string, MutableHandleValue rval)
/*
 * ES5 15.10.6.2 (and 15.10.6.3, which calls 15.10.6.2).
 *
 * RegExp.prototype.test doesn't need to create a results array, and we use
 * |execType| to perform this optimization.
 */
static bool
ExecuteRegExp(JSContext *cx, RegExpExecType execType, CallArgs args)
{
    /* Step 1 (b) was performed by CallNonGenericMethod. */
    Rooted<RegExpObject*> reobj(cx, &regexp->asRegExp());
    /* Step 1 was performed by CallNonGenericMethod. */
    Rooted<RegExpObject*> reobj(cx, &args.thisv().toObject().asRegExp());

    RegExpGuard re;
    if (StartsWithGreedyStar(reobj->getSource())) {
@@ -579,8 +584,13 @@ js::ExecuteRegExp(JSContext *cx, RegExpExecType execType, HandleObject regexp,

    RegExpStatics *res = cx->regExpStatics();

    /* Step 2. */
    JSString *input = ToString(cx, (args.length() > 0) ? args[0] : UndefinedValue());
    if (!input)
        return false;

    /* Step 3. */
    Rooted<JSLinearString*> linearInput(cx, string->ensureLinear(cx));
    Rooted<JSLinearString*> linearInput(cx, input->ensureLinear(cx));
    if (!linearInput)
        return false;

@@ -602,20 +612,20 @@ js::ExecuteRegExp(JSContext *cx, RegExpExecType execType, HandleObject regexp,
    /* Step 9a. */
    if (i < 0 || i > length) {
        reobj->zeroLastIndex();
        rval.setNull();
        args.rval().setNull();
        return true;
    }

    /* Steps 8-21. */
    size_t lastIndexInt(i);
    if (!ExecuteRegExp(cx, res, *re, linearInput.get(), chars, length, &lastIndexInt, execType,
                       rval.address())) {
    if (!ExecuteRegExp(cx, res, *re, linearInput, chars, length, &lastIndexInt, execType,
                       args.rval().address())) {
        return false;
    }

    /* Step 11 (with sticky extension). */
    if (re->global() || (!rval.isNull() && re->sticky())) {
        if (rval.isNull())
    if (re->global() || (!args.rval().isNull() && re->sticky())) {
        if (args.rval().isNull())
            reobj->zeroLastIndex();
        else
            reobj->setLastIndex(lastIndexInt);
@@ -624,26 +634,6 @@ js::ExecuteRegExp(JSContext *cx, RegExpExecType execType, HandleObject regexp,
    return true;
}

/*
 * ES5 15.10.6.2 (and 15.10.6.3, which calls 15.10.6.2).
 *
 * RegExp.prototype.test doesn't need to create a results array, and we use
 * |execType| to perform this optimization.
 */
static bool
ExecuteRegExp(JSContext *cx, RegExpExecType execType, CallArgs args)
{
    /* Step 1 (a) was performed by CallNonGenericMethod. */
    RootedObject regexp(cx, &args.thisv().toObject());

    /* Step 2. */
    RootedString string(cx, ToString(cx, (args.length() > 0) ? args[0] : UndefinedValue()));
    if (!string)
        return false;

    return ExecuteRegExp(cx, execType, regexp, string, args.rval());
}

/* ES5 15.10.6.2. */
static bool
regexp_exec_impl(JSContext *cx, CallArgs args)
+0 −4
Original line number Diff line number Diff line
@@ -35,10 +35,6 @@ ExecuteRegExp(JSContext *cx, RegExpStatics *res, RegExpShared &shared,
              JSLinearString *input, const jschar *chars, size_t length,
              size_t *lastIndex, RegExpExecType type, Value *rval);

bool
ExecuteRegExp(JSContext *cx, RegExpExecType execType, HandleObject regexp,
              HandleString string, MutableHandleValue rval);

extern JSBool
regexp_exec(JSContext *cx, unsigned argc, Value *vp);

+0 −24
Original line number Diff line number Diff line
@@ -233,30 +233,6 @@ CodeGenerator::visitRegExp(LRegExp *lir)
    return callVM(CloneRegExpObjectInfo, lir);
}

bool
CodeGenerator::visitRegExpTest(LRegExpTest *lir)
{
    typedef bool (*pf)(JSContext *cx, RegExpExecType type, HandleObject regexp,
                       HandleString string, MutableHandleValue rval);
    static const VMFunction ExecuteRegExpInfo = FunctionInfo<pf>(ExecuteRegExp);

    pushArg(ToRegister(lir->string()));
    pushArg(ToRegister(lir->regexp()));
    pushArg(Imm32(RegExpTest));
    if (!callVM(ExecuteRegExpInfo, lir))
        return false;

    Register output = ToRegister(lir->output());
    Label notBool, end;
    masm.branchTestBoolean(Assembler::NotEqual, JSReturnOperand, &notBool);
    masm.unboxBoolean(JSReturnOperand, output);
    masm.jump(&end);
    masm.bind(&notBool);
    masm.mov(Imm32(0), output);
    masm.bind(&end);
    return true;
}

bool
CodeGenerator::visitLambdaForSingleton(LLambdaForSingleton *lir)
{
+0 −1
Original line number Diff line number Diff line
@@ -62,7 +62,6 @@ class CodeGenerator : public CodeGeneratorSpecific
    bool visitIntToString(LIntToString *lir);
    bool visitInteger(LInteger *lir);
    bool visitRegExp(LRegExp *lir);
    bool visitRegExpTest(LRegExpTest *lir);
    bool visitLambda(LLambda *lir);
    bool visitLambdaForSingleton(LLambdaForSingleton *lir);
    bool visitPointer(LPointer *lir);
+49 −0
Original line number Diff line number Diff line
@@ -3676,6 +3676,41 @@ IonBuilder::jsop_funapply(uint32 argc)
    return pushTypeBarrier(apply, types, barrier);
}

// Get the builtin RegExp.prototype.test function.
static bool
GetBuiltinRegExpTest(JSContext *cx, JSScript *script, JSFunction **result)
{
    JS_ASSERT(*result == NULL);

    // Get the builtin RegExp.prototype object.
    RootedObject proto(cx, script->global().getOrCreateRegExpPrototype(cx));
    if (!proto)
        return false;

    // Get the |test| property. Note that we use lookupProperty, not getProperty,
    // to avoid calling a getter.
    RootedShape shape(cx);
    RootedObject holder(cx);
    if (!JSObject::lookupProperty(cx, proto, cx->names().test, &holder, &shape))
        return false;

    if (proto != holder || !shape || !shape->hasDefaultGetter() || !shape->hasSlot())
        return true;

    // The RegExp.prototype.test property is writable, so we have to ensure
    // we got the builtin function.
    Value val = holder->getSlot(shape->slot());
    if (!val.isObject())
        return true;

    JSObject *obj = &val.toObject();
    if (!obj->isFunction() || obj->toFunction()->maybeNative() != regexp_test)
        return true;

    *result = obj->toFunction();
    return true;
}

bool
IonBuilder::jsop_call(uint32 argc, bool constructing)
{
@@ -3705,6 +3740,20 @@ IonBuilder::jsop_call(uint32 argc, bool constructing)
    }

    RootedFunction target(cx, NULL);
    if (numTargets == 1) {
        target = targets[0]->toFunction();

        // Call RegExp.test instead of RegExp.exec if the result will not be used
        // or will only be used to test for existence.
        if (target->maybeNative() == regexp_exec && !CallResultEscapes(pc)) {
            JSFunction *newTarget = NULL;
            if (!GetBuiltinRegExpTest(cx, script_, &newTarget))
                return false;
            if (newTarget)
                target = newTarget;
        }
    }

    return makeCallBarrier(target, argc, constructing, types, barrier);
}

Loading