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

This commit is contained in:
Ed Morley 2012-09-29 00:53:43 +01:00
parent 2425a83ed3
commit 036290e94d
14 changed files with 70 additions and 175 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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)
{

View File

@ -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);

View File

@ -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);
}

View File

@ -387,9 +387,6 @@ class IonBuilder : public MIRGenerator
InliningStatus inlineStrFromCharCode(uint32 argc, bool constructing);
InliningStatus inlineStrCharAt(uint32 argc, bool constructing);
// RegExp natives.
InliningStatus inlineRegExpTest(uint32 argc, bool constructing);
InliningStatus inlineNativeCall(JSNative native, uint32 argc, bool constructing);
bool jsop_call_inline(HandleFunction callee, uint32 argc, bool constructing,

View File

@ -1726,29 +1726,6 @@ class LRegExp : public LCallInstructionHelper<1, 0, 0>
}
};
class LRegExpTest : public LCallInstructionHelper<1, 2, 0>
{
public:
LIR_HEADER(RegExpTest);
LRegExpTest(const LAllocation &regexp, const LAllocation &string)
{
setOperand(0, regexp);
setOperand(1, string);
}
const LAllocation *regexp() {
return getOperand(0);
}
const LAllocation *string() {
return getOperand(1);
}
const MRegExpTest *mir() const {
return mir_->toRegExpTest();
}
};
class LLambdaForSingleton : public LCallInstructionHelper<1, 1, 0>
{
public:

View File

@ -94,7 +94,6 @@
_(OsrValue) \
_(OsrScopeChain) \
_(RegExp) \
_(RegExpTest) \
_(Lambda) \
_(LambdaForSingleton) \
_(ImplicitThis) \

View File

@ -1116,17 +1116,6 @@ LIRGenerator::visitRegExp(MRegExp *ins)
return defineVMReturn(lir, ins) && assignSafepoint(lir, ins);
}
bool
LIRGenerator::visitRegExpTest(MRegExpTest *ins)
{
JS_ASSERT(ins->regexp()->type() == MIRType_Object);
JS_ASSERT(ins->string()->type() == MIRType_String);
LRegExpTest *lir = new LRegExpTest(useRegisterAtStart(ins->regexp()),
useRegisterAtStart(ins->string()));
return defineVMReturn(lir, ins) && assignSafepoint(lir, ins);
}
bool
LIRGenerator::visitLambda(MLambda *ins)
{

View File

@ -127,7 +127,6 @@ class LIRGenerator : public LIRGeneratorSpecific
bool visitTruncateToInt32(MTruncateToInt32 *truncate);
bool visitToString(MToString *convert);
bool visitRegExp(MRegExp *ins);
bool visitRegExpTest(MRegExpTest *ins);
bool visitLambda(MLambda *ins);
bool visitImplicitThis(MImplicitThis *ins);
bool visitSlots(MSlots *ins);

View File

@ -64,12 +64,6 @@ IonBuilder::inlineNativeCall(JSNative native, uint32 argc, bool constructing)
if (native == js_str_charAt)
return inlineStrCharAt(argc, constructing);
// RegExp natives.
if (native == regexp_exec && !CallResultEscapes(pc))
return inlineRegExpTest(argc, constructing);
if (native == regexp_test)
return inlineRegExpTest(argc, constructing);
return InliningStatus_NotInlined;
}
@ -686,33 +680,5 @@ IonBuilder::inlineStrCharAt(uint32 argc, bool constructing)
return InliningStatus_Inlined;
}
IonBuilder::InliningStatus
IonBuilder::inlineRegExpTest(uint32 argc, bool constructing)
{
if (argc != 1 || constructing)
return InliningStatus_NotInlined;
// TI can infer a NULL return type of regexp_test with eager compilation.
if (CallResultEscapes(pc) && getInlineReturnType() != MIRType_Boolean)
return InliningStatus_NotInlined;
if (getInlineArgType(argc, 0) != MIRType_Object)
return InliningStatus_NotInlined;
if (getInlineArgType(argc, 1) != MIRType_String)
return InliningStatus_NotInlined;
MDefinitionVector argv;
if (!discardCall(argc, argv, current))
return InliningStatus_Error;
MInstruction *match = MRegExpTest::New(argv[0], argv[1]);
current->add(match);
current->push(match);
if (!resumeAfter(match))
return InliningStatus_Error;
return InliningStatus_Inlined;
}
} // namespace ion
} // namespace js

View File

@ -2970,37 +2970,6 @@ class MRegExp : public MNullaryInstruction
}
};
class MRegExpTest
: public MBinaryInstruction,
public MixPolicy<ObjectPolicy<1>, StringPolicy >
{
private:
MRegExpTest(MDefinition *regexp, MDefinition *string)
: MBinaryInstruction(string, regexp)
{
setResultType(MIRType_Boolean);
}
public:
INSTRUCTION_HEADER(RegExpTest)
static MRegExpTest *New(MDefinition *regexp, MDefinition *string) {
return new MRegExpTest(regexp, string);
}
TypePolicy *typePolicy() {
return this;
}
MDefinition *regexp() const {
return getOperand(1);
}
MDefinition *string() const {
return getOperand(0);
}
};
class MLambda
: public MUnaryInstruction,
public SingleObjectPolicy

View File

@ -75,7 +75,6 @@ namespace ion {
_(Start) \
_(OsrEntry) \
_(RegExp) \
_(RegExpTest) \
_(Lambda) \
_(ImplicitThis) \
_(Slots) \

View File

@ -1,10 +0,0 @@
var p = Proxy.create({
has : function(id) {}
});
Object.prototype.__proto__ = p;
function f() {
if (/a/.exec("a"))
(null).default++;
}
delete RegExp.prototype.test;
f();