<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://bugs.webkit.org/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.4.1"
          urlbase="https://bugs.webkit.org/"
          
          maintainer="admin@webkit.org"
>

    <bug>
          <bug_id>86330</bug_id>
          
          <creation_ts>2012-05-13 20:48:35 -0700</creation_ts>
          <short_desc>DFG performs incorrect constant folding on double-to-uint32 conversion in Uint32Array PutByVal</short_desc>
          <delta_ts>2012-05-14 09:54:41 -0700</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>WebKit</product>
          <component>JavaScriptCore</component>
          <version>528+ (Nightly build)</version>
          <rep_platform>Mac (Intel)</rep_platform>
          <op_sys>OS X 10.7</op_sys>
          <bug_status>RESOLVED</bug_status>
          <resolution>FIXED</resolution>
          
          
          <bug_file_loc>http://felixcloutier.com/documents/jsx-webkit/mock.xhtml</bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords>InRadar</keywords>
          <priority>P2</priority>
          <bug_severity>Normal</bug_severity>
          <target_milestone>---</target_milestone>
          
          
          <everconfirmed>0</everconfirmed>
          <reporter name="Félix Cloutier">felixcca</reporter>
          <assigned_to name="Nobody">webkit-unassigned</assigned_to>
          <cc>fpizlo</cc>
    
    <cc>oliver</cc>
          

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>622623</commentid>
    <comment_count>0</comment_count>
    <who name="Félix Cloutier">felixcca</who>
    <bug_when>2012-05-13 20:48:35 -0700</bug_when>
    <thetext>Using r116899.

I hope you won&apos;t hate me too much for this bug report. I&apos;ve been told on #webkit to report it anyways.

I&apos;m working on a Playstation emulator written in Javascript. It generates Javascript code from MIPS instructions and executes them; but when the debugger is not attached, the execution goes wrong. At some point, the value 0x80054664 should be assigned to element #31 of a Uint32Array (called &quot;this.gpr&quot;) through a very simple statement:

    this.gpr[31] = 0x8005465c;

But the statement is either not executed or does not write the correct value, because instead I get this.gpr[31] == 0x80000000, which is the value it had before the assignment.

When the code is run with the Javascript debugger enabled, it does write 0x80054664, so the problem seems to be with the &quot;production&quot; JS compiler.

Also, when this.gpr[31] is not a typed array element (like if I make this.gpr an object with getters and setters for indices 0-33), everything goes right.

The bug is also resilient to mocking. Setting up the state of the emulator to something that simply &quot;looks like&quot; the conditions in which the bug happens (mocking the GPR state and the function generated) doesn&apos;t trigger it. I would very much like to give you a complete test case, but for this I would need to send a PlayStation BIOS, and I can&apos;t do that.

Still, I&apos;ve joined the URL of the mock, so you can get an idea of what&apos;s going on. The generated Javascript code that doesn&apos;t work under obscure circumstances can be found in mock.js (the &quot;psx.memory.compiled.compiled[0x8005465c]&quot; part). For all practical purposes, the only part of this function that should be executed is from line 230 to line 233.

