mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 03:17:55 +00:00
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:
parent
2c1d51db1c
commit
888e564924
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue