InstanceOf IC should do generic if the prototype is not an object.
authorkeith_miller@apple.com <keith_miller@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 2 Jul 2018 18:04:54 +0000 (18:04 +0000)
committerkeith_miller@apple.com <keith_miller@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 2 Jul 2018 18:04:54 +0000 (18:04 +0000)
https://bugs.webkit.org/show_bug.cgi?id=187250

Reviewed by Mark Lam.

JSTests:

* stress/instanceof-non-object-prototype.js: Added.
(let):
(test):
(i.catch):

Source/JavaScriptCore:

The old code was wrong for two reasons. First, the AccessCase expected that
the prototype value would be non-null. Second, we would end up returning
false instead of throwing an exception.

* jit/Repatch.cpp:
(JSC::tryCacheInstanceOf):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@233427 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JSTests/ChangeLog
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/jit/Repatch.cpp
jstests/stress/instanceof-non-object-prototype.js [new file with mode: 0644]

index ec806de..3993eac 100644 (file)
@@ -1,3 +1,15 @@
+2018-07-02  Keith Miller  <keith_miller@apple.com>
+
+        InstanceOf IC should do generic if the prototype is not an object.
+        https://bugs.webkit.org/show_bug.cgi?id=187250
+
+        Reviewed by Mark Lam.
+
+        * stress/instanceof-non-object-prototype.js: Added.
+        (let):
+        (test):
+        (i.catch):
+
 2018-06-30  Mark Lam  <mark.lam@apple.com>
 
         Builtins and host functions should get their own structures.
index 97f7cdb..1cd202f 100644 (file)
@@ -1,3 +1,17 @@
+2018-07-02  Keith Miller  <keith_miller@apple.com>
+
+        InstanceOf IC should do generic if the prototype is not an object.
+        https://bugs.webkit.org/show_bug.cgi?id=187250
+
+        Reviewed by Mark Lam.
+
+        The old code was wrong for two reasons. First, the AccessCase expected that
+        the prototype value would be non-null. Second, we would end up returning
+        false instead of throwing an exception.
+
+        * jit/Repatch.cpp:
+        (JSC::tryCacheInstanceOf):
+
 2018-07-01  Mark Lam  <mark.lam@apple.com>
 
         Builtins and host functions should get their own structures.
index 6448fdf..b00ca20 100644 (file)
@@ -736,28 +736,27 @@ static InlineCacheAction tryCacheInstanceOf(
         GCSafeConcurrentJSLocker locker(codeBlock->m_lock, vm.heap);
         
         JSCell* value = valueValue.asCell();
-        JSObject* prototype = jsDynamicCast<JSObject*>(vm, prototypeValue);
-        
         Structure* structure = value->structure(vm);
-        
         std::unique_ptr<AccessCase> newCase;
-        
-        if (!jsDynamicCast<JSObject*>(vm, value)) {
-            newCase = InstanceOfAccessCase::create(
-                vm, codeBlock, AccessCase::InstanceOfMiss, structure, ObjectPropertyConditionSet(),
-                prototype);
-        } else if (prototype && structure->prototypeQueriesAreCacheable()) {
-            // FIXME: Teach this to do poly proto.
-            // https://bugs.webkit.org/show_bug.cgi?id=185663
-            
-            ObjectPropertyConditionSet conditionSet = generateConditionsForInstanceOf(
-                vm, codeBlock, exec, structure, prototype, wasFound);
-            
-            if (conditionSet.isValid()) {
+        JSObject* prototype = jsDynamicCast<JSObject*>(vm, prototypeValue);
+        if (prototype) {
+            if (!jsDynamicCast<JSObject*>(vm, value)) {
                 newCase = InstanceOfAccessCase::create(
-                    vm, codeBlock,
-                    wasFound ? AccessCase::InstanceOfHit : AccessCase::InstanceOfMiss,
-                    structure, conditionSet, prototype);
+                    vm, codeBlock, AccessCase::InstanceOfMiss, structure, ObjectPropertyConditionSet(),
+                    prototype);
+            } else if (structure->prototypeQueriesAreCacheable()) {
+                // FIXME: Teach this to do poly proto.
+                // https://bugs.webkit.org/show_bug.cgi?id=185663
+
+                ObjectPropertyConditionSet conditionSet = generateConditionsForInstanceOf(
+                    vm, codeBlock, exec, structure, prototype, wasFound);
+
+                if (conditionSet.isValid()) {
+                    newCase = InstanceOfAccessCase::create(
+                        vm, codeBlock,
+                        wasFound ? AccessCase::InstanceOfHit : AccessCase::InstanceOfMiss,
+                        structure, conditionSet, prototype);
+                }
             }
         }
         
diff --git a/jstests/stress/instanceof-non-object-prototype.js b/jstests/stress/instanceof-non-object-prototype.js
new file mode 100644 (file)
index 0000000..a43bd57
--- /dev/null
@@ -0,0 +1,21 @@
+let base = "sting";
+let constructor = function() { };
+constructor.prototype = 42;
+
+function test(a, b) {
+    return a instanceof b;
+}
+noInline(test);
+
+for (let i = 0; i < 10000; i++) {
+    let exception;
+    try {
+        var result = test(base, constructor);
+    } catch (e) {
+        exception = e;
+    }
+    if (exception)
+        throw new Error("Threw an exception: " + exception);
+    if (result !== false)
+        throw new Error("instanceof returned: " + result);
+}