Crash in operationNewFunction when scrolling on Google+
authormsaboff@apple.com <msaboff@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 4 Jan 2015 03:47:25 +0000 (03:47 +0000)
committermsaboff@apple.com <msaboff@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 4 Jan 2015 03:47:25 +0000 (03:47 +0000)
https://bugs.webkit.org/show_bug.cgi?id=140033

Reviewed by Oliver Hunt.

Source/JavaScriptCore:

In DFG code, the scope register can be eliminated because all uses have been
dead code eliminated.  In the case where one of the uses was creating a function
that is never used, the baseline code will still create the function.  If we OSR
exit to a path where that function gets created, check the scope register value
and set the new, but dead, function to undefined instead of creating a new function.

* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_new_func_exp):

LayoutTests:

New regerssion test.

* js/regress-140033-expected.txt: Added.
* js/regress-140033.html: Added.
* js/script-tests/regress-140033.js: Added.
(.unused):
(defineADeadFunction):

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

LayoutTests/ChangeLog
LayoutTests/js/regress-140033-expected.txt [new file with mode: 0644]
LayoutTests/js/regress-140033.html [new file with mode: 0644]
LayoutTests/js/script-tests/regress-140033.js [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/jit/JITOpcodes.cpp

index cbd774d..7ba709f 100644 (file)
@@ -1,3 +1,18 @@
+2015-01-03  Michael Saboff  <msaboff@apple.com>
+
+        Crash in operationNewFunction when scrolling on Google+
+        https://bugs.webkit.org/show_bug.cgi?id=140033
+
+        Reviewed by Oliver Hunt.
+
+        New regerssion test.
+
+        * js/regress-140033-expected.txt: Added.
+        * js/regress-140033.html: Added.
+        * js/script-tests/regress-140033.js: Added.
+        (.unused):
+        (defineADeadFunction):
+
 2015-01-02  Anders Carlsson  <andersca@apple.com>
 
         Get rid of storage tracker layout tests
diff --git a/LayoutTests/js/regress-140033-expected.txt b/LayoutTests/js/regress-140033-expected.txt
new file mode 100644 (file)
index 0000000..d014d7b
--- /dev/null
@@ -0,0 +1,9 @@
+Regression test for https://webkit.org/b/140033. This test should run without crashing.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/regress-140033.html b/LayoutTests/js/regress-140033.html
new file mode 100644 (file)
index 0000000..786e0c7
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="script-tests/regress-140033.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/script-tests/regress-140033.js b/LayoutTests/js/script-tests/regress-140033.js
new file mode 100644 (file)
index 0000000..530f61a
--- /dev/null
@@ -0,0 +1,23 @@
+description(
+"Regression test for https://webkit.org/b/140033. This test should run without crashing."
+);
+
+function defineADeadFunction(x, y)
+{
+    var u;
+    var a = u;
+    var b = x;
+
+    if (x > 1500)
+        b -= y;
+
+    var unused = function() {
+        return 42;
+    }
+
+    return b;
+}
+
+var result = 0;
+for (var i = 1; i < 2000; i++)
+    result += defineADeadFunction(i, " ");
index b49f2b8..e83df86 100644 (file)
@@ -1,3 +1,19 @@
+2015-01-03  Michael Saboff  <msaboff@apple.com>
+
+        Crash in operationNewFunction when scrolling on Google+
+        https://bugs.webkit.org/show_bug.cgi?id=140033
+
+        Reviewed by Oliver Hunt.
+
+        In DFG code, the scope register can be eliminated because all uses have been
+        dead code eliminated.  In the case where one of the uses was creating a function
+        that is never used, the baseline code will still create the function.  If we OSR
+        exit to a path where that function gets created, check the scope register value
+        and set the new, but dead, function to undefined instead of creating a new function.
+
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_new_func_exp):
+
 2015-01-01  Yusuke Suzuki  <utatane.tea@gmail.com>
 
         String includes methods perform toString on searchString before toInt32 on a offset
index 030184a..e6daf8e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009, 2012, 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2012-2015 Apple Inc. All rights reserved.
  * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
  *
  * Redistribution and use in source and binary forms, with or without
@@ -1058,14 +1058,24 @@ void JIT::emit_op_new_func(Instruction* currentInstruction)
 
 void JIT::emit_op_new_func_exp(Instruction* currentInstruction)
 {
+    Jump notUndefinedScope;
     int dst = currentInstruction[1].u.operand;
 #if USE(JSVALUE64)
     emitGetVirtualRegister(currentInstruction[2].u.operand, regT0);
+    notUndefinedScope = branch64(NotEqual, regT0, TrustedImm64(JSValue::encode(jsUndefined())));
+    store64(TrustedImm64(JSValue::encode(jsUndefined())), Address(callFrameRegister, sizeof(Register) * dst));
 #else
     emitLoadPayload(currentInstruction[2].u.operand, regT0);
+    notUndefinedScope = branch32(NotEqual, tagFor(currentInstruction[2].u.operand), TrustedImm32(JSValue::UndefinedTag));
+    emitStore(dst, jsUndefined());
 #endif
+
+    Jump done = jump();
+    notUndefinedScope.link(this);
+
     FunctionExecutable* funcExpr = m_codeBlock->functionExpr(currentInstruction[3].u.operand);
     callOperation(operationNewFunction, dst, regT0, funcExpr);
+    done.link(this);
 }
 
 void JIT::emit_op_new_array(Instruction* currentInstruction)