[vm/interpreter] Fix PC offsets of bytecode try blocks in PcDescriptors

When looking for an exception handler, PC corresponding to a return
address is used (e.g. it is pointing to the next instruction).
This CL adjusts start and end offsets of bytecode try blocks in
PcDescriptors accordingly.

Change-Id: Ib12d8d11c37443fde93b3e1739c785effc5a922c
Reviewed-on: https://dart-review.googlesource.com/70120
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Régis Crelier <regis@google.com>
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc
index fe7750d..1f6e9e6 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.cc
+++ b/runtime/vm/compiler/frontend/bytecode_reader.cc
@@ -544,9 +544,13 @@
     for (intptr_t try_index = 0; try_index < try_block_count; try_index++) {
       intptr_t outer_try_index_plus1 = helper_->reader_.ReadUInt();
       intptr_t outer_try_index = outer_try_index_plus1 - 1;
-      intptr_t start_pc = sizeof(KBCInstr) * helper_->reader_.ReadUInt();
-      intptr_t end_pc = sizeof(KBCInstr) * helper_->reader_.ReadUInt();
-      intptr_t handler_pc = sizeof(KBCInstr) * helper_->reader_.ReadUInt();
+      // PcDescriptors are expressed in terms of return addresses.
+      intptr_t start_pc = KernelBytecode::BytecodePcToOffset(
+          helper_->reader_.ReadUInt(), /* is_return_address = */ true);
+      intptr_t end_pc = KernelBytecode::BytecodePcToOffset(
+          helper_->reader_.ReadUInt(), /* is_return_address = */ true);
+      intptr_t handler_pc = KernelBytecode::BytecodePcToOffset(
+          helper_->reader_.ReadUInt(), /* is_return_address = */ false);
       uint8_t flags = helper_->reader_.ReadByte();
       const uint8_t kFlagNeedsStackTrace = 1 << 0;
       const uint8_t kFlagIsSynthetic = 1 << 1;
diff --git a/runtime/vm/constants_kbc.h b/runtime/vm/constants_kbc.h
index 45f1aff..9beae96 100644
--- a/runtime/vm/constants_kbc.h
+++ b/runtime/vm/constants_kbc.h
@@ -1126,6 +1126,17 @@
 
   static KBCInstr At(uword pc) { return *reinterpret_cast<KBCInstr*>(pc); }
 
+  // Converts bytecode PC into an offset.
+  // For return addresses used in PcDescriptors, PC is also advanced to the
+  // next instruction.
+  static intptr_t BytecodePcToOffset(uint32_t pc, bool is_return_address) {
+    return sizeof(KBCInstr) * (pc + (is_return_address ? 1 : 0));
+  }
+
+  static uint32_t OffsetToBytecodePc(intptr_t offset, bool is_return_address) {
+    return (offset / sizeof(KBCInstr)) - (is_return_address ? 1 : 0);
+  }
+
  private:
   DISALLOW_ALLOCATION();
   DISALLOW_IMPLICIT_CONSTRUCTORS(KernelBytecode);