Ensure consistent order of evaluation in LLInt slow paths
https://bugs.webkit.org/show_bug.cgi?id=88409

Reviewed by Geoffrey Garen.

* llint/LLIntSlowPaths.cpp:
(slow_path_mul)
(slow_path_sub)
(slow_path_div)
(slow_path_mod)
(slow_path_lshift)
(slow_path_rshift)
(slow_path_urshift)
(slow_path_bitand)
(slow_path_bitor)
(slow_path_bitxor): Avoid calling toNumber, toInt32, or toUInt32
multiple times without intervening sequence points.  Fixes
fast/js/exception-sequencing-binops.html with GCC 4.7 on x86-64
Linux, which reordered evaluation of the arguments to fmod.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@119602 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 3558be9..1865c2d 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,5 +1,27 @@
 2012-06-06  Andy Wingo  <wingo@igalia.com>
 
+        Ensure consistent order of evaluation in LLInt slow paths
+        https://bugs.webkit.org/show_bug.cgi?id=88409
+
+        Reviewed by Geoffrey Garen.
+
+        * llint/LLIntSlowPaths.cpp:
+        (slow_path_mul)
+        (slow_path_sub)
+        (slow_path_div)
+        (slow_path_mod)
+        (slow_path_lshift)
+        (slow_path_rshift)
+        (slow_path_urshift)
+        (slow_path_bitand)
+        (slow_path_bitor)
+        (slow_path_bitxor): Avoid calling toNumber, toInt32, or toUInt32
+        multiple times without intervening sequence points.  Fixes
+        fast/js/exception-sequencing-binops.html with GCC 4.7 on x86-64
+        Linux, which reordered evaluation of the arguments to fmod.
+
+2012-06-06  Andy Wingo  <wingo@igalia.com>
+
         [GTK] Enable the LLInt
         https://bugs.webkit.org/show_bug.cgi?id=88315
 
diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
index ac567bd..7133b0d 100644
--- a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
+++ b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
@@ -621,64 +621,88 @@
     LLINT_RETURN(jsAddSlowCase(exec, v1, v2));
 }
 
+// The following arithmetic and bitwise operations need to be sure to run
+// toNumber() on their operands in order.  (A call to toNumber() is idempotent
+// if an exception is already set on the ExecState.)
+
 LLINT_SLOW_PATH_DECL(slow_path_mul)
 {
     LLINT_BEGIN();
-    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec) * LLINT_OP_C(3).jsValue().toNumber(exec)));
+    double a = LLINT_OP_C(2).jsValue().toNumber(exec);
+    double b = LLINT_OP_C(3).jsValue().toNumber(exec);
+    LLINT_RETURN(jsNumber(a * b));
 }
 
 LLINT_SLOW_PATH_DECL(slow_path_sub)
 {
     LLINT_BEGIN();
-    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec) - LLINT_OP_C(3).jsValue().toNumber(exec)));
+    double a = LLINT_OP_C(2).jsValue().toNumber(exec);
+    double b = LLINT_OP_C(3).jsValue().toNumber(exec);
+    LLINT_RETURN(jsNumber(a - b));
 }
 
 LLINT_SLOW_PATH_DECL(slow_path_div)
 {
     LLINT_BEGIN();
-    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec) / LLINT_OP_C(3).jsValue().toNumber(exec)));
+    double a = LLINT_OP_C(2).jsValue().toNumber(exec);
+    double b = LLINT_OP_C(3).jsValue().toNumber(exec);
+    LLINT_RETURN(jsNumber(a / b));
 }
 
 LLINT_SLOW_PATH_DECL(slow_path_mod)
 {
     LLINT_BEGIN();
-    LLINT_RETURN(jsNumber(fmod(LLINT_OP_C(2).jsValue().toNumber(exec), LLINT_OP_C(3).jsValue().toNumber(exec))));
+    double a = LLINT_OP_C(2).jsValue().toNumber(exec);
+    double b = LLINT_OP_C(3).jsValue().toNumber(exec);
+    LLINT_RETURN(jsNumber(fmod(a, b)));
 }
 
 LLINT_SLOW_PATH_DECL(slow_path_lshift)
 {
     LLINT_BEGIN();
-    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) << (LLINT_OP_C(3).jsValue().toUInt32(exec) & 31)));
+    int32_t a = LLINT_OP_C(2).jsValue().toInt32(exec);
+    uint32_t b = LLINT_OP_C(3).jsValue().toUInt32(exec);
+    LLINT_RETURN(jsNumber(a << (b & 31)));
 }
 
 LLINT_SLOW_PATH_DECL(slow_path_rshift)
 {
     LLINT_BEGIN();
-    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) >> (LLINT_OP_C(3).jsValue().toUInt32(exec) & 31)));
+    int32_t a = LLINT_OP_C(2).jsValue().toInt32(exec);
+    uint32_t b = LLINT_OP_C(3).jsValue().toUInt32(exec);
+    LLINT_RETURN(jsNumber(a >> (b & 31)));
 }
 
 LLINT_SLOW_PATH_DECL(slow_path_urshift)
 {
     LLINT_BEGIN();
-    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toUInt32(exec) >> (LLINT_OP_C(3).jsValue().toUInt32(exec) & 31)));
+    uint32_t a = LLINT_OP_C(2).jsValue().toUInt32(exec);
+    uint32_t b = LLINT_OP_C(3).jsValue().toUInt32(exec);
+    LLINT_RETURN(jsNumber(a >> (b & 31)));
 }
 
 LLINT_SLOW_PATH_DECL(slow_path_bitand)
 {
     LLINT_BEGIN();
-    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) & LLINT_OP_C(3).jsValue().toInt32(exec)));
+    int32_t a = LLINT_OP_C(2).jsValue().toInt32(exec);
+    int32_t b = LLINT_OP_C(3).jsValue().toInt32(exec);
+    LLINT_RETURN(jsNumber(a & b));
 }
 
 LLINT_SLOW_PATH_DECL(slow_path_bitor)
 {
     LLINT_BEGIN();
-    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) | LLINT_OP_C(3).jsValue().toInt32(exec)));
+    int32_t a = LLINT_OP_C(2).jsValue().toInt32(exec);
+    int32_t b = LLINT_OP_C(3).jsValue().toInt32(exec);
+    LLINT_RETURN(jsNumber(a | b));
 }
 
 LLINT_SLOW_PATH_DECL(slow_path_bitxor)
 {
     LLINT_BEGIN();
-    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) ^ LLINT_OP_C(3).jsValue().toInt32(exec)));
+    int32_t a = LLINT_OP_C(2).jsValue().toInt32(exec);
+    int32_t b = LLINT_OP_C(3).jsValue().toInt32(exec);
+    LLINT_RETURN(jsNumber(a ^ b));
 }
 
 LLINT_SLOW_PATH_DECL(slow_path_check_has_instance)