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

Unified Diff: runtime/vm/flow_graph_optimizer.cc

Issue 10541135: Some cleanups, started implementing checked instance calls, better equality operation. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 6 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
Index: runtime/vm/flow_graph_optimizer.cc
===================================================================
--- runtime/vm/flow_graph_optimizer.cc (revision 8588)
+++ runtime/vm/flow_graph_optimizer.cc (working copy)
@@ -158,11 +158,11 @@
}
-void FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallComp* comp,
+bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallComp* comp,
Token::Kind op_kind) {
if (comp->ic_data()->NumberOfChecks() != 1) {
// TODO(srdjan): Not yet supported.
- return;
+ return false;
}
BinaryOpComp::OperandsType operands_type;
@@ -171,7 +171,7 @@
if (op_kind == Token::kDIV ||
op_kind == Token::kMOD) {
// TODO(srdjan): Not yet supported.
- return;
+ return false;
}
operands_type = BinaryOpComp::kSmiOperands;
@@ -181,13 +181,13 @@
op_kind != Token::kMUL &&
op_kind != Token::kDIV) {
// TODO(vegorov): Not yet supported.
- return;
+ return false;
}
operands_type = BinaryOpComp::kDoubleOperands;
} else {
// TODO(srdjan): Not yet supported.
- return;
+ return false;
}
ASSERT(comp->instr() != NULL);
@@ -200,18 +200,17 @@
comp,
left,
right);
- ASSERT(bin_op->ic_data() == NULL);
bin_op->set_ic_data(comp->ic_data());
- bin_op->set_instr(comp->instr());
- comp->instr()->replace_computation(bin_op);
+ comp->ReplaceWith(bin_op);
+ return true;
}
-void FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallComp* comp,
- Token::Kind op_kind) {
+bool FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallComp* comp,
+ Token::Kind op_kind) {
if (comp->ic_data()->NumberOfChecks() != 1) {
// TODO(srdjan): Not yet supported.
- return;
+ return false;
}
ASSERT(comp->instr() != NULL);
ASSERT(comp->InputCount() == 1);
@@ -222,11 +221,11 @@
unary_op = new NumberNegateComp(comp, comp->InputAt(0));
}
if (unary_op != NULL) {
- ASSERT(unary_op->ic_data() == NULL);
unary_op->set_ic_data(comp->ic_data());
- unary_op->set_instr(comp->instr());
- comp->instr()->replace_computation(unary_op);
+ comp->ReplaceWith(unary_op);
+ return true;
}
+ return false;
}
@@ -266,40 +265,75 @@
}
-// Returns array of all class ids that are in ic_data. The result is
-// normalized so that a smi class is at index 0 if it exists in the ic_data.
-static ZoneGrowableArray<intptr_t>* ExtractClassIds(const ICData& ic_data) {
- if (ic_data.NumberOfChecks() == 0) return NULL;
- ZoneGrowableArray<intptr_t>* result =
- new ZoneGrowableArray<intptr_t>(ic_data.NumberOfChecks());
+// Returns all receiver class-ids and corresponding tagets for the given
+// 'ic_data', sorted so that a smi class id is at index[0] if it exists.
+static void ExtractClassIdsAndTargets(const ICData& ic_data,
+ ZoneGrowableArray<intptr_t>* class_ids,
+ ZoneGrowableArray<Function*>* targets) {
+ ASSERT(class_ids != NULL);
+ ASSERT(targets != NULL);
+ class_ids->Clear();
+ targets->Clear();
intptr_t smi_index = -1;
Function& target = Function::Handle();
- Class& cls = Class::Handle();
+ GrowableArray<const Class*> classes;
for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
- ic_data.GetOneClassCheckAt(i, &cls, &target);
- result->Add(cls.id());
- if (cls.id() == kSmi) {
+ ic_data.GetCheckAt(i, &classes, &target);
+ // Collect receiver class only.
+ const intptr_t class_id = (*classes[0]).id();
+ if (ic_data.num_args_tested() > 1) {
+ // Check if we have not already entered the class-id.
+ Function* target_found = NULL;
+ for (intptr_t k = 0; k < class_ids->length(); k++) {
+ if ((*class_ids)[k] == class_id) {
+ target_found = (*targets)[k];
+ break;
+ }
+ }
+ if (target_found != NULL) {
+ ASSERT(target_found->raw() == target.raw());
+ continue;
+ }
+ }
+ if (class_id == kSmi) {
ASSERT(smi_index < 0); // Classes entered only once in ic_data.
- smi_index = i;
+ smi_index = class_ids->length();
}
+ class_ids->Add(class_id);
+ targets->Add(&Function::ZoneHandle(target.raw()));
}
if (smi_index >= 0) {
// Smi class id must be at index 0.
- intptr_t temp = (*result)[0];
- (*result)[0] = (*result)[smi_index];
- (*result)[smi_index] = temp;
+ intptr_t temp_id = (*class_ids)[0];
+ Function* temp_func = (*targets)[0];
+ (*class_ids)[0] = (*class_ids)[smi_index];
+ (*targets)[0] = (*targets)[smi_index];
+ (*class_ids)[smi_index] = temp_id;
+ (*targets)[smi_index] = temp_func;
}
+}
+
+
+// Returns array of all class ids that are in ic_data. The result is
+// normalized so that a smi class is at index 0 if it exists in the ic_data.
+static ZoneGrowableArray<intptr_t>* ExtractClassIds(const ICData& ic_data) {
+ if (ic_data.NumberOfChecks() == 0) return NULL;
+ ZoneGrowableArray<intptr_t>* result =
+ new ZoneGrowableArray<intptr_t>(ic_data.NumberOfChecks());
+ ZoneGrowableArray<Function*>* dummy =
+ new ZoneGrowableArray<Function*>(ic_data.NumberOfChecks());
+ ExtractClassIdsAndTargets(ic_data, result, dummy);
Vyacheslav Egorov (Google) 2012/06/13 09:02:27 how about passing NULL instead of dummy? Collectin
srdjan 2012/06/13 18:34:24 Done.
return result;
}
// Only unique implicit instance getters can be currently handled.
-void FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallComp* comp) {
+bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallComp* comp) {
ASSERT(comp->HasICData());
const ICData& ic_data = *comp->ic_data();
if (ic_data.NumberOfChecks() == 0) {
// No type feedback collected.
- return;
+ return false;
}
Function& target = Function::Handle();
GrowableArray<const Class*> classes;
@@ -309,7 +343,7 @@
if (target.kind() == RawFunction::kImplicitGetter) {
if (!HasOneTarget(ic_data)) {
// TODO(srdjan): Implement for mutiple targets.
- return;
+ return false;
}
// Inline implicit instance getter.
const String& field_name =
@@ -318,10 +352,8 @@
ASSERT(!field.IsNull());
LoadInstanceFieldComp* load = new LoadInstanceFieldComp(
field, comp->InputAt(0), comp, ExtractClassIds(ic_data));
- // Replace 'comp' with 'load'.
- load->set_instr(comp->instr());
- comp->instr()->replace_computation(load);
- return;
+ comp->ReplaceWith(load);
+ return true;
}
// Not an implicit getter.
@@ -334,7 +366,7 @@
(recognized_kind == MethodRecognizer::kGrowableArrayLength)) {
if (!HasOneTarget(ic_data)) {
// TODO(srdjan): Implement for mutiple targets.
- return;
+ return false;
}
intptr_t length_offset = -1;
switch (recognized_kind) {
@@ -354,9 +386,8 @@
Type::ZoneHandle(Type::IntInterface()),
comp,
ExtractClassIds(ic_data));
- load->set_instr(comp->instr());
- comp->instr()->replace_computation(load);
- return;
+ comp->ReplaceWith(load);
+ return true;
}
if (recognized_kind == MethodRecognizer::kStringBaseLength) {
@@ -367,25 +398,24 @@
Type::ZoneHandle(Type::IntInterface()),
comp,
ExtractClassIds(ic_data));
- load->set_instr(comp->instr());
- comp->instr()->replace_computation(load);
- return;
+ comp->ReplaceWith(load);
+ return true;
}
+ return false;
}
// Inline only simple, frequently called core library methods.
-void FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallComp* comp) {
+bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallComp* comp) {
ASSERT(comp->HasICData());
const ICData& ic_data = *comp->ic_data();
if ((ic_data.NumberOfChecks() == 0) || !HasOneTarget(ic_data)) {
// No type feedback collected.
- return;
+ return false;
}
Function& target = Function::Handle();
GrowableArray<const Class*> classes;
ic_data.GetCheckAt(0, &classes, &target);
- ASSERT(classes.length() == 1);
MethodRecognizer::Kind recognized_kind =
MethodRecognizer::RecognizeKind(target);
if (recognized_kind == MethodRecognizer::kDoubleToDouble) {
@@ -394,27 +424,38 @@
if (recognized_kind == MethodRecognizer::kIntegerToDouble) {
// TODO(srdjan): Implement.
}
+ return false;
}
void FlowGraphOptimizer::VisitInstanceCall(InstanceCallComp* comp) {
- if (comp->HasICData()) {
+ if (comp->HasICData() && (comp->ic_data()->NumberOfChecks() > 0)) {
const String& function_name = comp->function_name();
Token::Kind op_kind = Token::GetBinaryOp(function_name);
Vyacheslav Egorov (Google) 2012/06/13 09:02:27 Can we just store op_kind in the InstanceCallComp
srdjan 2012/06/13 18:34:24 Yes, next CL.
- if (op_kind != Token::kILLEGAL) {
- TryReplaceWithBinaryOp(comp, op_kind);
+ if ((op_kind != Token::kILLEGAL) && TryReplaceWithBinaryOp(comp, op_kind)) {
return;
}
op_kind = Token::GetUnaryOp(function_name);
- if (op_kind != Token::kILLEGAL) {
- TryReplaceWithUnaryOp(comp, op_kind);
+ if ((op_kind != Token::kILLEGAL) && TryReplaceWithUnaryOp(comp, op_kind)) {
return;
}
- if (Field::IsGetterName(function_name)) {
- TryInlineInstanceGetter(comp);
+ if ((Field::IsGetterName(function_name)) && TryInlineInstanceGetter(comp)) {
return;
}
- TryInlineInstanceMethod(comp);
+ if (TryInlineInstanceMethod(comp)) {
+ return;
+ }
+ const intptr_t kMaxChecks = 4;
+ if (comp->ic_data()->num_args_tested() <= kMaxChecks) {
+ ZoneGrowableArray<intptr_t>* class_ids =
+ new ZoneGrowableArray<intptr_t>();
+ ZoneGrowableArray<Function*>* targets =
+ new ZoneGrowableArray<Function*>();
+ ExtractClassIdsAndTargets(*comp->ic_data(), class_ids, targets);
+ CheckedInstanceCallComp* call =
+ new CheckedInstanceCallComp(comp, *class_ids, *targets);
+ comp->ReplaceWith(call);
+ }
}
}
@@ -428,16 +469,16 @@
}
-void FlowGraphOptimizer::TryInlineInstanceSetter(InstanceSetterComp* comp) {
+bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceSetterComp* comp) {
ASSERT(comp->HasICData());
const ICData& ic_data = *comp->ic_data();
if (ic_data.NumberOfChecks() == 0) {
// No type feedback collected.
- return;
+ return false;
}
if (!HasOneTarget(ic_data)) {
// TODO(srdjan): Implement when not all targets are the sa,e.
- return;
+ return false;
}
Function& target = Function::Handle();
Class& cls = Class::Handle();
@@ -445,7 +486,7 @@
if (target.kind() != RawFunction::kImplicitSetter) {
// Not an implicit setter.
// TODO(srdjan): Inline special setters.
- return;
+ return false;
}
// Inline implicit instance setter.
const Field& field = Field::Handle(GetField(cls, comp->field_name()));
@@ -456,9 +497,8 @@
comp->InputAt(1),
comp,
ExtractClassIds(ic_data));
- // Replace 'comp' with 'store'.
- store->set_instr(comp->instr());
- comp->instr()->replace_computation(store);
+ comp->ReplaceWith(store);
+ return true;
}
@@ -510,6 +550,17 @@
}
+void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareComp* comp) {
+ if (!comp->HasICData()) return;
+ const ICData& ic_data = *comp->ic_data();
+ if (ic_data.NumberOfChecks() != 1) return;
+ ASSERT(HasOneTarget(ic_data));
+ if (HasTwoSmi(ic_data)) {
+ comp->set_operands_class_id(kSmi);
+ }
+}
+
+
void FlowGraphOptimizer::VisitDo(DoInstr* instr) {
instr->computation()->Accept(this);
}

Powered by Google App Engine
This is Rietveld 408576698