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

Unified Diff: runtime/vm/flow_graph_optimizer.cc

Issue 105143011: Optimize one byte string comparisons. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years 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
Index: runtime/vm/flow_graph_optimizer.cc
===================================================================
--- runtime/vm/flow_graph_optimizer.cc (revision 31282)
+++ runtime/vm/flow_graph_optimizer.cc (working copy)
@@ -1481,6 +1481,122 @@
}
+static bool IsStringFromCharCode(Definition* d) {
+ return (d->IsStringCharCode() &&
+ (d->AsStringCharCode()->kind() == StringCharCodeInstr::kFromCharCode));
+}
+
+
+// Return true if d is a string of length one (a constant or result from
+// from string-from-char-code instruction.
+static bool IsLengthOneString(Definition* d) {
+ if (d->IsConstant()) {
+ const Object& obj = d->AsConstant()->value();
+ if (obj.IsString()) {
+ return String::Cast(obj).Length() == 1;
+ } else {
+ return false;
+ }
+ } else {
+ return IsStringFromCharCode(d);
+ }
+}
+
+
+// Returns true if the string comparison was converted into char-code
+// comparison. Conversion is only possible for strings of length one.
+// E.g., detect str[x] == "x"; and use an integer comparison of char-codes.
+// TODO(srdjan): Expand for two-byte and external strings.
+bool FlowGraphOptimizer::TryStringLengthOneEquality(InstanceCallInstr* call,
+ Token::Kind op_kind) {
+ ASSERT(HasOnlyTwoOf(*call->ic_data(), kOneByteStringCid));
+ // Check that left and right are length one strings (either string constants
+ // or results of string-from-char-code.
+ Definition* left = call->ArgumentAt(0);
+ Definition* right = call->ArgumentAt(1);
+ Value* left_val = NULL;
+ Definition* to_remove_left = NULL;
+ if (IsLengthOneString(right)) {
+ // Swap, since we know that both arguments are strings
+ Definition* temp = left;
+ left = right;
+ right = temp;
+ }
+ if (IsLengthOneString(left)) {
+ // Optimize if left is a string with length one (either constant or
+ // result of string-from-char-code.
+ if (left->IsConstant()) {
+ ConstantInstr* left_const = left->AsConstant();
+ const String& str = String::Cast(left_const->value());
+ ASSERT(str.Length() == 1);
+ ConstantInstr* char_code_left =
+ new ConstantInstr(Smi::ZoneHandle(Smi::New(str.CharAt(0))));
Florian Schneider 2013/12/20 09:29:12 Use flow_graph()->GetConstant(Smi::Handle(Smi::New
srdjan 2013/12/20 19:48:03 Done, and using ZoneHandle since the handle escape
+ InsertBefore(call, char_code_left, NULL, Definition::kValue);
+ left_val = new Value(char_code_left);
+ } else if (IsStringFromCharCode(left)) {
+ // Use input of string-from-charcode as left value.
+ StringCharCodeInstr* instr = left->AsStringCharCode();
+ left_val = new Value(instr->char_code()->definition());
+ to_remove_left = instr;
+ } else {
+ // IsLengthOneString(left) should have been false.
+ UNREACHABLE();
+ }
+
+ Definition* to_remove_right = NULL;
+ Value* right_val = NULL;
+ if (IsStringFromCharCode(right)) {
+ // Skip string-from-char-code, and use its input as right value.
+ StringCharCodeInstr* right_instr = right->AsStringCharCode();
+ right_val = new Value(right_instr->char_code()->definition());
+ to_remove_right = right_instr;
+ } else {
+ const ICData& unary_checks_1 =
+ ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecksForArgNr(1));
+ AddCheckClass(right,
+ unary_checks_1,
+ call->deopt_id(),
+ call->env(),
+ call);
+ // String-to-char-code instructions returns -1 (illegal charcode) if
+ // string is not of length one.
+ StringCharCodeInstr* char_code_right = new StringCharCodeInstr(
+ new Value(right),
+ kOneByteStringCid,
+ StringCharCodeInstr::kToCharCode);
+ InsertBefore(call, char_code_right, call->env(), Definition::kValue);
+ right_val = new Value(char_code_right);
+ }
+
+ // Comparing char-codes instead of strings.
+ EqualityCompareInstr* comp =
+ new EqualityCompareInstr(call->token_pos(),
+ op_kind,
+ left_val,
+ right_val,
+ kSmiCid,
+ call->deopt_id());
+ ReplaceCall(call, comp);
+
+ // Remove dead instructions.
+ if ((to_remove_left != NULL) &&
+ (to_remove_left->input_use_list() == NULL)) {
+ ConstantInstr* null = new ConstantInstr(Instance::ZoneHandle());
Florian Schneider 2013/12/20 09:29:12 Use flow_grah()->constant_null().
srdjan 2013/12/20 19:48:03 Done.
+ to_remove_left->ReplaceUsesWith(null);
+ to_remove_left->RemoveFromGraph();
+ }
+ if ((to_remove_right != NULL) &&
+ (to_remove_right->input_use_list() == NULL)) {
+ ConstantInstr* null = new ConstantInstr(Instance::ZoneHandle());
Florian Schneider 2013/12/20 09:29:12 Use flow_grah()->constant_null().
srdjan 2013/12/20 19:48:03 Done.
+ to_remove_right->ReplaceUsesWith(null);
+ to_remove_right->RemoveFromGraph();
+ }
+ return true;
+ }
+ return false;
+}
+
+
static bool SmiFitsInDouble() { return kSmiBits < 53; }
bool FlowGraphOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call,
@@ -1493,7 +1609,13 @@
Definition* right = call->ArgumentAt(1);
intptr_t cid = kIllegalCid;
- if (HasOnlyTwoOf(ic_data, kSmiCid)) {
+ if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) {
+ if (TryStringLengthOneEquality(call, op_kind)) {
+ return true;
+ } else {
+ return false;
+ }
+ } else if (HasOnlyTwoOf(ic_data, kSmiCid)) {
InsertBefore(call,
new CheckSmiInstr(new Value(left), call->deopt_id()),
call->env(),
@@ -2355,9 +2477,10 @@
LoadIndexedInstr* load_char_code =
BuildStringCodeUnitAt(call, class_ids[0]);
InsertBefore(call, load_char_code, NULL, Definition::kValue);
- StringFromCharCodeInstr* char_at =
- new StringFromCharCodeInstr(new Value(load_char_code),
- kOneByteStringCid);
+ StringCharCodeInstr* char_at =
+ new StringCharCodeInstr(new Value(load_char_code),
+ kOneByteStringCid,
+ StringCharCodeInstr::kFromCharCode);
ReplaceCall(call, char_at);
return true;
}
@@ -6661,9 +6784,32 @@
}
-void ConstantPropagator::VisitStringFromCharCode(
- StringFromCharCodeInstr* instr) {
- SetValue(instr, non_constant_);
+void ConstantPropagator::VisitStringCharCode(StringCharCodeInstr* instr) {
+ if (instr->kind() == StringCharCodeInstr::kFromCharCode) {
+ const Object& o = instr->char_code()->definition()->constant_value();
+ if (IsNonConstant(o)) {
+ SetValue(instr, non_constant_);
+ } else if (IsConstant(o)) {
+ const intptr_t ch_code = Smi::Cast(o).Value();
+ ASSERT(ch_code >= 0);
+ if (ch_code < Symbols::kMaxOneCharCodeSymbol) {
+ RawString** table = Symbols::PredefinedAddress();
+ SetValue(instr, String::ZoneHandle(table[ch_code]));
+ } else {
+ SetValue(instr, non_constant_);
+ }
+ }
+ } else {
+ ASSERT(instr->kind() == StringCharCodeInstr::kToCharCode);
+ const Object& o = instr->str()->definition()->constant_value();
+ if (IsNonConstant(o)) {
+ SetValue(instr, non_constant_);
+ } else if (IsConstant(o)) {
+ const String& str = String::Cast(o);
+ const intptr_t result = (str.Length() == 1) ? str.CharAt(0) : -1;
Florian Schneider 2013/12/20 09:29:12 Can the case of Length() > 1 occur at all?
srdjan 2013/12/20 19:48:03 Yes, length 0 as well. StringToCharCode has as its
+ SetValue(instr, Smi::ZoneHandle(Smi::New(result)));
+ }
+ }
}

Powered by Google App Engine
This is Rietveld 408576698