Commit f0d8277b authored by fpizlo@apple.com's avatar fpizlo@apple.com
Browse files

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/JavaScriptCore: 

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.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@146947 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent cf69686e
2013-03-26 Filip Pizlo <fpizlo@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 <dino@apple.com>
 
When a primary plugin is restarted, also start similar plugins
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
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="resources/js-test-pre.js"></script>
</head>
<body>
<script src="script-tests/dfg-phantom-base.js"></script>
<script src="resources/js-test-post.js"></script>
</body>
</html>
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
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="resources/js-test-pre.js"></script>
</head>
<body>
<script src="script-tests/dfg-to-string-toString-becomes-bad-with-check-structure.js"></script>
<script src="resources/js-test-post.js"></script>
</body>
</html>
......@@ -184,6 +184,7 @@ fast/js/dfg-negative-array-index
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-cell
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
......
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");
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\"");
}
2013-03-26 Filip Pizlo <fpizlo@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 <mhahnenberg@apple.com>
 
REGRESSION(r144131): It made fast/js/regress/string-repeat-arith.html assert on 32 bit
......
......@@ -3981,10 +3981,8 @@ void SpeculativeJIT::compileToStringOnCell(Node* node)
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 @@ void SpeculativeJIT::compileToStringOnCell(Node* node)
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 @@ void SpeculativeJIT::speculateString(Edge edge)
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 @@ void SpeculativeJIT::speculateStringObject(Edge edge)
if (!needsTypeCheck(edge, SpecStringObject))
return;
speculateStringObject(gpr);
speculateStringObject(edge, gpr);
m_state.forNode(edge).filter(SpecStringObject);
}
......@@ -4249,7 +4247,7 @@ void SpeculativeJIT::speculateStringOrStringObject(Edge edge)
JITCompiler::Jump isString = m_jit.branchPtr(
JITCompiler::Equal, structureGPR, TrustedImmPtr(m_jit.globalData()->stringStructure.get()));
speculateStringObjectForStructure(structureGPR);
speculateStringObjectForStructure(edge, structureGPR);
isString.link(&m_jit);
......
......@@ -2260,8 +2260,8 @@ public:
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 @@ private:
};
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));
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment