Commit 6a58370c authored by bmeurer's avatar bmeurer Committed by Commit bot

[strong] Simplify (and sortof optimize) string addition for strong mode.

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}
parent 3b18958b
......@@ -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) \
......
......@@ -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.
......
......@@ -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);
......
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