Bug 1314401 - Part 1: Eagerly check IsRegExpObject in IsRegExpMethodOptimizable. r=till, a=dveditz
authorTooru Fujisawa <arai_a@mac.com>
Wed, 02 Nov 2016 20:42:17 +0900
changeset 340926 bb22a02189975144b8752bede0230170ec929e2c
parent 340925 4fe13d90d53a89ada7689f9c2de73456e02bd7ce
child 340927 a1243da2fec4f351fa1fc5a2314f704f670fd8e8
push id10256
push userryanvm@gmail.com
push dateMon, 07 Nov 2016 17:59:41 +0000
treeherdermozilla-aurora@a1243da2fec4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstill, dveditz
bugs1314401
milestone51.0a2
Bug 1314401 - Part 1: Eagerly check IsRegExpObject in IsRegExpMethodOptimizable. r=till, a=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
@@ -1622,48 +1622,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
@@ -108,17 +108,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
@@ -151,16 +151,19 @@ function RegExpMatch(string) {
 
 // Checks if following properties and getters are not modified, and accessing
 // them not observed by content script:
 //   * global
 //   * sticky
 //   * 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
@@ -420,18 +420,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); }