Title: [146947] trunk
Revision
146947
Author
fpi...@apple.com
Date
2013-03-26 17:03:41 -0700 (Tue, 26 Mar 2013)

Log Message

REGRESSION: Sometimes, operations on proven strings ignore changes to the string prototype
https://bugs.webkit.org/show_bug.cgi?id=113353
<rdar://problem/13510778>

Source/_javascript_Core: 

Reviewed by Mark Hahnenberg and Geoffrey Garen.
        
ToString should call speculateStringObject() even if you know that it's a string object, since
it calls it to also get the watchpoint. Note that even with this change, if you do
Phantom(Check:StringObject:@a), it might get eliminated just because we proved that @a is a
string object (thereby eliminating the prototype watchpoint); that's fine since ToString is
MustGenerate and never decays to Phantom.

* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileToStringOnCell):
(JSC::DFG::SpeculativeJIT::speculateStringObject):
(JSC::DFG::SpeculativeJIT::speculateStringOrStringObject):
* dfg/DFGSpeculativeJIT.h:
(SpeculativeJIT):
(JSC::DFG::SpeculativeJIT::speculateStringObjectForStructure):

LayoutTests: 

Reviewed by Mark Hahnenberg and Geoffrey Garen.

* fast/js/jsc-test-list:
* fast/js/dfg-phantom-base-expected.txt: Added.
* fast/js/dfg-phantom-base.html: Added.
* fast/js/dfg-to-string-toString-becomes-bad-with-check-structure-expected.txt: Added.
* fast/js/dfg-to-string-toString-becomes-bad-with-check-structure.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (146946 => 146947)


--- trunk/LayoutTests/ChangeLog	2013-03-26 23:52:31 UTC (rev 146946)
+++ trunk/LayoutTests/ChangeLog	2013-03-27 00:03:41 UTC (rev 146947)
@@ -1,3 +1,17 @@
+2013-03-26  Filip Pizlo  <fpi...@apple.com>
+
+        REGRESSION: Sometimes, operations on proven strings ignore changes to the string prototype
+        https://bugs.webkit.org/show_bug.cgi?id=113353
+        <rdar://problem/13510778>
+
+        Reviewed by Mark Hahnenberg and Geoffrey Garen.
+
+        * fast/js/jsc-test-list:
+        * fast/js/dfg-phantom-base-expected.txt: Added.
+        * fast/js/dfg-phantom-base.html: Added.
+        * fast/js/dfg-to-string-toString-becomes-bad-with-check-structure-expected.txt: Added.
+        * fast/js/dfg-to-string-toString-becomes-bad-with-check-structure.html: Added.
+
 2013-03-26  Dean Jackson  <d...@apple.com>
 
         When a primary plugin is restarted, also start similar plugins

Added: trunk/LayoutTests/fast/js/dfg-phantom-base-expected.txt (0 => 146947)


--- trunk/LayoutTests/fast/js/dfg-phantom-base-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/js/dfg-phantom-base-expected.txt	2013-03-27 00:03:41 UTC (rev 146947)
@@ -0,0 +1,209 @@
+Tests that we use Phantom on the base of put_by_base correctly.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}}) is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/js/dfg-phantom-base.html (0 => 146947)


--- trunk/LayoutTests/fast/js/dfg-phantom-base.html	                        (rev 0)
+++ trunk/LayoutTests/fast/js/dfg-phantom-base.html	2013-03-27 00:03:41 UTC (rev 146947)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/fast/js/dfg-to-string-toString-becomes-bad-with-check-structure-expected.txt (0 => 146947)


--- trunk/LayoutTests/fast/js/dfg-to-string-toString-becomes-bad-with-check-structure-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/js/dfg-to-string-toString-becomes-bad-with-check-structure-expected.txt	2013-03-27 00:03:41 UTC (rev 146947)
@@ -0,0 +1,109 @@
+Tests that the DFG checks that the toString method didn't become bad even if the StringObject already had a CheckStructure.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "foo"
+PASS foo.call(new String("foo")) is "42"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/js/dfg-to-string-toString-becomes-bad-with-check-structure.html (0 => 146947)


--- trunk/LayoutTests/fast/js/dfg-to-string-toString-becomes-bad-with-check-structure.html	                        (rev 0)
+++ trunk/LayoutTests/fast/js/dfg-to-string-toString-becomes-bad-with-check-structure.html	2013-03-27 00:03:41 UTC (rev 146947)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>

Modified: trunk/LayoutTests/fast/js/jsc-test-list (146946 => 146947)


