[strong] Simplify (and sortof optimize) string addition for strong mode.
authorbmeurer <bmeurer@chromium.org>
Thu, 13 Aug 2015 07:05:07 +0000 (00:05 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 13 Aug 2015 07:05:18 +0000 (07:05 +0000)
In strong mode, whenever either operand to an addition is a string, both
must be strings, so we can just use a simple string map check instead of
the STRING_ADD_LEFT / STRING_ADD_RIGHT machinery, which tries to do sloppy
and strict mode conversions before giving up.

R=jarin@chromium.org

Review URL: https://codereview.chromium.org/1287203002

Cr-Commit-Position: refs/heads/master@{#30146}

src/builtins.h
src/hydrogen.cc
src/runtime.js

index 212ad89..8ced3e3 100644 (file)
@@ -186,9 +186,7 @@ enum BuiltinExtraArguments {
   V(TO_STRING, 0)                          \
   V(TO_NAME, 0)                            \
   V(STRING_ADD_LEFT, 1)                    \
-  V(STRING_ADD_LEFT_STRONG, 1)             \
   V(STRING_ADD_RIGHT, 1)                   \
-  V(STRING_ADD_RIGHT_STRONG, 1)            \
   V(APPLY_PREPARE, 1)                      \
   V(REFLECT_APPLY_PREPARE, 1)              \
   V(REFLECT_CONSTRUCT_PREPARE, 2)          \
index 559eca6..9b2a2f6 100644 (file)
@@ -10903,40 +10903,43 @@ HValue* HGraphBuilder::BuildBinaryOperation(
   // Special case for string addition here.
   if (op == Token::ADD &&
       (left_type->Is(Type::String()) || right_type->Is(Type::String()))) {
-    // Validate type feedback for left argument.
-    if (left_type->Is(Type::String())) {
+    if (is_strong(strength)) {
+      // In strong mode, if the one side of an addition is a string,
+      // the other side must be a string too.
       left = BuildCheckString(left);
-    }
-
-    // Validate type feedback for right argument.
-    if (right_type->Is(Type::String())) {
       right = BuildCheckString(right);
-    }
+    } else {
+      // Validate type feedback for left argument.
+      if (left_type->Is(Type::String())) {
+        left = BuildCheckString(left);
+      }
 
-    // Convert left argument as necessary.
-    if (left_type->Is(Type::Number()) && !is_strong(strength)) {
-      DCHECK(right_type->Is(Type::String()));
-      left = BuildNumberToString(left, left_type);
-    } else if (!left_type->Is(Type::String())) {
-      DCHECK(right_type->Is(Type::String()));
-      HValue* function = AddLoadJSBuiltin(
-          is_strong(strength) ? Builtins::STRING_ADD_RIGHT_STRONG
-                              : Builtins::STRING_ADD_RIGHT);
-      Add<HPushArguments>(left, right);
-      return AddUncasted<HInvokeFunction>(function, 2);
-    }
-
-    // Convert right argument as necessary.
-    if (right_type->Is(Type::Number()) && !is_strong(strength)) {
-      DCHECK(left_type->Is(Type::String()));
-      right = BuildNumberToString(right, right_type);
-    } else if (!right_type->Is(Type::String())) {
-      DCHECK(left_type->Is(Type::String()));
-      HValue* function = AddLoadJSBuiltin(is_strong(strength)
-                                              ? Builtins::STRING_ADD_LEFT_STRONG
-                                              : Builtins::STRING_ADD_LEFT);
-      Add<HPushArguments>(left, right);
-      return AddUncasted<HInvokeFunction>(function, 2);
+      // Validate type feedback for right argument.
+      if (right_type->Is(Type::String())) {
+        right = BuildCheckString(right);
+      }
+
+      // Convert left argument as necessary.
+      if (left_type->Is(Type::Number())) {
+        DCHECK(right_type->Is(Type::String()));
+        left = BuildNumberToString(left, left_type);
+      } else if (!left_type->Is(Type::String())) {
+        DCHECK(right_type->Is(Type::String()));
+        HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_RIGHT);
+        Add<HPushArguments>(left, right);
+        return AddUncasted<HInvokeFunction>(function, 2);
+      }
+
+      // Convert right argument as necessary.
+      if (right_type->Is(Type::Number())) {
+        DCHECK(left_type->Is(Type::String()));
+        right = BuildNumberToString(right, right_type);
+      } else if (!right_type->Is(Type::String())) {
+        DCHECK(left_type->Is(Type::String()));
+        HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT);
+        Add<HPushArguments>(left, right);
+        return AddUncasted<HInvokeFunction>(function, 2);
+      }
     }
 
     // Fast paths for empty constant strings.
index a120d96..e82d25e 100644 (file)
@@ -23,9 +23,7 @@ var COMPARE_STRONG;
 var ADD;
 var ADD_STRONG;
 var STRING_ADD_LEFT;
-var STRING_ADD_LEFT_STRONG;
 var STRING_ADD_RIGHT;
-var STRING_ADD_RIGHT_STRONG;
 var SUB;
 var SUB_STRONG;
 var MUL;
@@ -262,15 +260,6 @@ STRING_ADD_LEFT = function STRING_ADD_LEFT(y) {
 }
 
 
-// Left operand (this) is already a string.
-STRING_ADD_LEFT_STRONG = function STRING_ADD_LEFT_STRONG(y) {
-  if (IS_STRING(y)) {
-    return %_StringAdd(this, y);
-  }
-  throw %MakeTypeError(kStrongImplicitConversion);
-}
-
-
 // Right operand (y) is already a string.
 STRING_ADD_RIGHT = function STRING_ADD_RIGHT(y) {
   var x = this;
@@ -287,15 +276,6 @@ STRING_ADD_RIGHT = function STRING_ADD_RIGHT(y) {
 }
 
 
-// Right operand (y) is already a string.
-STRING_ADD_RIGHT_STRONG = function STRING_ADD_RIGHT_STRONG(y) {
-  if (IS_STRING(this)) {
-    return %_StringAdd(this, y);
-  }
-  throw %MakeTypeError(kStrongImplicitConversion);
-}
-
-
 // ECMA-262, section 11.6.2, page 50.
 SUB = function SUB(y) {
   var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this);