Commit 69a645d3 authored by Ross McIlroy's avatar Ross McIlroy Committed by Commit Bot

[TurboFan] Enable typed lowering of JSStringConcat to ConsString allocation.

Adds typed lowering of JSStringConcat to ConsString allocation if the
following conditions hold:
 - All concatinations will result in a ConsString of >= ConString::kMinLength
 - No concatinations will result in a empty string in the RHS unless there is
   a sequential string in the LHS.

This also means JSStringConcat needs an eager checkpoint since it can
deopt if throwing a RangeError when the string length protector is valid.

BUG=v8:6243

Change-Id: I01ca79f884df467c10f2c032c72d51b5199c1a3c
Reviewed-on: https://chromium-review.googlesource.com/526636
Commit-Queue: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46093}
parent d03768b0
...@@ -2159,6 +2159,7 @@ void BytecodeGraphBuilder::VisitToPrimitiveToString() { ...@@ -2159,6 +2159,7 @@ void BytecodeGraphBuilder::VisitToPrimitiveToString() {
} }
void BytecodeGraphBuilder::VisitStringConcat() { void BytecodeGraphBuilder::VisitStringConcat() {
PrepareEagerCheckpoint();
interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(0); interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(0);
int operand_count = int operand_count =
static_cast<int>(bytecode_iterator().GetRegisterCountOperand(1)); static_cast<int>(bytecode_iterator().GetRegisterCountOperand(1));
......
This diff is collapsed.
...@@ -69,6 +69,7 @@ class V8_EXPORT_PRIVATE JSTypedLowering final ...@@ -69,6 +69,7 @@ class V8_EXPORT_PRIVATE JSTypedLowering final
Reduction ReduceJSToStringInput(Node* input); Reduction ReduceJSToStringInput(Node* input);
Reduction ReduceJSToString(Node* node); Reduction ReduceJSToString(Node* node);
Reduction ReduceJSToPrimitiveToString(Node* node); Reduction ReduceJSToPrimitiveToString(Node* node);
Reduction ReduceJSStringConcat(Node* node);
Reduction ReduceJSToObject(Node* node); Reduction ReduceJSToObject(Node* node);
Reduction ReduceJSConvertReceiver(Node* node); Reduction ReduceJSConvertReceiver(Node* node);
Reduction ReduceJSConstructForwardVarargs(Node* node); Reduction ReduceJSConstructForwardVarargs(Node* node);
...@@ -94,6 +95,13 @@ class V8_EXPORT_PRIVATE JSTypedLowering final ...@@ -94,6 +95,13 @@ class V8_EXPORT_PRIVATE JSTypedLowering final
// Helper for ReduceJSLoadModule and ReduceJSStoreModule. // Helper for ReduceJSLoadModule and ReduceJSStoreModule.
Node* BuildGetModuleCell(Node* node); Node* BuildGetModuleCell(Node* node);
// Helpers for ReduceJSCreateConsString and ReduceJSStringConcat.
Node* BuildGetStringLength(Node* value, Node** effect, Node* control);
void BuildThrowStringRangeError(Node* node, Node* context, Node* frame_state,
Node* effect, Node* control);
Node* BuildCreateConsString(Node* first, Node* second, Node* length,
Node* effect, Node* control);
Factory* factory() const; Factory* factory() const;
Graph* graph() const; Graph* graph() const;
JSGraph* jsgraph() const { return jsgraph_; } JSGraph* jsgraph() const { return jsgraph_; }
......
...@@ -108,6 +108,7 @@ bool OperatorProperties::HasFrameStateInput(const Operator* op) { ...@@ -108,6 +108,7 @@ bool OperatorProperties::HasFrameStateInput(const Operator* op) {
case IrOpcode::kJSCallWithSpread: case IrOpcode::kJSCallWithSpread:
// Misc operations // Misc operations
case IrOpcode::kJSStringConcat:
case IrOpcode::kJSForInNext: case IrOpcode::kJSForInNext:
case IrOpcode::kJSForInPrepare: case IrOpcode::kJSForInPrepare:
case IrOpcode::kJSStackCheck: case IrOpcode::kJSStackCheck:
......
...@@ -659,9 +659,7 @@ void String::StringVerify() { ...@@ -659,9 +659,7 @@ void String::StringVerify() {
void ConsString::ConsStringVerify() { void ConsString::ConsStringVerify() {
CHECK(this->first()->IsString()); CHECK(this->first()->IsString() && this->second()->IsString());
CHECK(this->second() == GetHeap()->empty_string() ||
this->second()->IsString());
CHECK(this->length() >= ConsString::kMinLength); CHECK(this->length() >= ConsString::kMinLength);
CHECK(this->length() == this->first()->length() + this->second()->length()); CHECK(this->length() == this->first()->length() + this->second()->length());
if (this->IsFlat()) { if (this->IsFlat()) {
......
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
var a = "a".repeat(268435440);
(function() {
function foo(a) {
try {
return "longer than ConsString:kMinLength" + a + "0123456789012";
} catch (e) {
return e;
}
}
foo("a");
foo("a");
// Optimize with string length protector check.
%OptimizeFunctionOnNextCall(foo);
foo("a");
assertInstanceof(foo(a), RangeError);
// Optimize without string length protector check.
%OptimizeFunctionOnNextCall(foo);
foo("a");
assertInstanceof(foo(a), RangeError);
})();
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