[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);