Index: runtime/vm/intermediate_language.cc |
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc |
index 250651e3bb61c3cee1b4fec56e64c5add6da63d7..17e86baedb6d2c771b6198e9d64adebf5f2ea91a 100644 |
--- a/runtime/vm/intermediate_language.cc |
+++ b/runtime/vm/intermediate_language.cc |
@@ -2530,6 +2530,41 @@ void TargetEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
} |
+void IndirectGotoInstr::ComputeOffsetTable(Isolate* isolate) { |
+ if (GetBlock()->offset() < 0) { |
+ // Don't generate a table when contained in an unreachable block. |
+ return; |
+ } |
+ ASSERT(SuccessorCount() == offsets_.Capacity()); |
+ offsets_.SetLength(SuccessorCount()); |
+ for (intptr_t i = 0; i < SuccessorCount(); i++) { |
+ TargetEntryInstr* target = SuccessorAt(i); |
+ intptr_t offset = target->offset(); |
+ |
+ // The intermediate block might be compacted, if so, use the indirect entry. |
+ if (offset < 0) { |
+ // Optimizations might have modified the immediate target block, but it |
+ // must end with a goto to the indirect entry. Also, we can't use |
+ // last_instruction because 'target' is compacted/unreachable. |
+ Instruction* last = target->next(); |
+ while (last != NULL && !last->IsGoto()) { |
+ last = last->next(); |
+ } |
+ ASSERT(last); |
+ IndirectEntryInstr* ientry = |
+ last->AsGoto()->successor()->AsIndirectEntry(); |
+ ASSERT(ientry != NULL); |
+ ASSERT(ientry->indirect_id() == i); |
+ offset = ientry->offset(); |
+ } |
+ |
+ ASSERT(offset > 0); |
+ offset -= Assembler::EntryPointToPcMarkerOffset(); |
+ offsets_.SetAt(i, Smi::ZoneHandle(isolate, Smi::New(offset))); |
+ } |
+} |
+ |
+ |
LocationSummary* IndirectEntryInstr::MakeLocationSummary( |
Isolate* isolate, bool optimizing) const { |
return JoinEntryInstr::MakeLocationSummary(isolate, optimizing); |