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 { ...@@ -186,9 +186,7 @@ enum BuiltinExtraArguments {
V(TO_STRING, 0) \ V(TO_STRING, 0) \
V(TO_NAME, 0) \ V(TO_NAME, 0) \
V(STRING_ADD_LEFT, 1) \ V(STRING_ADD_LEFT, 1) \
V(STRING_ADD_LEFT_STRONG, 1) \
V(STRING_ADD_RIGHT, 1) \ V(STRING_ADD_RIGHT, 1) \
V(STRING_ADD_RIGHT_STRONG, 1) \
V(APPLY_PREPARE, 1) \ V(APPLY_PREPARE, 1) \
V(REFLECT_APPLY_PREPARE, 1) \ V(REFLECT_APPLY_PREPARE, 1) \
V(REFLECT_CONSTRUCT_PREPARE, 2) \ V(REFLECT_CONSTRUCT_PREPARE, 2) \
......
...@@ -10903,6 +10903,12 @@ HValue* HGraphBuilder::BuildBinaryOperation( ...@@ -10903,6 +10903,12 @@ HValue* HGraphBuilder::BuildBinaryOperation(
// Special case for string addition here. // Special case for string addition here.
if (op == Token::ADD && if (op == Token::ADD &&
(left_type->Is(Type::String()) || right_type->Is(Type::String()))) { (left_type->Is(Type::String()) || right_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);
right = BuildCheckString(right);
} else {
// Validate type feedback for left argument. // Validate type feedback for left argument.
if (left_type->Is(Type::String())) { if (left_type->Is(Type::String())) {
left = BuildCheckString(left); left = BuildCheckString(left);
...@@ -10914,30 +10920,27 @@ HValue* HGraphBuilder::BuildBinaryOperation( ...@@ -10914,30 +10920,27 @@ HValue* HGraphBuilder::BuildBinaryOperation(
} }
// Convert left argument as necessary. // Convert left argument as necessary.
if (left_type->Is(Type::Number()) && !is_strong(strength)) { if (left_type->Is(Type::Number())) {
DCHECK(right_type->Is(Type::String())); DCHECK(right_type->Is(Type::String()));
left = BuildNumberToString(left, left_type); left = BuildNumberToString(left, left_type);
} else if (!left_type->Is(Type::String())) { } else if (!left_type->Is(Type::String())) {
DCHECK(right_type->Is(Type::String())); DCHECK(right_type->Is(Type::String()));
HValue* function = AddLoadJSBuiltin( HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_RIGHT);
is_strong(strength) ? Builtins::STRING_ADD_RIGHT_STRONG
: Builtins::STRING_ADD_RIGHT);
Add<HPushArguments>(left, right); Add<HPushArguments>(left, right);
return AddUncasted<HInvokeFunction>(function, 2); return AddUncasted<HInvokeFunction>(function, 2);
} }
// Convert right argument as necessary. // Convert right argument as necessary.
if (right_type->Is(Type::Number()) && !is_strong(strength)) { if (right_type->Is(Type::Number())) {
DCHECK(left_type->Is(Type::String())); DCHECK(left_type->Is(Type::String()));
right = BuildNumberToString(right, right_type); right = BuildNumberToString(right, right_type);
} else if (!right_type->Is(Type::String())) { } else if (!right_type->Is(Type::String())) {
DCHECK(left_type->Is(Type::String())); DCHECK(left_type->Is(Type::String()));
HValue* function = AddLoadJSBuiltin(is_strong(strength) HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT);
? Builtins::STRING_ADD_LEFT_STRONG
: Builtins::STRING_ADD_LEFT);
Add<HPushArguments>(left, right); Add<HPushArguments>(left, right);
return AddUncasted<HInvokeFunction>(function, 2); return AddUncasted<HInvokeFunction>(function, 2);
} }
}
// Fast paths for empty constant strings. // Fast paths for empty constant strings.
Handle<String> left_string = Handle<String> left_string =
......
...@@ -23,9 +23,7 @@ var COMPARE_STRONG; ...@@ -23,9 +23,7 @@ var COMPARE_STRONG;
var ADD; var ADD;
var ADD_STRONG; var ADD_STRONG;
var STRING_ADD_LEFT; var STRING_ADD_LEFT;
var STRING_ADD_LEFT_STRONG;
var STRING_ADD_RIGHT; var STRING_ADD_RIGHT;
var STRING_ADD_RIGHT_STRONG;
var SUB; var SUB;
var SUB_STRONG; var SUB_STRONG;
var MUL; var MUL;
...@@ -262,15 +260,6 @@ STRING_ADD_LEFT = function STRING_ADD_LEFT(y) { ...@@ -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. // Right operand (y) is already a string.
STRING_ADD_RIGHT = function STRING_ADD_RIGHT(y) { STRING_ADD_RIGHT = function STRING_ADD_RIGHT(y) {
var x = this; var x = this;
...@@ -287,15 +276,6 @@ STRING_ADD_RIGHT = function STRING_ADD_RIGHT(y) { ...@@ -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. // ECMA-262, section 11.6.2, page 50.
SUB = function SUB(y) { SUB = function SUB(y) {
var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this); 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