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

Unified Diff: runtime/vm/flow_graph_optimizer.cc

Issue 10918164: Inline GrowableObjectArray capacity getter, use CHA to eliminate load/store fields class checks. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 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 | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/flow_graph_optimizer.cc
===================================================================
--- runtime/vm/flow_graph_optimizer.cc (revision 12158)
+++ runtime/vm/flow_graph_optimizer.cc (working copy)
@@ -535,6 +535,35 @@
}
+// Use CHA to determine if the call needs a class check: if the callee's
+// receiver is the same as the caller's receiver and there are no overriden
+// callee functions, then no class check is needed.
+bool FlowGraphOptimizer::InstanceCallNeedsClassCheck(
+ InstanceCallInstr* call) const {
+ if (!FLAG_use_cha) return true;
+ Definition* callee_receiver = call->ArgumentAt(0)->value()->definition();
+ ASSERT(callee_receiver != NULL);
+ const Function& function = flow_graph_->parsed_function().function();
+ if (function.IsDynamicFunction() &&
+ callee_receiver->IsParameter() &&
+ (callee_receiver->AsParameter()->index() == 0)) {
+ const intptr_t static_receiver_cid = Class::Handle(function.Owner()).id();
+ ZoneGrowableArray<intptr_t>* subclass_cids =
+ CHA::GetSubclassIdsOf(static_receiver_cid);
+ if (subclass_cids->is_empty()) {
+ // No subclasses, no check needed.
+ return false;
+ }
+ ZoneGrowableArray<Function*>* overriding_functions =
+ CHA::GetNamedInstanceFunctionsOf(*subclass_cids, call->function_name());
+ if (overriding_functions->is_empty()) {
+ // No overriding functions.
+ return false;
+ }
+ }
+ return true;
+}
+
// Only unique implicit instance getters can be currently handled.
bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) {
ASSERT(call->HasICData());
@@ -559,7 +588,9 @@
const Field& field = Field::Handle(GetField(class_ids[0], field_name));
ASSERT(!field.IsNull());
- AddCheckClass(call, call->ArgumentAt(0)->value()->Copy());
+ if (InstanceCallNeedsClassCheck(call)) {
+ AddCheckClass(call, call->ArgumentAt(0)->value()->Copy());
+ }
// Detach environment from the original instruction because it can't
// deoptimize.
call->set_env(NULL);
@@ -607,6 +638,29 @@
return true;
}
+ if (recognized_kind == MethodRecognizer::kGrowableArrayCapacity) {
+ // Check receiver class.
+ AddCheckClass(call, call->ArgumentAt(0)->value()->Copy());
+
+ // TODO(srdjan): type of load should be GrowableObjectArrayType.
+ LoadVMFieldInstr* data_load = new LoadVMFieldInstr(
+ call->ArgumentAt(0)->value(),
+ Array::data_offset(),
+ Type::ZoneHandle(Type::DynamicType()));
+ data_load->set_result_cid(kGrowableObjectArrayCid);
+ InsertBefore(call, data_load, NULL, Definition::kValue);
+
+ LoadVMFieldInstr* length_load = new LoadVMFieldInstr(
+ new Value(data_load),
+ Array::length_offset(),
+ Type::ZoneHandle(Type::SmiType()));
+ length_load->set_result_cid(kSmiCid);
+
+ call->ReplaceWith(length_load, current_iterator());
+ RemovePushArguments(call);
+ return true;
+ }
+
if (recognized_kind == MethodRecognizer::kStringBaseLength) {
if (!HasOneTarget(ic_data)) {
// Target is not only StringBase_get_length.
@@ -688,30 +742,13 @@
}
const ICData& unary_checks =
ICData::ZoneHandle(instr->ic_data()->AsUnaryClassChecks());
- if (FLAG_use_cha) {
- // Check if receiver can have only one target, in which case
- // we emit call without class checks.
- Definition* receiver = instr->ArgumentAt(0)->value()->definition();
- ASSERT(receiver != NULL);
- const Function& function = flow_graph_->parsed_function().function();
- if (function.IsDynamicFunction() &&
- receiver->IsParameter() &&
- (receiver->AsParameter()->index() == 0)) {
- intptr_t static_receiver_cid = Class::Handle(function.Owner()).id();
- ZoneGrowableArray<intptr_t>* subclass_cids =
- CHA::GetSubclassIdsOf(static_receiver_cid);
- ZoneGrowableArray<Function*>* overriding_functions =
- CHA::GetNamedInstanceFunctionsOf(*subclass_cids,
- instr->function_name());
- if (overriding_functions->is_empty()) {
- const bool call_with_checks = false;
- PolymorphicInstanceCallInstr* call =
- new PolymorphicInstanceCallInstr(instr, unary_checks,
- call_with_checks);
- instr->ReplaceWith(call, current_iterator());
- return;
- }
- }
+ if (!InstanceCallNeedsClassCheck(instr)) {
+ const bool call_with_checks = false;
+ PolymorphicInstanceCallInstr* call =
+ new PolymorphicInstanceCallInstr(instr, unary_checks,
+ call_with_checks);
+ instr->ReplaceWith(call, current_iterator());
+ return;
}
const intptr_t kMaxChecks = 4;
if (instr->ic_data()->NumberOfChecks() <= kMaxChecks) {
@@ -776,7 +813,9 @@
const Field& field = Field::Handle(GetField(class_id, field_name));
ASSERT(!field.IsNull());
- AddCheckClass(instr, instr->ArgumentAt(0)->value()->Copy());
+ if (InstanceCallNeedsClassCheck(instr)) {
+ AddCheckClass(instr, instr->ArgumentAt(0)->value()->Copy());
+ }
// Detach environment from the original instruction because it can't
// deoptimize.
instr->set_env(NULL);
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698