--- trunk/LayoutTests/fast/js/jsc-test-list	2013-03-26 23:52:31 UTC (rev 146946)
+++ trunk/LayoutTests/fast/js/jsc-test-list	2013-03-27 00:03:41 UTC (rev 146947)
@@ -184,6 +184,7 @@
 fast/js/dfg-obvious-constant-cfa
 fast/js/dfg-osr-entry-hoisted-clobbered-structure-check
 fast/js/dfg-other-branch
+fast/js/dfg-phantom-base
 fast/js/dfg-phantom-get-local
 fast/js/dfg-post-inc-then-exit
 fast/js/dfg-proto-access-inline-osr-exit
@@ -204,6 +205,7 @@
 fast/js/dfg-to-string-on-value
 fast/js/dfg-to-string-side-effect
 fast/js/dfg-to-string-side-effect-clobbers-toString
+fast/js/dfg-to-string-toString-becomes-bad-with-check-structure
 fast/js/dfg-to-string-toString-becomes-bad-with-dictionary-string-prototype
 fast/js/dfg-to-string-toString-becomes-bad
 fast/js/dfg-to-string-toString-in-string

Added: trunk/LayoutTests/fast/js/script-tests/dfg-phantom-base.js (0 => 146947)


--- trunk/LayoutTests/fast/js/script-tests/dfg-phantom-base.js	                        (rev 0)
+++ trunk/LayoutTests/fast/js/script-tests/dfg-phantom-base.js	2013-03-27 00:03:41 UTC (rev 146947)
@@ -0,0 +1,19 @@
+description(
+"Tests that we use Phantom on the base of put_by_base correctly."
+);
+
+function foo(o) {
+    var x = o;
+    var y = o.f;
+    if (y) {
+        o.g.h;
+        return !x;
+    }
+    
+    // Do things to ensure that the structure check on o is not hoisted.
+    return o + o + o + o + o;
+}
+
+for (var i = 0; i < 200; ++i)
+    shouldBe("foo(i < 190 ? {f:42, g:{h:3}} : {f:42, g:{}})", "false");
+

Added: trunk/LayoutTests/fast/js/script-tests/dfg-to-string-toString-becomes-bad-with-check-structure.js (0 => 146947)


--- trunk/LayoutTests/fast/js/script-tests/dfg-to-string-toString-becomes-bad-with-check-structure.js	                        (rev 0)
+++ trunk/LayoutTests/fast/js/script-tests/dfg-to-string-toString-becomes-bad-with-check-structure.js	2013-03-27 00:03:41 UTC (rev 146947)
@@ -0,0 +1,14 @@
+description(
+"Tests that the DFG checks that the toString method didn't become bad even if the StringObject already had a CheckStructure."
+);
+
+function foo() {
+    return String(this);
+}
+
+for (var i = 0; i < 100; ++i) {
+    if (i == 99)
+        String.prototype.toString = function() { return 42; }
+    shouldBe("foo.call(new String(\"foo\"))", i >= 99 ? "\"42\"" : "\"foo\"");
+}
+

Modified: trunk/Source/_javascript_Core/ChangeLog (146946 => 146947)


--- trunk/Source/_javascript_Core/ChangeLog	2013-03-26 23:52:31 UTC (rev 146946)
+++ trunk/Source/_javascript_Core/ChangeLog	2013-03-27 00:03:41 UTC (rev 146947)
@@ -1,3 +1,25 @@
+2013-03-26  Filip Pizlo  <fpi...@apple.com>
+
+        REGRESSION: Sometimes, operations on proven strings ignore changes to the string prototype
+        https://bugs.webkit.org/show_bug.cgi?id=113353
+        <rdar://problem/13510778>
+
+        Reviewed by Mark Hahnenberg and Geoffrey Garen.
+        
+        ToString should call speculateStringObject() even if you know that it's a string object, since
+        it calls it to also get the watchpoint. Note that even with this change, if you do
+        Phantom(Check:StringObject:@a), it might get eliminated just because we proved that @a is a
+        string object (thereby eliminating the prototype watchpoint); that's fine since ToString is
+        MustGenerate and never decays to Phantom.
+
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileToStringOnCell):
+        (JSC::DFG::SpeculativeJIT::speculateStringObject):
+        (JSC::DFG::SpeculativeJIT::speculateStringOrStringObject):
+        * dfg/DFGSpeculativeJIT.h:
+        (SpeculativeJIT):
+        (JSC::DFG::SpeculativeJIT::speculateStringObjectForStructure):
+
 2013-03-26  Mark Hahnenberg  <mhahnenb...@apple.com>
 
         REGRESSION(r144131): It made fast/js/regress/string-repeat-arith.html assert on 32 bit

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (146946 => 146947)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2013-03-26 23:52:31 UTC (rev 146946)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2013-03-27 00:03:41 UTC (rev 146947)
@@ -3981,10 +3981,8 @@
         GPRTemporary result(this);
         GPRReg resultGPR = result.gpr();
         