If there&apos;s any way I could be more helpful, please tell me how, I&apos;ll gladly do it.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>622646</commentid>
    <comment_count>1</comment_count>
    <who name="Filip Pizlo">fpizlo</who>
    <bug_when>2012-05-13 22:13:57 -0700</bug_when>
    <thetext>(In reply to comment #0)
&gt; Using r116899.
&gt; 
&gt; I hope you won&apos;t hate me too much for this bug report. I&apos;ve been told on #webkit to report it anyways.
&gt; 
&gt; I&apos;m working on a Playstation emulator written in Javascript. It generates Javascript code from MIPS instructions and executes them; but when the debugger is not attached, the execution goes wrong. At some point, the value 0x80054664 should be assigned to element #31 of a Uint32Array (called &quot;this.gpr&quot;) through a very simple statement:
&gt; 
&gt;     this.gpr[31] = 0x8005465c;
&gt; 
&gt; But the statement is either not executed or does not write the correct value, because instead I get this.gpr[31] == 0x80000000, which is the value it had before the assignment.
&gt; 
&gt; When the code is run with the Javascript debugger enabled, it does write 0x80054664, so the problem seems to be with the &quot;production&quot; JS compiler.
&gt; 
&gt; Also, when this.gpr[31] is not a typed array element (like if I make this.gpr an object with getters and setters for indices 0-33), everything goes right.
&gt; 
&gt; The bug is also resilient to mocking. Setting up the state of the emulator to something that simply &quot;looks like&quot; the conditions in which the bug happens (mocking the GPR state and the function generated) doesn&apos;t trigger it. I would very much like to give you a complete test case, but for this I would need to send a PlayStation BIOS, and I can&apos;t do that.
&gt; 
&gt; Still, I&apos;ve joined the URL of the mock, so you can get an idea of what&apos;s going on. The generated Javascript code that doesn&apos;t work under obscure circumstances can be found in mock.js (the &quot;psx.memory.compiled.compiled[0x8005465c]&quot; part). For all practical purposes, the only part of this function that should be executed is from line 230 to line 233.
&gt; 
&gt; If there&apos;s any way I could be more helpful, please tell me how, I&apos;ll gladly do it.

Hi Felix!  Thanks for the detailed bug report!  I think I just found the bug.  In dfg/DFGSpeculativeJIT.cpp, there is the following code:

        JSValue jsValue = valueOfJSConstant(valueUse.index());
        if (!jsValue.isNumber()) {
            terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
            noResult(m_compileIndex);
            return;
        }
        double d = jsValue.asNumber();
        if (rounding == ClampRounding) {
            ASSERT(elementSize == 1);
            d = clampDoubleToByte(d);
        }
        GPRTemporary scratch(this);
        GPRReg scratchReg = scratch.gpr();
        m_jit.move(Imm32(static_cast&lt;int&gt;(d)), scratchReg);
        value.adopt(scratch);
        valueGPR = scratchReg;

This is in the compilePutByValForIntTypedArray() method.  I believe that the offending line is &quot;m_jit.move(Imm32(static_cast&lt;int&gt;(d)), scratchReg);&quot;.  Basically, we&apos;re doing a C++ cast from a double value (we will treat 0x8005465c as a double because it is outside the int32 range) to an int.  But C++ casting, at least on most common architectures (x86), implies that double values outside the int32 range result in 0x80000000, which is a special signaling value indicating that the cast overflowed.

I believe that the correct fix is to change &quot;static_cast&lt;int&gt;(d)&quot; to &quot;toInt32(d)&quot;.

But to confirm that this is really the problem, can you tell me if the following hold true:

1) The real code (not the mocked version) does not have a switch statement.  Currently our optimizing compiler does not yet support switch statements.  This might be the reason why your mocked code does not trigger the bug.

2) The real code does indeed store a constant into the UInt32Array, as opposed to storing a non-constant value.  In particular, the code does this:

this.gpr[31] = 0x8005465c;

and not this:

var x = 0x8005465c;
... bunch of stuff
this.gpr[31] = x;

Does that sound about right?

I&apos;m working on a reduced test case and a fix now, assuming that my guess is right.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>622648</commentid>
    <comment_count>2</comment_count>
      <attachid>141637</attachid>
    <who name="Filip Pizlo">fpizlo</who>
    <bug_when>2012-05-13 22:21:26 -0700</bug_when>
    <thetext>Created attachment 141637
reduced test case

This ought to fail somewhere around iteration 70 in tip of tree.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>622652</commentid>
    <comment_count>3</comment_count>
      <attachid>141638</attachid>
    <who name="Filip Pizlo">fpizlo</who>
    <bug_when>2012-05-13 22:24:46 -0700</bug_when>
    <thetext>Created attachment 141638
the patch

This fixes the reduced version of the bug that I found.

Felix, can you check if this does the trick for you?  It may be that you&apos;ve uncovered more than one bug!</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>622656</commentid>
    <comment_count>4</comment_count>
    <who name="Filip Pizlo">fpizlo</who>
    <bug_when>2012-05-13 22:29:46 -0700</bug_when>
    <thetext>&lt;rdar://problem/11442986&gt;</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>622669</commentid>
    <comment_count>5</comment_count>
      <attachid>141638</attachid>
    <who name="Darin Adler">darin</who>
    <bug_when>2012-05-13 22:49:16 -0700</bug_when>
    <thetext>Comment on attachment 141638
the patch

View in context: https://bugs.webkit.org/attachment.cgi?id=141638&amp;action=review

