Bug 1314401 - Part 1: Eagerly check IsRegExpObject in IsRegExpMethodOptimizable. r=till sec-approval=dveditz
authorTooru Fujisawa <arai_a@mac.com>
Fri, 04 Nov 2016 20:27:58 +0900
changeset 320962 05773111312ff06c776ab82602204e84a13dbb2c
parent 320961 3d032c10f6cc6d16ee04533ea7a218bf1ec4491d
child 320963 cb45e90f6596bbe9c96f1a99b690ce348c7a9321
push id83488
push userarai_a@mac.com
push dateFri, 04 Nov 2016 11:28:53 +0000
treeherdermozilla-inbound@05773111312f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstill
bugs1314401
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1314401 - Part 1: Eagerly check IsRegExpObject in IsRegExpMethodOptimizable. r=till sec-approval=dveditz
js/src/builtin/RegExp.cpp
js/src/builtin/RegExp.h
js/src/builtin/RegExp.js
js/src/vm/RegExpObject.h
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -1670,48 +1670,44 @@ js::RegExpInstanceOptimizable(JSContext*
     if (!RegExpInstanceOptimizableRaw(cx, &args[0].toObject(), &args[1].toObject(), &result))
         return false;
 
     args.rval().setBoolean(result);
     return true;
 }
 
 bool
-js::RegExpInstanceOptimizableRaw(JSContext* cx, JSObject* rx, JSObject* proto, uint8_t* result)
+js::RegExpInstanceOptimizableRaw(JSContext* cx, JSObject* obj, JSObject* proto, uint8_t* result)
 {
     JS::AutoCheckCannotGC nogc;
-    if (!rx->isNative()) {
-        *result = false;
-        return true;
-    }
 
-    NativeObject* nobj = static_cast<NativeObject*>(rx);
+    RegExpObject* rx = &obj->as<RegExpObject>();
 
     Shape* shape = cx->compartment()->regExps.getOptimizableRegExpInstanceShape();
-    if (shape == nobj->lastProperty()) {
+    if (shape == rx->lastProperty()) {
         *result = true;
         return true;
     }
 
     if (!rx->hasStaticPrototype()) {
         *result = false;
         return true;
     }
 
     if (rx->staticPrototype() != proto) {
         *result = false;
         return true;
     }
 
-    if (!RegExpObject::isInitialShape(nobj)) {
+    if (!RegExpObject::isInitialShape(rx)) {
         *result = false;
         return true;
     }
 
-    cx->compartment()->regExps.setOptimizableRegExpInstanceShape(nobj->lastProperty());
+    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
--- a/js/src/builtin/RegExp.h
+++ b/js/src/builtin/RegExp.h
@@ -114,17 +114,17 @@ RegExpPrototypeOptimizable(JSContext* cx
 
 extern MOZ_MUST_USE bool
 RegExpPrototypeOptimizableRaw(JSContext* cx, JSObject* proto, uint8_t* result);
 
 extern MOZ_MUST_USE bool
 RegExpInstanceOptimizable(JSContext* cx, unsigned argc, Value* vp);
 
 extern MOZ_MUST_USE bool
-RegExpInstanceOptimizableRaw(JSContext* cx, JSObject* rx, JSObject* proto, uint8_t* result);
+RegExpInstanceOptimizableRaw(JSContext* cx, JSObject* obj, JSObject* proto, uint8_t* result);
 
 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/builtin/RegExp.js
+++ b/js/src/builtin/RegExp.js
@@ -257,16 +257,19 @@ function RegExpLocalMatchOpt(rx, S, stic
 //   * global
 //   * ignoreCase
 //   * multiline
 //   * sticky
 //   * unicode
 //   * exec
 //   * lastIndex
 function IsRegExpMethodOptimizable(rx) {
+    if (!IsRegExpObject(rx))
+        return false;
+
     var RegExpProto = GetBuiltinPrototype("RegExp");
     // If RegExpPrototypeOptimizable and RegExpInstanceOptimizable succeed,
     // `RegExpProto.exec` is guaranteed to be data properties.
     return RegExpPrototypeOptimizable(RegExpProto) &&
            RegExpInstanceOptimizable(rx, RegExpProto) &&
            RegExpProto.exec === RegExp_prototype_Exec;
 }
 
--- a/js/src/vm/RegExpObject.h
+++ b/js/src/vm/RegExpObject.h
@@ -427,18 +427,18 @@ class RegExpObject : public NativeObject
      */
     static Shape*
     assignInitialShape(ExclusiveContext* cx, Handle<RegExpObject*> obj);
 
     /* Accessors. */
 
     static unsigned lastIndexSlot() { return LAST_INDEX_SLOT; }
 
-    static bool isInitialShape(NativeObject* nobj) {
-        Shape* shape = nobj->lastProperty();
+    static bool isInitialShape(RegExpObject* rx) {
+        Shape* shape = rx->lastProperty();
         if (!shape->hasSlot())
             return false;
         if (shape->maybeSlot() != LAST_INDEX_SLOT)
             return false;
         return true;
     }
 
     const Value& getLastIndex() const { return getSlot(LAST_INDEX_SLOT); }