Do not recompute unary_checks repeatedly. Add special (and quicker) way to check for method overrides using CHA.

Review URL: https://codereview.chromium.org//11275110

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@14434 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
srdjan@google.com 2012-11-01 21:06:36 +00:00
parent a2c7ebced0
commit 251169951b
4 changed files with 35 additions and 18 deletions

View file

@ -70,6 +70,27 @@ ZoneGrowableArray<intptr_t>* CHA::GetSubclassIdsOf(intptr_t cid) {
}
bool CHA::HasOverride(const Class& cls, const String& function_name) {
const GrowableObjectArray& cls_direct_subclasses =
GrowableObjectArray::Handle(cls.direct_subclasses());
if (cls_direct_subclasses.IsNull()) {
return false;
}
Class& direct_subclass = Class::Handle();
for (intptr_t i = 0; i < cls_direct_subclasses.Length(); i++) {
direct_subclass ^= cls_direct_subclasses.At(i);
if (direct_subclass.LookupDynamicFunction(function_name) !=
Function::null()) {
return true;
}
if (HasOverride(direct_subclass, function_name)) {
return true;
}
}
return false;
}
ZoneGrowableArray<Function*>* CHA::GetNamedInstanceFunctionsOf(
const ZoneGrowableArray<intptr_t>& cids,
const String& function_name) {

View file

@ -9,6 +9,7 @@
namespace dart {
class Class;
class Function;
template <typename T> class ZoneGrowableArray;
class String;
@ -33,6 +34,9 @@ class CHA : public AllStatic {
// Returns an array of functions overriding the given function.
// Must not be called for a function of class Object.
static ZoneGrowableArray<Function*>* GetOverridesOf(const Function& function);
// Returns true if any subclass of 'cls' contains the function.
static bool HasOverride(const Class& cls, const String& function_name);
};
} // namespace dart

View file

@ -876,19 +876,8 @@ bool FlowGraphOptimizer::InstanceCallNeedsClassCheck(
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 CHA::HasOverride(Class::Handle(function.Owner()),
call->function_name());
}
return true;
}
@ -1155,7 +1144,8 @@ void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
if ((op_kind == Token::kGET) && TryInlineInstanceGetter(instr)) {
return;
}
if ((op_kind == Token::kSET) && TryInlineInstanceSetter(instr)) {
if ((op_kind == Token::kSET) &&
TryInlineInstanceSetter(instr, unary_checks)) {
return;
}
if (TryInlineInstanceMethod(instr)) {
@ -1198,15 +1188,16 @@ void FlowGraphOptimizer::VisitStaticCall(StaticCallInstr* call) {
}
bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr) {
bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr,
const ICData& unary_ic_data) {
ASSERT((unary_ic_data.NumberOfChecks() > 0) &&
(unary_ic_data.num_args_tested() == 1));
if (FLAG_enable_type_checks) {
// TODO(srdjan): Add assignable check node if --enable_type_checks.
return false;
}
ASSERT(instr->HasICData());
const ICData& unary_ic_data =
ICData::Handle(instr->ic_data()->AsUnaryClassChecks());
if (unary_ic_data.NumberOfChecks() == 0) {
// No type feedback collected.
return false;

View file

@ -63,7 +63,8 @@ class FlowGraphOptimizer : public FlowGraphVisitor {
bool TryReplaceWithUnaryOp(InstanceCallInstr* call, Token::Kind op_kind);
bool TryInlineInstanceGetter(InstanceCallInstr* call);
bool TryInlineInstanceSetter(InstanceCallInstr* call);
bool TryInlineInstanceSetter(InstanceCallInstr* call,
const ICData& unary_ic_data);
bool TryInlineInstanceMethod(InstanceCallInstr* call);