Can you add a regression test for this? Normally we don’t land fixes without tests.

&gt; Source/JavaScriptCore/ChangeLog:9
&gt; +        static_cast&lt;int&gt;(d) is wrong, since JS semantics require us to use toInt32(d).

Sure would be nice to be more specific here about how close static_cast&lt;int&gt; was or wasn’t, such as what values it would give a wrong value for.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>622670</commentid>
    <comment_count>6</comment_count>
    <who name="Filip Pizlo">fpizlo</who>
    <bug_when>2012-05-13 22:55:45 -0700</bug_when>
    <thetext>(In reply to comment #5)
&gt; (From update of attachment 141638 [details])
&gt; View in context: https://bugs.webkit.org/attachment.cgi?id=141638&amp;action=review
&gt; 
&gt; Can you add a regression test for this? Normally we don’t land fixes without tests.

Of course, I will LayoutTest-ify the attached test case.

&gt; 
&gt; &gt; Source/JavaScriptCore/ChangeLog:9
&gt; &gt; +        static_cast&lt;int&gt;(d) is wrong, since JS semantics require us to use toInt32(d).
&gt; 
&gt; Sure would be nice to be more specific here about how close static_cast&lt;int&gt; was or wasn’t, such as what values it would give a wrong value for.

Fixed the ChangeLog.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>622701</commentid>
    <comment_count>7</comment_count>
    <who name="Filip Pizlo">fpizlo</who>
    <bug_when>2012-05-13 23:47:47 -0700</bug_when>
    <thetext>Landed in http://trac.webkit.org/changeset/116925

Felix, please reopen or file a new bug if this does not fix the issue.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>622998</commentid>
    <comment_count>8</comment_count>
    <who name="Félix Cloutier">felixcca</who>
    <bug_when>2012-05-14 08:20:24 -0700</bug_when>
    <thetext>(In reply to comment #7)
&gt; Landed in http://trac.webkit.org/changeset/116925
&gt; 
&gt; Felix, please reopen or file a new bug if this does not fix the issue.

I&apos;m at work right now, so I&apos;ll check when I get home for lunch. In reply to the first message, though, the function in mock.js *is* the actual generated code: it&apos;s really assigning a constant, but the switch is really there.

Anyways, I&apos;ll tell you if it did the trick.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>623051</commentid>
    <comment_count>9</comment_count>
    <who name="Félix Cloutier">felixcca</who>
    <bug_when>2012-05-14 09:54:41 -0700</bug_when>
    <thetext>Yup, that fixed it. Thanks!</thetext>
  </long_desc>
      
          <attachment
              isobsolete="0"
              ispatch="0"
              isprivate="0"
          >
            <attachid>141637</attachid>
            <date>2012-05-13 22:21:26 -0700</date>
            <delta_ts>2012-05-13 22:21:26 -0700</delta_ts>
            <desc>reduced test case</desc>
            <filename>reduced_case.js</filename>
            <type>text/plain</type>
            <size>202</size>
            <attacher name="Filip Pizlo">fpizlo</attacher>
            
              <data encoding="base64">ZnVuY3Rpb24gZm9vKGEpIHsKICAgIGFbMF0gPSAweDgwMDU0NjVjOwp9Cgp2YXIgYXJyYXkgPSBu
ZXcgVWludDMyQXJyYXkoMSk7Cgpmb3IgKHZhciBpID0gMDsgaSA8IDEwMDA7ICsraSkgewogICAg
Zm9vKGFycmF5KTsKICAgIGlmIChhcnJheVswXSAhPSAweDgwMDU0NjVjKQogICAgICAgIHRocm93
ICJFcnJvciBvbiBpdGVyYXRpb24gIiArIGk7Cn0KCg==
</data>

          </attachment>
          <attachment
              isobsolete="0"
              ispatch="1"
              isprivate="0"
          >
            <attachid>141638</attachid>
            <date>2012-05-13 22:24:46 -0700</date>
            <delta_ts>2012-05-13 22:49:16 -0700</delta_ts>
            <desc>the patch</desc>
            <filename>fix_uint32array_store_patch_1.diff</filename>
            <type>text/plain</type>
            <size>1437</size>
            <attacher name="Filip Pizlo">fpizlo</attacher>
            
              <data encoding="base64">SW5kZXg6IFNvdXJjZS9KYXZhU2NyaXB0Q29yZS9DaGFuZ2VMb2cKPT09PT09PT09PT09PT09PT09
PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQotLS0gU291
cmNlL0phdmFTY3JpcHRDb3JlL0NoYW5nZUxvZwkocmV2aXNpb24gMTE2OTE1KQorKysgU291cmNl
L0phdmFTY3JpcHRDb3JlL0NoYW5nZUxvZwkod29ya2luZyBjb3B5KQpAQCAtMSwzICsxLDE2IEBA
CisyMDEyLTA1LTEzICBGaWxpcCBQaXpsbyAgPGZwaXpsb0BhcHBsZS5jb20+CisKKyAgICAgICAg
REZHIHBlcmZvcm1zIGluY29ycmVjdCBjb25zdGFudCBmb2xkaW5nIG9uIGRvdWJsZS10by11aW50
MzIgY29udmVyc2lvbiBpbgorICAgICAgICBVaW50MzJBcnJheSBQdXRCeVZhbAorICAgICAgICBo
dHRwczovL2J1Z3Mud2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9ODYzMzAKKworICAgICAgICBS
ZXZpZXdlZCBieSBOT0JPRFkgKE9PUFMhKS4KKyAgICAgICAgCisgICAgICAgIHN0YXRpY19jYXN0
PGludD4oZCkgaXMgd3JvbmcsIHNpbmNlIEpTIHNlbWFudGljcyByZXF1aXJlIHVzIHRvIHVzZSB0
b0ludDMyKGQpLgorCisgICAgICAgICogZGZnL0RGR1NwZWN1bGF0aXZlSklULmNwcDoKKyAgICAg
ICAgKEpTQzo6REZHOjpTcGVjdWxhdGl2ZUpJVDo6Y29tcGlsZVB1dEJ5VmFsRm9ySW50VHlwZWRB
cnJheSk6CisKIDIwMTItMDUtMTEgIEdhdmluIEJhcnJhY2xvdWdoICA8YmFycmFjbG91Z2hAYXBw
bGUuY29tPgogCiAgICAgICAgIEludHJvZHVjZSBQcm9wZXJ0eU5hbWUgY2xhc3MKSW5kZXg6IFNv
dXJjZS9KYXZhU2NyaXB0Q29yZS9kZmcvREZHU3BlY3VsYXRpdmVKSVQuY3BwCj09PT09PT09PT09
PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0K
LS0tIFNvdXJjZS9KYXZhU2NyaXB0Q29yZS9kZmcvREZHU3BlY3VsYXRpdmVKSVQuY3BwCShyZXZp
c2lvbiAxMTYwMzMpCisrKyBTb3VyY2UvSmF2YVNjcmlwdENvcmUvZGZnL0RGR1NwZWN1bGF0aXZl
SklULmNwcAkod29ya2luZyBjb3B5KQpAQCAtMTk3NCw3ICsxOTc0LDcgQEAgdm9pZCBTcGVjdWxh
dGl2ZUpJVDo6Y29tcGlsZVB1dEJ5VmFsRm9ySQogICAgICAgICB9CiAgICAgICAgIEdQUlRlbXBv
cmFyeSBzY3JhdGNoKHRoaXMpOwogICAgICAgICBHUFJSZWcgc2NyYXRjaFJlZyA9IHNjcmF0Y2gu
Z3ByKCk7Ci0gICAgICAgIG1faml0Lm1vdmUoSW1tMzIoc3RhdGljX2Nhc3Q8aW50PihkKSksIHNj
cmF0Y2hSZWcpOworICAgICAgICBtX2ppdC5tb3ZlKEltbTMyKHRvSW50MzIoZCkpLCBzY3JhdGNo
UmVnKTsKICAgICAgICAgdmFsdWUuYWRvcHQoc2NyYXRjaCk7CiAgICAgICAgIHZhbHVlR1BSID0g
c2NyYXRjaFJlZzsKICAgICB9IGVsc2UgaWYgKGF0KHZhbHVlVXNlKS5zaG91bGRTcGVjdWxhdGVJ
bnRlZ2VyKCkpIHsK
</data>
<flag name="review"
          id="147802"
          type_id="1"
          status="+"
          setter="darin"
    />
          </attachment>
      

    </bug>

</bugzilla>