Index: runtime/vm/flow_graph.cc |
diff --git a/runtime/vm/flow_graph.cc b/runtime/vm/flow_graph.cc |
index a5cadf04173fc9749c9b3e9e511986c453d7b3db..c2aa1c77810036319e70fb5b695a13ad679524f2 100644 |
--- a/runtime/vm/flow_graph.cc |
+++ b/runtime/vm/flow_graph.cc |
@@ -5,6 +5,7 @@ |
#include "vm/flow_graph.h" |
#include "vm/bit_vector.h" |
+#include "vm/cha.h" |
#include "vm/flow_graph_builder.h" |
#include "vm/flow_graph_compiler.h" |
#include "vm/flow_graph_range_analysis.h" |
@@ -372,6 +373,54 @@ static void VerifyUseListsInInstruction(Instruction* instr) { |
} |
+static bool IsReceiver(Definition* def, BitVector* processed) { |
+ if (def->IsParameter() && (def->AsParameter()->index() == 0)) return true; |
Vyacheslav Egorov (Google)
2016/03/30 16:59:20
Maybe
if (def->IsParameter() return (def->AsParam
Florian Schneider
2016/03/30 21:03:57
Done.
|
+ if (!def->IsPhi()) return false; |
+ PhiInstr* phi = def->AsPhi(); |
+ if (processed->Contains(phi->ssa_temp_index())) return true; |
+ processed->Add(phi->ssa_temp_index()); |
+ for (intptr_t i = 0; i < phi->InputCount(); ++i) { |
+ if (!IsReceiver(phi->InputAt(i)->definition(), processed)) return false; |
Vyacheslav Egorov (Google)
2016/03/30 16:59:20
Please add a comment that we are not reusing proce
Florian Schneider
2016/03/30 21:03:57
Done. Rewrote computation to store the result at e
|
+ } |
+ return true; |
+} |
+ |
+ |
+// 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 FlowGraph::InstanceCallNeedsClassCheck(InstanceCallInstr* call, |
+ RawFunction::Kind kind) const { |
+ if (!FLAG_use_cha_deopt && !isolate()->all_classes_finalized()) { |
+ // Even if class or function are private, lazy class finalization |
+ // may later add overriding methods. |
+ return true; |
+ } |
+ Definition* callee_receiver = call->ArgumentAt(0); |
+ ASSERT(callee_receiver != NULL); |
+ if (function().IsDynamicFunction() && |
+ IsReceiver(callee_receiver, |
Vyacheslav Egorov (Google)
2016/03/30 16:59:20
I find it somewhat expensive not only to repeat th
Florian Schneider
2016/03/30 21:03:57
Good point. It should not take extra space anyway.
|
+ new(zone()) BitVector(zone(), |
+ max_virtual_register_number()))) { |
+ const String& name = (kind == RawFunction::kMethodExtractor) |
+ ? String::Handle(zone(), Field::NameFromGetter(call->function_name())) |
+ : call->function_name(); |
+ const Class& cls = Class::Handle(zone(), function().Owner()); |
+ if (!thread()->cha()->HasOverride(cls, name)) { |
+ if (FLAG_trace_cha) { |
+ THR_Print(" **(CHA) Instance call needs no check, " |
+ "no overrides of '%s' '%s'\n", |
+ name.ToCString(), cls.ToCString()); |
+ } |
+ thread()->cha()->AddToLeafClasses(cls); |
+ return false; |
+ } |
+ } |
+ return true; |
+} |
+ |
+ |
+ |
bool FlowGraph::VerifyUseLists() { |
// Verify the initial definitions. |
for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); ++i) { |