Bug 1324810 - Part 1: Make RegExpPrototypeOptimizableRaw and RegExpInstanceOptimizableRaw infallible. r=jandem, a=lizzard
authorTooru Fujisawa <arai_a@mac.com>
Thu, 22 Dec 2016 04:39:44 +0900
changeset 353281 1458ff2725619c3db4b1dcb4f057f26a60208873
parent 353280 fe80ac73a1121b8ba7a6c7040a1f25d19b030739
child 353282 6320e45707353782ef142c667e987102f9636140
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-esr52@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem, lizzard
bugs1324810
milestone52.0a2
Bug 1324810 - Part 1: Make RegExpPrototypeOptimizableRaw and RegExpInstanceOptimizableRaw infallible. r=jandem, a=lizzard
js/src/builtin/RegExp.cpp
js/src/builtin/RegExp.h
js/src/jit/CodeGenerator.cpp
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -1546,174 +1546,135 @@ js::GetFirstDollarIndexRaw(JSContext* cx
 
 bool
 js::RegExpPrototypeOptimizable(JSContext* cx, unsigned argc, Value* vp)
 {
     // This can only be called from self-hosted code.
     CallArgs args = CallArgsFromVp(argc, vp);
     MOZ_ASSERT(args.length() == 1);
 
-    uint8_t result = false;
-    if (!RegExpPrototypeOptimizableRaw(cx, &args[0].toObject(), &result))
-        return false;
-
-    args.rval().setBoolean(result);
+    args.rval().setBoolean(RegExpPrototypeOptimizableRaw(cx, &args[0].toObject()));
     return true;
 }
 
 bool
-js::RegExpPrototypeOptimizableRaw(JSContext* cx, JSObject* proto, uint8_t* result)
+js::RegExpPrototypeOptimizableRaw(JSContext* cx, JSObject* proto)
 {
     JS::AutoCheckCannotGC nogc;
-    if (!proto->isNative()) {
-        *result = false;
-        return true;
-    }
+    AutoAssertNoPendingException aanpe(cx);
+    if (!proto->isNative())
+        return false;
 
     NativeObject* nproto = static_cast<NativeObject*>(proto);
 
     Shape* shape = cx->compartment()->regExps.getOptimizableRegExpPrototypeShape();
-    if (shape == nproto->lastProperty()) {
-        *result = true;
+    if (shape == nproto->lastProperty())
         return true;
-    }
 
     JSFunction* flagsGetter;
     if (!GetOwnGetterPure(cx, proto, NameToId(cx->names().flags), &flagsGetter))
         return false;
 
-    if (!flagsGetter) {
-        *result = false;
-        return true;
-    }
+    if (!flagsGetter)
+        return false;
 
-    if (!IsSelfHostedFunctionWithName(flagsGetter, cx->names().RegExpFlagsGetter)) {
-        *result = false;
-        return true;
-    }
+    if (!IsSelfHostedFunctionWithName(flagsGetter, cx->names().RegExpFlagsGetter))
+        return false;
 
     JSNative globalGetter;
     if (!GetOwnNativeGetterPure(cx, proto, NameToId(cx->names().global), &globalGetter))
         return false;
 
-    if (globalGetter != regexp_global) {
-        *result = false;
-        return true;
-    }
+    if (globalGetter != regexp_global)
+        return false;
 
     JSNative ignoreCaseGetter;
     if (!GetOwnNativeGetterPure(cx, proto, NameToId(cx->names().ignoreCase), &ignoreCaseGetter))
         return false;
 
-    if (ignoreCaseGetter != regexp_ignoreCase) {
-        *result = false;
-        return true;
-    }
+    if (ignoreCaseGetter != regexp_ignoreCase)
+        return false;
 
     JSNative multilineGetter;
     if (!GetOwnNativeGetterPure(cx, proto, NameToId(cx->names().multiline), &multilineGetter))
         return false;
 
-    if (multilineGetter != regexp_multiline) {
-        *result = false;
-        return true;
-    }
+    if (multilineGetter != regexp_multiline)
+        return false;
 
     JSNative stickyGetter;
     if (!GetOwnNativeGetterPure(cx, proto, NameToId(cx->names().sticky), &stickyGetter))
         return false;
 
-    if (stickyGetter != regexp_sticky) {
-        *result = false;
-        return true;
-    }
+    if (stickyGetter != regexp_sticky)
+        return false;
 
     JSNative unicodeGetter;
     if (!GetOwnNativeGetterPure(cx, proto, NameToId(cx->names().unicode), &unicodeGetter))
         return false;
 
-    if (unicodeGetter != regexp_unicode) {
-        *result = false;
-        return true;
-    }
+    if (unicodeGetter != regexp_unicode)
+        return false;
 
     // Check if @@match, @@search, and exec are own data properties,
     // those values should be tested in selfhosted JS.
     bool has = false;
     if (!HasOwnDataPropertyPure(cx, proto, SYMBOL_TO_JSID(cx->wellKnownSymbols().match), &has))
         return false;
-    if (!has) {
-        *result = false;
-        return true;
-    }
+    if (!has)
+        return false;
 
     if (!HasOwnDataPropertyPure(cx, proto, SYMBOL_TO_JSID(cx->wellKnownSymbols().search), &has))
         return false;
-    if (!has) {
-        *result = false;
-        return true;
-    }
+    if (!has)
+        return false;
 
     if (!HasOwnDataPropertyPure(cx, proto, NameToId(cx->names().exec), &has))
         return false;
-    if (!has) {
-        *result = false;
-        return true;
-    }
+    if (!has)
+        return false;
 
     cx->compartment()->regExps.setOptimizableRegExpPrototypeShape(nproto->lastProperty());
-    *result = true;
     return true;
 }
 
 bool
 js::RegExpInstanceOptimizable(JSContext* cx, unsigned argc, Value* vp)
 {
     // This can only be called from self-hosted code.
     CallArgs args = CallArgsFromVp(argc, vp);
     MOZ_ASSERT(args.length() == 2);
 
-    uint8_t result = false;
-    if (!RegExpInstanceOptimizableRaw(cx, &args[0].toObject(), &args[1].toObject(), &result))
-        return false;
-
-    args.rval().setBoolean(result);
+    args.rval().setBoolean(RegExpInstanceOptimizableRaw(cx, &args[0].toObject(),
+                                                        &args[1].toObject()));
     return true;
 }
 
 bool
-js::RegExpInstanceOptimizableRaw(JSContext* cx, JSObject* obj, JSObject* proto, uint8_t* result)
+js::RegExpInstanceOptimizableRaw(JSContext* cx, JSObject* obj, JSObject* proto)
 {
     JS::AutoCheckCannotGC nogc;
+    AutoAssertNoPendingException aanpe(cx);
 
     RegExpObject* rx = &obj->as<RegExpObject>();
 
     Shape* shape = cx->compartment()->regExps.getOptimizableRegExpInstanceShape();
-    if (shape == rx->lastProperty()) {
-        *result = true;
+    if (shape == rx->lastProperty())
         return true;
-    }
 
-    if (!rx->hasStaticPrototype()) {
-        *result = false;
-        return true;
-    }
+    if (!rx->hasStaticPrototype())
+        return false;
 
-    if (rx->staticPrototype() != proto) {
-        *result = false;
-        return true;
-    }
+    if (rx->staticPrototype() != proto)
+        return false;
 
-    if (!RegExpObject::isInitialShape(rx)) {
-        *result = false;
-        return true;
-    }
+    if (!RegExpObject::isInitialShape(rx))
+        return false;
 
     cx->compartment()->regExps.setOptimizableRegExpInstanceShape(rx->lastProperty());
-    *result = true;
     return true;
 }
 
 /*
  * Pattern match the script to check if it is is indexing into a particular
  * object, e.g. 'function(a) { return b[a]; }'. Avoid calling the script in
  * such cases, which are used by javascript packers (particularly the popular
  * Dean Edwards packer) to efficiently encode large scripts. We only handle the
--- a/js/src/builtin/RegExp.h
+++ b/js/src/builtin/RegExp.h
@@ -108,23 +108,23 @@ IsRegExp(JSContext* cx, HandleValue valu
 
 extern MOZ_MUST_USE bool
 RegExpCreate(JSContext* cx, HandleValue pattern, HandleValue flags, MutableHandleValue rval);
 
 extern MOZ_MUST_USE bool
 RegExpPrototypeOptimizable(JSContext* cx, unsigned argc, Value* vp);
 
 extern MOZ_MUST_USE bool
-RegExpPrototypeOptimizableRaw(JSContext* cx, JSObject* proto, uint8_t* result);
+RegExpPrototypeOptimizableRaw(JSContext* cx, JSObject* proto);
 
 extern MOZ_MUST_USE bool
 RegExpInstanceOptimizable(JSContext* cx, unsigned argc, Value* vp);
 
 extern MOZ_MUST_USE bool
-RegExpInstanceOptimizableRaw(JSContext* cx, JSObject* obj, JSObject* proto, uint8_t* result);
+RegExpInstanceOptimizableRaw(JSContext* cx, JSObject* obj, JSObject* proto);
 
 extern MOZ_MUST_USE bool
 RegExpGetSubstitution(JSContext* cx, HandleLinearString matched, HandleLinearString string,
                       size_t position, HandleObject capturesObj, HandleLinearString replacement,
                       size_t firstDollarIndex, MutableHandleValue rval);
 
 extern MOZ_MUST_USE bool
 GetFirstDollarIndex(JSContext* cx, unsigned argc, Value* vp);
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -2100,33 +2100,25 @@ CodeGenerator::visitRegExpPrototypeOptim
 }
 
 void
 CodeGenerator::visitOutOfLineRegExpPrototypeOptimizable(OutOfLineRegExpPrototypeOptimizable* ool)
 {
     LRegExpPrototypeOptimizable* ins = ool->ins();
     Register object = ToRegister(ins->object());
     Register output = ToRegister(ins->output());
-    Register temp = ToRegister(ins->temp());
 
     saveVolatile(output);
 
-    masm.reserveStack(sizeof(void*));
-    masm.moveStackPtrTo(temp);
-
     masm.setupUnalignedABICall(output);
     masm.loadJSContext(output);
     masm.passABIArg(output);
     masm.passABIArg(object);
-    masm.passABIArg(temp);
     masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, RegExpPrototypeOptimizableRaw));
-    masm.branchIfFalseBool(ReturnReg, masm.exceptionLabel());
-
-    masm.load8ZeroExtend(Address(masm.getStackPointer(), 0), output);
-    masm.freeStack(sizeof(void*));
+    masm.storeCallBoolResult(output);
 
     restoreVolatile(output);
 
     masm.jump(ool->rejoin());
 }
 
 class OutOfLineRegExpInstanceOptimizable : public OutOfLineCodeBase<CodeGenerator>
 {
@@ -2170,34 +2162,26 @@ CodeGenerator::visitRegExpInstanceOptimi
 
 void
 CodeGenerator::visitOutOfLineRegExpInstanceOptimizable(OutOfLineRegExpInstanceOptimizable* ool)
 {
     LRegExpInstanceOptimizable* ins = ool->ins();
     Register object = ToRegister(ins->object());
     Register proto = ToRegister(ins->proto());
     Register output = ToRegister(ins->output());
-    Register temp = ToRegister(ins->temp());
 
     saveVolatile(output);
 
-    masm.reserveStack(sizeof(void*));
-    masm.moveStackPtrTo(temp);
-
     masm.setupUnalignedABICall(output);
     masm.loadJSContext(output);
     masm.passABIArg(output);
     masm.passABIArg(object);
     masm.passABIArg(proto);
-    masm.passABIArg(temp);
     masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, RegExpInstanceOptimizableRaw));
-    masm.branchIfFalseBool(ReturnReg, masm.exceptionLabel());
-
-    masm.load8ZeroExtend(Address(masm.getStackPointer(), 0), output);
-    masm.freeStack(sizeof(void*));
+    masm.storeCallBoolResult(output);
 
     restoreVolatile(output);
 
     masm.jump(ool->rejoin());
 }
 
 static void
 FindFirstDollarIndex(MacroAssembler& masm, Register str, Register len, Register chars,