Attempt to do direct class comparison for type checks using CHA.

Next step is to convert instanceof nodes to an integer comparison node, which would then be automatically merged with branch.
Review URL: https://codereview.chromium.org//11348289

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@15486 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
srdjan@google.com 2012-11-29 00:49:42 +00:00
parent 2c1d51db1c
commit 888e564924
5 changed files with 60 additions and 0 deletions

View file

@ -6,6 +6,7 @@
#include "vm/flow_graph_compiler.h"
#include "vm/cha.h"
#include "vm/dart_entry.h"
#include "vm/debugger.h"
#include "vm/deopt_instructions.h"
@ -28,6 +29,7 @@ DECLARE_FLAG(bool, intrinsify);
DECLARE_FLAG(bool, propagate_ic_data);
DECLARE_FLAG(bool, report_usage_count);
DECLARE_FLAG(int, optimization_counter_threshold);
DECLARE_FLAG(bool, use_cha);
void CompilerDeoptInfo::BuildReturnAddress(DeoptInfoBuilder* builder,
const Function& function,
@ -1004,4 +1006,28 @@ FieldAddress FlowGraphCompiler::ElementAddressForRegIndex(intptr_t cid,
}
}
// Returns true if checking against this type is a direct class id comparison.
bool FlowGraphCompiler::TypeCheckAsClassEquality(const AbstractType& type) {
ASSERT(type.IsFinalized() && !type.IsMalformed());
// Requires CHA, which can be applied in optimized code only,
if (!FLAG_use_cha || !is_optimizing()) return false;
if (!type.IsInstantiated()) return false;
const Class& type_class = Class::Handle(type.type_class());
// Could be an interface check?
if (type_class.is_implemented()) return false;
const intptr_t type_cid = type_class.id();
if (CHA::HasSubclasses(type_cid)) return false;
if (type_class.HasTypeArguments()) {
// Only raw types can be directly compared, thus disregarding type
// arguments.
const AbstractTypeArguments& type_arguments =
AbstractTypeArguments::Handle(type.arguments());
const bool is_raw_type = type_arguments.IsNull() ||
type_arguments.IsRaw(type_arguments.Length());
return is_raw_type;
}
return true;
}
} // namespace dart

View file

@ -392,6 +392,20 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateInlineInstanceof(
// type error. A null value is handled prior to executing this inline code.
return SubtypeTestCache::null();
}
if (TypeCheckAsClassEquality(type)) {
const intptr_t type_cid = Class::Handle(type.type_class()).id();
const Register kInstanceReg = EAX;
__ testl(kInstanceReg, Immediate(kSmiTagMask));
if (type_cid == kSmiCid) {
__ j(ZERO, is_instance_lbl);
} else {
__ j(ZERO, is_not_instance_lbl);
__ CompareClassId(kInstanceReg, type_cid, EDI);
__ j(EQUAL, is_instance_lbl);
}
__ jmp(is_not_instance_lbl);
return SubtypeTestCache::null();
}
if (type.IsInstantiated()) {
const Class& type_class = Class::ZoneHandle(type.type_class());
// A Smi object cannot be the instance of a parameterized class.

View file

@ -297,6 +297,9 @@ class FlowGraphCompiler : public ValueObject {
Label* is_instance_lbl,
Label* is_not_instance_lbl);
// Returns true if checking against this type is a direct class id comparison.
bool TypeCheckAsClassEquality(const AbstractType& type);
void GenerateBoolToJump(Register bool_reg, Label* is_true, Label* is_false);
void CopyParameters();

View file

@ -392,6 +392,20 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateInlineInstanceof(
// type error. A null value is handled prior to executing this inline code.
return SubtypeTestCache::null();
}
if (TypeCheckAsClassEquality(type)) {
const intptr_t type_cid = Class::Handle(type.type_class()).id();
const Register kInstanceReg = RAX;
__ testq(kInstanceReg, Immediate(kSmiTagMask));
if (type_cid == kSmiCid) {
__ j(ZERO, is_instance_lbl);
} else {
__ j(ZERO, is_not_instance_lbl);
__ CompareClassId(kInstanceReg, type_cid);
__ j(EQUAL, is_instance_lbl);
}
__ jmp(is_not_instance_lbl);
return SubtypeTestCache::null();
}
if (type.IsInstantiated()) {
const Class& type_class = Class::ZoneHandle(type.type_class());
// A Smi object cannot be the instance of a parameterized class.

View file

@ -298,6 +298,9 @@ class FlowGraphCompiler : public ValueObject {
Label* is_instance_lbl,
Label* is_not_instance_lbl);
// Returns true if checking against this type is a direct class id comparison.
bool TypeCheckAsClassEquality(const AbstractType& type);
void GenerateBoolToJump(Register bool_reg, Label* is_true, Label* is_false);
void CopyParameters();