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

Unified Diff: runtime/vm/aot_optimizer.cc

Issue 2074533002: Simplify and improve optimization of is-tests in the precompiler. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 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/aot_optimizer.cc
diff --git a/runtime/vm/aot_optimizer.cc b/runtime/vm/aot_optimizer.cc
index 7cae460a5424d2a03c30e9daf8f0c2e39acafcfa..89d6b091ed43adba93821a62d7629e4d32a07bcb 100644
--- a/runtime/vm/aot_optimizer.cc
+++ b/runtime/vm/aot_optimizer.cc
@@ -1949,7 +1949,8 @@ bool AotOptimizer::TryInlineInt32x4Method(
// If type tests specified by 'ic_data' do not depend on type arguments,
// return mapping cid->result in 'results' (i : cid; i + 1: result).
// If all tests yield the same result, return it otherwise return Bool::null.
-// If no mapping is possible, 'results' is empty.
+// If no mapping is possible, 'results' has less than
+// (ic_data.NumberOfChecks() * 2) entries
// An instance-of test returning all same results can be converted to a class
// check.
RawBool* AotOptimizer::InstanceOfAsBool(
@@ -2078,7 +2079,7 @@ static void TryAddTest(ZoneGrowableArray<intptr_t>* results,
// TODO(srdjan): Do also for other than 'int' type.
static bool TryExpandTestCidsResult(ZoneGrowableArray<intptr_t>* results,
const AbstractType& type) {
- ASSERT(results->length() >= 2); // At least on eentry.
+ ASSERT(results->length() >= 2); // At least on entry.
const ClassTable& class_table = *Isolate::Current()->class_table();
if ((*results)[0] != kSmiCid) {
const Class& cls = Class::Handle(class_table.At(kSmiCid));
@@ -2100,14 +2101,26 @@ static bool TryExpandTestCidsResult(ZoneGrowableArray<intptr_t>* results,
ASSERT(type.IsInstantiated() && !type.IsMalformedOrMalbounded());
ASSERT(results->length() >= 2);
- if (type.IsIntType()) {
+ if (type.IsSmiType()) {
+ ASSERT((*results)[0] == kSmiCid);
+ return false;
+ } else if (type.IsIntType()) {
ASSERT((*results)[0] == kSmiCid);
TryAddTest(results, kMintCid, true);
TryAddTest(results, kBigintCid, true);
// Cannot deoptimize since all tests returning true have been added.
return false;
+ } else if (type.IsNumberType()) {
+ ASSERT((*results)[0] == kSmiCid);
+ TryAddTest(results, kMintCid, true);
+ TryAddTest(results, kBigintCid, true);
+ TryAddTest(results, kDoubleCid, true);
+ return false;
+ } else if (type.IsDoubleType()) {
+ ASSERT((*results)[0] == kSmiCid);
+ TryAddTest(results, kDoubleCid, true);
+ return false;
}
-
return true; // May deoptimize since we have not identified all 'true' tests.
}
@@ -2115,11 +2128,6 @@ static bool TryExpandTestCidsResult(ZoneGrowableArray<intptr_t>* results,
// TODO(srdjan): Use ICData to check if always true or false.
void AotOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
ASSERT(Token::IsTypeTestOperator(call->token_kind()));
- // Guard against repeated speculative inlining.
- if (!use_speculative_inlining_ ||
- IsBlackListedForInlining(call->deopt_id())) {
- return;
- }
Definition* left = call->ArgumentAt(0);
Definition* type_args = NULL;
AbstractType& type = AbstractType::ZoneHandle(Z);
@@ -2152,46 +2160,6 @@ void AotOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
negate = Bool::Cast(call->ArgumentAt(3)->OriginalDefinition()
->AsConstant()->value()).value();
}
- const ICData& unary_checks =
- ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks());
- if ((unary_checks.NumberOfChecks() > 0) &&
- (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) {
- ZoneGrowableArray<intptr_t>* results =
- new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2);
- Bool& as_bool =
- Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results));
- if (as_bool.IsNull()) {
- if (results->length() == unary_checks.NumberOfChecks() * 2) {
- const bool can_deopt = TryExpandTestCidsResult(results, type);
- TestCidsInstr* test_cids = new(Z) TestCidsInstr(
- call->token_pos(),
- negate ? Token::kISNOT : Token::kIS,
- new(Z) Value(left),
- *results,
- can_deopt ? call->deopt_id() : Thread::kNoDeoptId);
- // Remove type.
- ReplaceCall(call, test_cids);
- return;
- }
- } else {
- // TODO(srdjan): Use TestCidsInstr also for this case.
- // One result only.
- AddReceiverCheck(call);
- if (negate) {
- as_bool = Bool::Get(!as_bool.value()).raw();
- }
- ConstantInstr* bool_const = flow_graph()->GetConstant(as_bool);
- for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
- PushArgumentInstr* push = call->PushArgumentAt(i);
- push->ReplaceUsesWith(push->value()->definition());
- push->RemoveFromGraph();
- }
- call->ReplaceUsesWith(bool_const);
- ASSERT(current_iterator()->Current() == call);
- current_iterator()->RemoveCurrentFromGraph();
- return;
- }
- }
if (TypeCheckAsClassEquality(type)) {
LoadClassIdInstr* left_cid = new(Z) LoadClassIdInstr(new(Z) Value(left));
@@ -2214,6 +2182,31 @@ void AotOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
return;
}
+ const ICData& unary_checks =
+ ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks());
+ if ((unary_checks.NumberOfChecks() > 0) &&
+ (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) {
+ ZoneGrowableArray<intptr_t>* results =
+ new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2);
+ InstanceOfAsBool(unary_checks, type, results);
+ if (results->length() == unary_checks.NumberOfChecks() * 2) {
+ const bool can_deopt = TryExpandTestCidsResult(results, type);
+ if (can_deopt && !IsAllowedForInlining(call->deopt_id())) {
+ // Guard against repeated speculative inlining.
+ return;
+ }
+ TestCidsInstr* test_cids = new(Z) TestCidsInstr(
+ call->token_pos(),
+ negate ? Token::kISNOT : Token::kIS,
+ new(Z) Value(left),
+ *results,
+ can_deopt ? call->deopt_id() : Thread::kNoDeoptId);
+ // Remove type.
+ ReplaceCall(call, test_cids);
+ return;
+ }
+ }
+
InstanceOfInstr* instance_of =
new(Z) InstanceOfInstr(call->token_pos(),
new(Z) Value(left),
@@ -2228,11 +2221,6 @@ void AotOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
// TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids).
void AotOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) {
ASSERT(Token::IsTypeCastOperator(call->token_kind()));
- // Guard against repeated speculative inlining.
- if (!use_speculative_inlining_ ||
- IsBlackListedForInlining(call->deopt_id())) {
- return;
- }
Definition* left = call->ArgumentAt(0);
Definition* type_args = call->ArgumentAt(1);
const AbstractType& type =
@@ -2247,6 +2235,10 @@ void AotOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) {
const Bool& as_bool = Bool::ZoneHandle(Z,
InstanceOfAsBool(unary_checks, type, results));
if (as_bool.raw() == Bool::True().raw()) {
+ // Guard against repeated speculative inlining.
+ if (!IsAllowedForInlining(call->deopt_id())) {
+ return;
+ }
AddReceiverCheck(call);
// Remove the original push arguments.
for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
@@ -2272,11 +2264,12 @@ void AotOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) {
}
-bool AotOptimizer::IsBlackListedForInlining(intptr_t call_deopt_id) {
+bool AotOptimizer::IsAllowedForInlining(intptr_t call_deopt_id) {
+ if (!use_speculative_inlining_) return false;
for (intptr_t i = 0; i < inlining_black_list_->length(); ++i) {
- if ((*inlining_black_list_)[i] == call_deopt_id) return true;
+ if ((*inlining_black_list_)[i] == call_deopt_id) return false;
}
- return false;
+ return true;
}
@@ -2329,8 +2322,7 @@ void AotOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
return;
}
- if (use_speculative_inlining_ &&
- !IsBlackListedForInlining(instr->deopt_id()) &&
+ if (IsAllowedForInlining(instr->deopt_id()) &&
(unary_checks.NumberOfChecks() > 0)) {
if ((op_kind == Token::kINDEX) && TryReplaceWithIndexedOp(instr)) {
return;

Powered by Google App Engine
This is Rietveld 408576698