Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(104)

Unified Diff: src/compiler/js-builtin-reducer.cc

Issue 2180373005: [turbofan] Add support for String.prototype.charCodeAt/charAt. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler/js-builtin-reducer.h ('k') | src/compiler/js-graph.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/js-builtin-reducer.cc
diff --git a/src/compiler/js-builtin-reducer.cc b/src/compiler/js-builtin-reducer.cc
index c8fe93d099138a94d4878d3fb2b8c727ce078d42..fa7f51d6ba2517cd456f509769571259a09ea0e8 100644
--- a/src/compiler/js-builtin-reducer.cc
+++ b/src/compiler/js-builtin-reducer.cc
@@ -3,6 +3,8 @@
// found in the LICENSE file.
#include "src/compiler/js-builtin-reducer.h"
+
+#include "src/compiler/access-builder.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/node-matchers.h"
#include "src/compiler/node-properties.h"
@@ -40,6 +42,10 @@ class JSCallReduction {
return function->shared()->builtin_function_id();
}
+ bool ReceiverMatches(Type* type) {
+ return NodeProperties::GetType(receiver())->Is(type);
+ }
+
// Determines whether the call takes zero inputs.
bool InputsMatchZero() { return GetJSCallArity() == 0; }
@@ -66,6 +72,7 @@ class JSCallReduction {
return true;
}
+ Node* receiver() { return NodeProperties::GetValueInput(node_, 1); }
Node* left() { return GetJSCallInput(0); }
Node* right() { return GetJSCallInput(1); }
@@ -534,6 +541,127 @@ Reduction JSBuiltinReducer::ReduceStringFromCharCode(Node* node) {
return NoChange();
}
+namespace {
+
+Node* GetStringReceiver(Node* node) {
+ Node* receiver = NodeProperties::GetValueInput(node, 1);
+ Type* receiver_type = NodeProperties::GetType(receiver);
+ Node* effect = NodeProperties::GetEffectInput(node);
+ if (receiver_type->Is(Type::String())) return receiver;
+ // Check if the {node} is dominated by a CheckString renaming for
+ // it's {receiver}, and if so use that renaming as {receiver} for
+ // the lowering below.
+ for (Node* dominator = effect;;) {
+ if (dominator->opcode() == IrOpcode::kCheckString &&
+ dominator->InputAt(0) == receiver) {
+ return dominator;
+ }
+ if (dominator->op()->EffectInputCount() != 1) {
+ // Didn't find any appropriate CheckString node.
+ return nullptr;
+ }
+ dominator = NodeProperties::GetEffectInput(dominator);
+ }
+}
+
+} // namespace
+
+// ES6 section 21.1.3.1 String.prototype.charAt ( pos )
+Reduction JSBuiltinReducer::ReduceStringCharAt(Node* node) {
+ // We need at least target, receiver and index parameters.
+ if (node->op()->ValueInputCount() >= 3) {
+ Node* index = NodeProperties::GetValueInput(node, 2);
+ Type* index_type = NodeProperties::GetType(index);
+ Node* effect = NodeProperties::GetEffectInput(node);
+ Node* control = NodeProperties::GetControlInput(node);
+
+ if (index_type->Is(Type::Unsigned32())) {
+ if (Node* receiver = GetStringReceiver(node)) {
+ // Determine the {receiver} length.
+ Node* receiver_length = effect = graph()->NewNode(
+ simplified()->LoadField(AccessBuilder::ForStringLength()), receiver,
+ effect, control);
+
+ // Check if {index} is less than {receiver} length.
+ Node* check = graph()->NewNode(simplified()->NumberLessThan(), index,
+ receiver_length);
+ Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
+ check, control);
+
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* vtrue;
+ {
+ // Load the character from the {receiver}.
+ vtrue = graph()->NewNode(simplified()->StringCharCodeAt(), receiver,
+ index, if_true);
+
+ // Return it as single character string.
+ vtrue = graph()->NewNode(simplified()->StringFromCharCode(), vtrue);
+ }
+
+ // Return the empty string otherwise.
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* vfalse = jsgraph()->EmptyStringConstant();
+
+ control = graph()->NewNode(common()->Merge(2), if_true, if_false);
+ Node* value =
+ graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
+ vtrue, vfalse, control);
+
+ ReplaceWithValue(node, value, effect, control);
+ return Replace(value);
+ }
+ }
+ }
+
+ return NoChange();
+}
+
+// ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos )
+Reduction JSBuiltinReducer::ReduceStringCharCodeAt(Node* node) {
+ // We need at least target, receiver and index parameters.
+ if (node->op()->ValueInputCount() >= 3) {
+ Node* index = NodeProperties::GetValueInput(node, 2);
+ Type* index_type = NodeProperties::GetType(index);
+ Node* effect = NodeProperties::GetEffectInput(node);
+ Node* control = NodeProperties::GetControlInput(node);
+
+ if (index_type->Is(Type::Unsigned32())) {
+ if (Node* receiver = GetStringReceiver(node)) {
+ // Determine the {receiver} length.
+ Node* receiver_length = effect = graph()->NewNode(
+ simplified()->LoadField(AccessBuilder::ForStringLength()), receiver,
+ effect, control);
+
+ // Check if {index} is less than {receiver} length.
+ Node* check = graph()->NewNode(simplified()->NumberLessThan(), index,
+ receiver_length);
+ Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
+ check, control);
+
+ // Load the character from the {receiver}.
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* vtrue = graph()->NewNode(simplified()->StringCharCodeAt(),
+ receiver, index, if_true);
+
+ // Return NaN otherwise.
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* vfalse = jsgraph()->NaNConstant();
+
+ control = graph()->NewNode(common()->Merge(2), if_true, if_false);
+ Node* value =
+ graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
+ vtrue, vfalse, control);
+
+ ReplaceWithValue(node, value, effect, control);
+ return Replace(value);
+ }
+ }
+ }
+
+ return NoChange();
+}
+
Reduction JSBuiltinReducer::Reduce(Node* node) {
Reduction reduction = NoChange();
JSCallReduction r(node);
@@ -646,6 +774,10 @@ Reduction JSBuiltinReducer::Reduce(Node* node) {
case kStringFromCharCode:
reduction = ReduceStringFromCharCode(node);
break;
+ case kStringCharAt:
+ return ReduceStringCharAt(node);
+ case kStringCharCodeAt:
+ return ReduceStringCharCodeAt(node);
default:
break;
}
« no previous file with comments | « src/compiler/js-builtin-reducer.h ('k') | src/compiler/js-graph.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698