-        if (!m_state.forNode(node->child1()).m_currentKnownStructure.isSubsetOf(StructureSet(m_jit.globalObjectFor(node->codeOrigin)->stringObjectStructure()))) {
-            speculateStringObject(op1GPR);
-            m_state.forNode(node->child1()).filter(SpecStringObject);
-        }
+        speculateStringObject(node->child1(), op1GPR);
+        m_state.forNode(node->child1()).filter(SpecStringObject);
         m_jit.loadPtr(JITCompiler::Address(op1GPR, JSWrapperObject::internalValueCellOffset()), resultGPR);
         cellResult(resultGPR, node);
         break;
@@ -3998,7 +3996,7 @@
         JITCompiler::Jump isString = m_jit.branchPtr(
             JITCompiler::Equal, resultGPR, TrustedImmPtr(m_jit.globalData()->stringStructure.get()));
         
-        speculateStringObjectForStructure(resultGPR);
+        speculateStringObjectForStructure(node->child1(), resultGPR);
         
         m_jit.loadPtr(JITCompiler::Address(op1GPR, JSWrapperObject::internalValueCellOffset()), resultGPR);
         
@@ -4212,9 +4210,9 @@
             MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
 }
 
-void SpeculativeJIT::speculateStringObject(GPRReg gpr)
+void SpeculativeJIT::speculateStringObject(Edge edge, GPRReg gpr)
 {
-    speculateStringObjectForStructure(JITCompiler::Address(gpr, JSCell::structureOffset()));
+    speculateStringObjectForStructure(edge, JITCompiler::Address(gpr, JSCell::structureOffset()));
 }
 
 void SpeculativeJIT::speculateStringObject(Edge edge)
@@ -4227,7 +4225,7 @@
     if (!needsTypeCheck(edge, SpecStringObject))
         return;
     
-    speculateStringObject(gpr);
+    speculateStringObject(edge, gpr);
     m_state.forNode(edge).filter(SpecStringObject);
 }
 
@@ -4249,7 +4247,7 @@
     JITCompiler::Jump isString = m_jit.branchPtr(
         JITCompiler::Equal, structureGPR, TrustedImmPtr(m_jit.globalData()->stringStructure.get()));
     
-    speculateStringObjectForStructure(structureGPR);
+    speculateStringObjectForStructure(edge, structureGPR);
     
     isString.link(&m_jit);
     

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (146946 => 146947)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2013-03-26 23:52:31 UTC (rev 146946)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2013-03-27 00:03:41 UTC (rev 146947)
@@ -2260,8 +2260,8 @@
     void speculateObjectOrOther(Edge);
     void speculateString(Edge);
     template<typename StructureLocationType>
-    void speculateStringObjectForStructure(StructureLocationType);
-    void speculateStringObject(GPRReg);
+    void speculateStringObjectForStructure(Edge, StructureLocationType);
+    void speculateStringObject(Edge, GPRReg);
     void speculateStringObject(Edge);
     void speculateStringOrStringObject(Edge);
     void speculateNotCell(Edge);
@@ -2991,17 +2991,19 @@
 };
 
 template<typename StructureLocationType>
-void SpeculativeJIT::speculateStringObjectForStructure(StructureLocationType structureLocation)
+void SpeculativeJIT::speculateStringObjectForStructure(Edge edge, StructureLocationType structureLocation)
 {
     Structure* stringObjectStructure =
         m_jit.globalObjectFor(m_currentNode->codeOrigin)->stringObjectStructure();
     Structure* stringPrototypeStructure = stringObjectStructure->storedPrototype().asCell()->structure();
     ASSERT(stringPrototypeStructure->transitionWatchpointSetIsStillValid());
     
-    speculationCheck(
-        NotStringObject, JSValueRegs(), 0,
-        m_jit.branchPtr(
-            JITCompiler::NotEqual, structureLocation, TrustedImmPtr(stringObjectStructure)));
+    if (!m_state.forNode(edge).m_currentKnownStructure.isSubsetOf(StructureSet(m_jit.globalObjectFor(m_currentNode->codeOrigin)->stringObjectStructure()))) {
+        speculationCheck(
+            NotStringObject, JSValueRegs(), 0,
+            m_jit.branchPtr(
+                JITCompiler::NotEqual, structureLocation, TrustedImmPtr(stringObjectStructure)));
+    }
     stringPrototypeStructure->addTransitionWatchpoint(speculationWatchpoint(NotStringObject));
 }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to