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

Unified Diff: dart/runtime/vm/flow_graph_optimizer.cc

Issue 119673004: Version 1.1.0-dev.5.2 (Closed) Base URL: http://dart.googlecode.com/svn/trunk/
Patch Set: Created 6 years, 11 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 | « dart/runtime/vm/flow_graph_optimizer.h ('k') | dart/runtime/vm/flow_graph_type_propagator.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: dart/runtime/vm/flow_graph_optimizer.cc
===================================================================
--- dart/runtime/vm/flow_graph_optimizer.cc (revision 31530)
+++ dart/runtime/vm/flow_graph_optimizer.cc (working copy)
@@ -41,7 +41,7 @@
"Print live sets for load optimization pass.");
DEFINE_FLAG(bool, enable_simd_inline, true,
"Enable inlining of SIMD related method calls.");
-DEFINE_FLAG(int, getter_setter_ratio, 10,
+DEFINE_FLAG(int, getter_setter_ratio, 13,
"Ratio of getter/setter usage used for double field unboxing heuristics");
DECLARE_FLAG(bool, eliminate_type_checks);
DECLARE_FLAG(bool, enable_type_checks);
@@ -124,7 +124,7 @@
const Token::Kind op_kind = call->token_kind();
if (Token::IsRelationalOperator(op_kind) ||
- Token::IsRelationalOperator(op_kind) ||
+ Token::IsEqualityOperator(op_kind) ||
Token::IsBinaryOperator(op_kind)) {
// Guess cid: if one of the inputs is a number assume that the other
// is a number of same type.
@@ -1481,6 +1481,111 @@
}
+// 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 d->IsStringFromCharCode();
+ }
+}
+
+
+// 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 =
+ flow_graph()->GetConstant(Smi::ZoneHandle(Smi::New(str.CharAt(0))));
+ left_val = new Value(char_code_left);
+ } else if (left->IsStringFromCharCode()) {
+ // Use input of string-from-charcode as left value.
+ StringFromCharCodeInstr* instr = left->AsStringFromCharCode();
+ 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 (right->IsStringFromCharCode()) {
+ // Skip string-from-char-code, and use its input as right value.
+ StringFromCharCodeInstr* right_instr = right->AsStringFromCharCode();
+ 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.
+ StringToCharCodeInstr* char_code_right =
+ new StringToCharCodeInstr(new Value(right), kOneByteStringCid);
+ 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)) {
+ to_remove_left->ReplaceUsesWith(flow_graph()->constant_null());
+ to_remove_left->RemoveFromGraph();
+ }
+ if ((to_remove_right != NULL) &&
+ (to_remove_right->input_use_list() == NULL)) {
+ to_remove_right->ReplaceUsesWith(flow_graph()->constant_null());
+ to_remove_right->RemoveFromGraph();
+ }
+ return true;
+ }
+ return false;
+}
+
+
static bool SmiFitsInDouble() { return kSmiBits < 53; }
bool FlowGraphOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call,
@@ -1493,7 +1598,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(),
@@ -3313,7 +3424,8 @@
}
// Remove call, replace it with 'left'.
call->ReplaceUsesWith(left);
- call->RemoveFromGraph();
+ ASSERT(current_iterator()->Current() == call);
+ current_iterator()->RemoveCurrentFromGraph();
return;
}
}
@@ -6661,12 +6773,43 @@
}
+void ConstantPropagator::VisitDebugStepCheck(DebugStepCheckInstr* instr) {
+ // Nothing to do.
+}
+
+
void ConstantPropagator::VisitStringFromCharCode(
StringFromCharCodeInstr* instr) {
- SetValue(instr, non_constant_);
+ const Object& o = instr->char_code()->definition()->constant_value();
+ if (o.IsNull() || 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_);
+ }
+ }
}
+void ConstantPropagator::VisitStringToCharCode(StringToCharCodeInstr* instr) {
+ const Object& o = instr->str()->definition()->constant_value();
+ if (o.IsNull() || 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;
+ SetValue(instr, Smi::ZoneHandle(Smi::New(result)));
+ }
+}
+
+
+
+
void ConstantPropagator::VisitStringInterpolate(StringInterpolateInstr* instr) {
SetValue(instr, non_constant_);
return;
« no previous file with comments | « dart/runtime/vm/flow_graph_optimizer.h ('k') | dart/runtime/vm/flow_graph_type_propagator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698