• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef PANDA_VERIFICATION_ABSINT_ABS_INT_INL_H
17 #define PANDA_VERIFICATION_ABSINT_ABS_INT_INL_H
18 
19 #include "abs_int_inl_compat_checks.h"
20 #include "bytecode_instruction-inl.h"
21 #include "file_items.h"
22 #include "include/mem/panda_containers.h"
23 #include "include/method.h"
24 #include "include/runtime.h"
25 #include "lang_specifics.h"
26 #include "macros.h"
27 #include "panda_types.h"
28 #include "runtime/include/class.h"
29 #include "runtime/interpreter/runtime_interface.h"
30 #include "type/type_system.h"
31 #include "util/lazy.h"
32 #include "utils/logger.h"
33 #include "util/str.h"
34 #include "verification/config/debug_breakpoint/breakpoint.h"
35 #include "verification/config/whitelist/whitelist.h"
36 #include "verification_context.h"
37 #include "verification/jobs/cache.h"
38 #include "verification_status.h"
39 #include "verifier_messages.h"
40 
41 #include <array>
42 #include <cmath>
43 #include <cstdint>
44 #include <functional>
45 #include <iomanip>
46 #include <limits>
47 #include <memory>
48 #include <type_traits>
49 #include <unordered_map>
50 
51 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
52 #define LOG_INST()                                             \
53     do {                                                       \
54         if (!GetInst().IsValid()) {                            \
55             SHOW_MSG(InvalidInstruction)                       \
56             LOG_VERIFIER_INVALID_INSTRUCTION();                \
57             END_SHOW_MSG();                                    \
58             SET_STATUS_FOR_MSG(InvalidInstruction);            \
59             return false;                                      \
60         }                                                      \
61         if (CurrentJob.Options().ShowContext()) {              \
62             DumpRegs(ExecCtx().CurrentRegContext());           \
63         }                                                      \
64         SHOW_MSG(DebugAbsIntLogInstruction)                    \
65         LOG_VERIFIER_DEBUG_ABS_INT_LOG_INSTRUCTION(GetInst()); \
66         END_SHOW_MSG();                                        \
67     } while (0)
68 
69 #ifndef NDEBUG
70 #define DBGBRK()                                                             \
71     if (debug_) {                                                            \
72         DBG_MANAGED_BRK(CurrentJob.JobCachedMethod().id, inst_.GetOffset()); \
73     }
74 #else
75 #define DBGBRK()
76 #endif
77 
78 #define MSG(Message) CurrentJob.Options().Msg(VerifierMessage::Message)
79 
80 #define SHOW_MSG(Message) \
81     MSG(Message).IfNotHidden([&]{
82 #define END_SHOW_MSG() \
83     })
84 
85 #define SET_STATUS_FOR_MSG(Message)                                         \
86     do {                                                                    \
87         MSG(Message).IfWarning([&] {                                        \
88             if (status_ != VerificationStatus::ERROR) {                     \
89                 status_ = VerificationStatus::WARNING;                      \
90             }                                                               \
91         });                                                                 \
92         MSG(Message).IfError([&] { status_ = VerificationStatus::ERROR; }); \
93     } while (0)
94 
95 /*
96 TODO(vdyadov): add AddrMap to verification context where put marks on all checked bytes.
97 after absint process ends, check this AddrMap for holes.
98 holes are either dead byte-code or issues with absint cflow handling.
99 */
100 
101 // TODO(vdyadov): refactor this file, all utility functions put in separate/other files
102 
103 /*
104 TODO(vdyadov): IMPORTANT!!! (Done)
105 Current definition of context incompatibility is NOT CORRECT one!
106 There are situations when verifier will rule out fully correct programs.
107 For instance:
108 ....
109 movi v0,0
110 ldai 0
111 jmp label1
112 ....
113 lda.str ""
114 sta v0
115 ldai 0
116 jmp label1
117 .....
118 label1:
119   return
120 
121 Here we have context incompatibility on label1, but it does not harm, because conflicting reg is
122 not used anymore.
123 
124 Solutions:
125 1(current). Conflicts are reported as warnings, conflicting regs are removed fro resulting context.
126 So, on attempt of usage of conflicting reg, absint will fail with message of undefined reg.
127 May be mark them as conflicting? (done)
128 2. On each label/checkpoint compute set of registers that will be used in next conputations and process
129 conflicting contexts modulo used registers set. It is complex solution, but very preciese.
130 */
131 
132 // TODO(vdyadov): regain laziness, strict evaluation is very expensive!
133 
134 namespace panda::verifier {
135 template <typename Handler>
FilterItems(const PandaVector<Type> & items,Handler && handler)136 PandaVector<Type> FilterItems(const PandaVector<Type> &items, Handler &&handler)
137 {
138     PandaVector<Type> result;
139     for (const auto &item : items) {
140         if (handler(item)) {
141             result.push_back(item);
142         }
143     }
144     return result;
145 }
146 
147 template <typename Handler>
IsItemPresent(const PandaVector<Type> & items,Handler && handler)148 bool IsItemPresent(const PandaVector<Type> &items, Handler &&handler)
149 {
150     for (const auto &item : items) {
151         if (handler(item)) {
152             return true;
153         }
154     }
155     return false;
156 }
157 
158 class AbsIntInstructionHandler {
159 public:
160     static constexpr int ACC = -1;
161     static constexpr int INVALID_REG = -2;  // TODO(vdyadov): may be use Index<..> here?
162 
163     using TypeId = panda_file::Type::TypeId;
164 
165     const Type &U1;
166     const Type &I8;
167     const Type &U8;
168     const Type &I16;
169     const Type &U16;
170     const Type &I32;
171     const Type &U32;
172     const Type &I64;
173     const Type &U64;
174     const Type &F32;
175     const Type &F64;
176 
177     const Job &CurrentJob;
178 
AbsIntInstructionHandler(VerificationContext & verif_ctx,const uint8_t * pc,EntryPointType code_type)179     AbsIntInstructionHandler(VerificationContext &verif_ctx, const uint8_t *pc, EntryPointType code_type)
180         : U1 {verif_ctx.Types().U1()},
181           I8 {verif_ctx.Types().I8()},
182           U8 {verif_ctx.Types().U8()},
183           I16 {verif_ctx.Types().I16()},
184           U16 {verif_ctx.Types().U16()},
185           I32 {verif_ctx.Types().I32()},
186           U32 {verif_ctx.Types().U32()},
187           I64 {verif_ctx.Types().I64()},
188           U64 {verif_ctx.Types().U64()},
189           F32 {verif_ctx.Types().F32()},
190           F64 {verif_ctx.Types().F64()},
191           CurrentJob {verif_ctx.GetJob()},
192           inst_(pc, verif_ctx.CflowInfo().InstMap().AddrStart<const uint8_t *>(),
193                 verif_ctx.CflowInfo().InstMap().AddrEnd<const uint8_t *>()),
194           context_ {verif_ctx},
195           status_ {VerificationStatus::OK},
196           code_type_ {code_type}
197     {
198 #ifndef NDEBUG
199         if (Runtime::GetCurrent()->GetVerificationOptions().Mode == VerificationMode::DEBUG) {
200             const auto &method = CurrentJob.JobCachedMethod();
201             debug_ = debug::ManagedBreakpointPresent(method.id);
202             if (debug_) {
203                 LOG(DEBUG, VERIFIER) << "Debug mode for method " << method.GetName() << " is on";
204             }
205         }
206 #endif
207     }
208 
209     ~AbsIntInstructionHandler() = default;
210 
GetStatus()211     VerificationStatus GetStatus()
212     {
213         return status_;
214     }
215 
GetPrimaryOpcode()216     uint8_t GetPrimaryOpcode()
217     {
218         return inst_.GetPrimaryOpcode();
219     }
220 
GetSecondaryOpcode()221     uint8_t GetSecondaryOpcode()
222     {
223         return inst_.GetSecondaryOpcode();
224     }
225 
IsPrimaryOpcodeValid()226     bool IsPrimaryOpcodeValid() const
227     {
228         return inst_.IsPrimaryOpcodeValid();
229     }
230 
231     bool IsRegDefined(int reg);
232 
233     const PandaString &ImageOf(const Type &type);
234 
235     PandaString ImageOf(const AbstractType &abstract_type);
236 
237     PandaString ImageOf(const TypeSet &types);
238 
239     template <typename Container>
ImagesOf(const Container & types)240     PandaString ImagesOf(const Container &types)
241     {
242         PandaString result {"[ "};
243         bool comma = false;
244         for (const auto &type : types) {
245             if (comma) {
246                 result += ", ";
247             }
248             result += ImageOf(type);
249             comma = true;
250         }
251         result += " ]";
252         return result;
253     }
254 
255     PandaVector<Type> SubtypesOf(const PandaVector<Type> &types);
256     PandaVector<Type> SubtypesOf(std::initializer_list<Type> types);
257 
258     PandaVector<Type> SupertypesOf(const PandaVector<Type> &types);
259     PandaVector<Type> SupertypesOf(std::initializer_list<Type> types);
260 
261     template <typename Container>
CheckTypes(const Type & type,const Container & tgt_types)262     bool CheckTypes(const Type &type, const Container &tgt_types)
263     {
264         for (const auto &t : tgt_types) {
265             if (type <= t) {
266                 return true;
267             }
268         }
269         return false;
270     }
271 
272     template <typename Container>
CheckTypes(const AbstractType & type,const Container & tgt_types)273     bool CheckTypes(const AbstractType &type, const Container &tgt_types)
274     {
275         for (const auto &t : tgt_types) {
276             if (type.ExistsType([&](auto type1) { return type1 <= t; })) {
277                 return true;
278             }
279         }
280         return false;
281     }
282 
283     template <typename Container>
CheckRegTypes(int reg,const Container & tgt_types)284     bool CheckRegTypes(int reg, const Container &tgt_types)
285     {
286         if (!IsRegDefined(reg)) {
287             return false;
288         }
289         auto &&type = GetRegType(reg);
290 
291         if (CheckTypes(type, tgt_types)) {
292             return true;
293         }
294 
295         SHOW_MSG(BadRegisterType)
296         LOG_VERIFIER_BAD_REGISTER_TYPE(RegisterName(reg, true), ImageOf(type), ImagesOf(tgt_types),
297                                        ImagesOf(SubtypesOf(tgt_types)));
298         END_SHOW_MSG();
299         return false;
300     }
301 
CheckRegTypesTakingIntoAccountTypecasts(int reg,Type type)302     bool CheckRegTypesTakingIntoAccountTypecasts(int reg, Type type)
303     {
304         if (!IsRegDefined(reg)) {
305             return false;
306         }
307         bool result = false;
308         auto handler = [&result, &type](const AbstractTypedValue &atv) {
309             const auto &at = atv.GetAbstractType();
310             if (at.IsType()) {
311                 if (at.GetType() <= type) {
312                     result = true;
313                 }
314             } else if (at.IsTypeSet()) {
315                 at.GetTypeSet().ForAll([&](const Type &type_in_at) {
316                     if (type_in_at <= type) {
317                         result = true;
318                     }
319                     return !result;
320                 });
321             }
322             return !result;
323         };
324         ExecCtx().ForAllTypesOfRegAccordingToTypecasts(reg, ExecCtx().CurrentRegContext(), handler);
325         return result;
326     }
327 
328     bool CheckRegTypes(int reg, std::initializer_list<Type> types);
329 
330     bool CheckTypes(const Type &type, std::initializer_list<Type> types);
331 
CheckTypes(const AbstractType & type,std::initializer_list<Type> types)332     bool CheckTypes(const AbstractType &type, std::initializer_list<Type> types)
333     {
334         return CheckTypes<std::initializer_list<Type>>(type, types);
335     }
336 
337     const AbstractTypedValue &GetReg(int reg_idx);
338 
339     const AbstractType &GetRegType(int reg_idx);
340 
341     void SetReg(int reg_idx, const AbstractTypedValue &val);
342     void SetReg(int reg_idx, const AbstractType &type);
343 
344     void SetRegAndOthersOfSameOrigin(int reg_idx, const AbstractTypedValue &val);
345     void SetRegAndOthersOfSameOrigin(int reg_idx, const AbstractType &type);
346 
347     const AbstractTypedValue &GetAcc();
348 
349     const AbstractType &GetAccType();
350 
351     void SetAcc(const AbstractTypedValue &val);
352     void SetAcc(const AbstractType &type);
353 
354     void SetAccAndOthersOfSameOrigin(const AbstractTypedValue &val);
355     void SetAccAndOthersOfSameOrigin(const AbstractType &type);
356 
357     template <typename T>
MkVal(T t)358     AbstractTypedValue MkVal(T t)
359     {
360         return AbstractTypedValue {Types().TypeOf(t), context_.NewVar()};
361     }
362 
363     AbstractTypedValue MkVal(const AbstractType &t);
364 
365     PandaTypes &Types();
366 
367     const Type &ReturnType();
368 
369     ExecContext &ExecCtx();
370 
371     void DumpRegs(const RegContext &ctx);
372 
373     bool CheckCtxCompatibility(const RegContext &src, const RegContext &dst);
374 
375     void Sync();
376 
AssignRegToReg(int dst,int src)377     void AssignRegToReg(int dst, int src)
378     {
379         auto atv = GetReg(src);
380         if (!atv.GetOrigin().IsValid()) {
381             // generate new origin and set all values to be originated at it
382             AbstractTypedValue new_atv {atv, inst_};
383             SetReg(src, new_atv);
384             SetReg(dst, new_atv);
385         } else {
386             SetReg(dst, atv);
387         }
388     }
389 
AssignAccToReg(int src)390     void AssignAccToReg(int src)
391     {
392         AssignRegToReg(ACC, src);
393     }
394 
AssignRegToAcc(int dst)395     void AssignRegToAcc(int dst)
396     {
397         AssignRegToReg(dst, ACC);
398     }
399 
400     template <BytecodeInstructionSafe::Format format>
HandleNop()401     bool HandleNop()
402     {
403         LOG_INST();
404         DBGBRK();
405         Sync();
406         MoveToNextInst<format>();
407         return true;
408     }
409 
410     // Names meanings: vs - v_source, vd - v_destination
411     template <BytecodeInstructionSafe::Format format>
HandleMov()412     bool HandleMov()
413     {
414         LOG_INST();
415         DBGBRK();
416         uint16_t vd = inst_.GetVReg<format, 0x00>();
417         uint16_t vs = inst_.GetVReg<format, 0x01>();
418         Sync();
419         if (!CheckRegTypes(vs, {Types().Bits32Type()})) {
420             SET_STATUS_FOR_MSG(BadRegisterType);
421             SET_STATUS_FOR_MSG(UndefinedRegister);
422             return false;
423         }
424         AssignRegToReg(vd, vs);
425         MoveToNextInst<format>();
426         return true;
427     }
428 
429     template <BytecodeInstructionSafe::Format format>
HandleMovWide()430     bool HandleMovWide()
431     {
432         LOG_INST();
433         DBGBRK();
434         uint16_t vd = inst_.GetVReg<format, 0x00>();
435         uint16_t vs = inst_.GetVReg<format, 0x01>();
436         Sync();
437         if (!CheckRegTypes(vs, {Types().Bits64Type()})) {
438             SET_STATUS_FOR_MSG(BadRegisterType);
439             SET_STATUS_FOR_MSG(UndefinedRegister);
440             return false;
441         }
442         AssignRegToReg(vd, vs);
443         MoveToNextInst<format>();
444         return true;
445     }
446 
447     template <BytecodeInstructionSafe::Format format>
HandleMovObj()448     bool HandleMovObj()
449     {
450         LOG_INST();
451         DBGBRK();
452         uint16_t vd = inst_.GetVReg<format, 0x00>();
453         uint16_t vs = inst_.GetVReg<format, 0x01>();
454         Sync();
455         if (!CheckRegTypes(vs, {Types().RefType()})) {
456             SET_STATUS_FOR_MSG(BadRegisterType);
457             SET_STATUS_FOR_MSG(UndefinedRegister);
458             return false;
459         }
460         AssignRegToReg(vd, vs);
461         MoveToNextInst<format>();
462         return true;
463     }
464 
465     template <BytecodeInstructionSafe::Format format>
HandleMovDyn()466     bool HandleMovDyn()
467     {
468         // TODO(vdyadov): implement
469         LOG(ERROR, VERIFIER) << "Verifier error: instruction is not implemented";
470         status_ = VerificationStatus::ERROR;
471         return false;
472     }
473 
474     template <BytecodeInstructionSafe::Format format>
HandleMovi()475     bool HandleMovi()
476     {
477         LOG_INST();
478         DBGBRK();
479         uint16_t vd = inst_.GetVReg<format>();
480         Sync();
481         SetReg(vd, I32);
482         MoveToNextInst<format>();
483         return true;
484     }
485 
486     template <BytecodeInstructionSafe::Format format>
HandleMoviDyn()487     bool HandleMoviDyn()
488     {
489         // TODO(vdyadov): implement
490         LOG(ERROR, VERIFIER) << "Verifier error: instruction is not implemented";
491         status_ = VerificationStatus::ERROR;
492         return true;
493     }
494 
495     template <BytecodeInstructionSafe::Format format>
HandleMoviWide()496     bool HandleMoviWide()
497     {
498         LOG_INST();
499         DBGBRK();
500         uint16_t vd = inst_.GetVReg<format>();
501         Sync();
502         SetReg(vd, I64);
503         MoveToNextInst<format>();
504         return true;
505     }
506 
507     template <BytecodeInstructionSafe::Format format>
HandleFmovi()508     bool HandleFmovi()
509     {
510         LOG_INST();
511         DBGBRK();
512         uint16_t vd = inst_.GetVReg<format>();
513         Sync();
514         SetReg(vd, F32);
515         MoveToNextInst<format>();
516         return true;
517     }
518 
519     template <BytecodeInstructionSafe::Format format>
HandleFmoviWide()520     bool HandleFmoviWide()
521     {
522         LOG_INST();
523         DBGBRK();
524         uint16_t vd = inst_.GetVReg<format>();
525         Sync();
526         SetReg(vd, F64);
527         MoveToNextInst<format>();
528         return true;
529     }
530 
531     template <BytecodeInstructionSafe::Format format>
HandleMovNull()532     bool HandleMovNull()
533     {
534         LOG_INST();
535         DBGBRK();
536         uint16_t vd = inst_.GetVReg<format>();
537         Sync();
538         SetReg(vd, Types().NullRefType());
539         MoveToNextInst<format>();
540         return true;
541     }
542 
543     template <BytecodeInstructionSafe::Format format>
HandleLdglobalDyn()544     bool HandleLdglobalDyn()
545     {
546         // TODO(vdyadov): implement
547         MoveToNextInst<format>();
548         LOG(ERROR, VERIFIER) << "Verifier error: instruction is not implemented";
549         status_ = VerificationStatus::ERROR;
550         return false;
551     }
552 
553     template <BytecodeInstructionSafe::Format format>
HandleLda()554     bool HandleLda()
555     {
556         LOG_INST();
557         DBGBRK();
558         uint16_t vs = inst_.GetVReg<format>();
559         Sync();
560         if (!CheckRegTypes(vs, {Types().Bits32Type()})) {
561             SET_STATUS_FOR_MSG(BadRegisterType);
562             SET_STATUS_FOR_MSG(UndefinedRegister);
563             return false;
564         }
565         AssignAccToReg(vs);
566         MoveToNextInst<format>();
567         return true;
568     }
569 
570     template <BytecodeInstructionSafe::Format format>
HandleLdaDyn()571     bool HandleLdaDyn()
572     {
573         LOG_INST();
574         DBGBRK();
575         // TODO(vdyadov): implement
576         Sync();
577         MoveToNextInst<format>();
578         LOG(ERROR, VERIFIER) << "Verifier error: instruction is not implemented";
579         status_ = VerificationStatus::ERROR;
580         return false;
581     }
582 
583     template <BytecodeInstructionSafe::Format format>
HandleLdaiDyn()584     bool HandleLdaiDyn()
585     {
586         LOG_INST();
587         DBGBRK();
588         // TODO(vdyadov): implement
589         Sync();
590         MoveToNextInst<format>();
591         LOG(ERROR, VERIFIER) << "Verifier error: instruction is not implemented";
592         status_ = VerificationStatus::ERROR;
593         return false;
594     }
595 
596     template <BytecodeInstructionSafe::Format format>
HandleLdaWide()597     bool HandleLdaWide()
598     {
599         LOG_INST();
600         DBGBRK();
601         uint16_t vs = inst_.GetVReg<format>();
602         Sync();
603         if (!CheckRegTypes(vs, {Types().Bits64Type()})) {
604             SET_STATUS_FOR_MSG(BadRegisterType);
605             SET_STATUS_FOR_MSG(UndefinedRegister);
606             return false;
607         }
608         AssignAccToReg(vs);
609         MoveToNextInst<format>();
610         return true;
611     }
612 
613     template <BytecodeInstructionSafe::Format format>
HandleLdaObj()614     bool HandleLdaObj()
615     {
616         LOG_INST();
617         DBGBRK();
618         uint16_t vs = inst_.GetVReg<format>();
619         Sync();
620         if (!CheckRegTypes(vs, {Types().RefType()})) {
621             SET_STATUS_FOR_MSG(BadRegisterType);
622             SET_STATUS_FOR_MSG(UndefinedRegister);
623             return false;
624         }
625         AssignAccToReg(vs);
626         MoveToNextInst<format>();
627         return true;
628     }
629 
630     template <BytecodeInstructionSafe::Format format>
HandleLdobjDyn()631     bool HandleLdobjDyn()
632     {
633         LOG_INST();
634         DBGBRK();
635         // TODO(vdyadov): implement
636         Sync();
637         MoveToNextInst<format>();
638         LOG(ERROR, VERIFIER) << "Verifier error: instruction is not implemented";
639         status_ = VerificationStatus::ERROR;
640         return false;
641     }
642 
643     template <BytecodeInstructionSafe::Format format>
HandleLdai()644     bool HandleLdai()
645     {
646         LOG_INST();
647         DBGBRK();
648         Sync();
649         SetAcc(I32);
650         MoveToNextInst<format>();
651         return true;
652     }
653 
654     template <BytecodeInstructionSafe::Format format>
HandleLdaiWide()655     bool HandleLdaiWide()
656     {
657         LOG_INST();
658         DBGBRK();
659         Sync();
660         SetAcc(I64);
661         MoveToNextInst<format>();
662         return true;
663     }
664 
665     template <BytecodeInstructionSafe::Format format>
HandleFldai()666     bool HandleFldai()
667     {
668         LOG_INST();
669         DBGBRK();
670         Sync();
671         SetAcc(F32);
672         MoveToNextInst<format>();
673         return true;
674     }
675 
676     template <BytecodeInstructionSafe::Format format>
HandleFldaiWide()677     bool HandleFldaiWide()
678     {
679         LOG_INST();
680         DBGBRK();
681         Sync();
682         SetAcc(F64);
683         MoveToNextInst<format>();
684         return true;
685     }
686 
687     template <BytecodeInstructionSafe::Format format>
HandleFldaiDyn()688     bool HandleFldaiDyn()
689     {
690         LOG_INST();
691         DBGBRK();
692         // TODO(vdyadov): implement
693         LOG(ERROR, VERIFIER) << "Verifier error: instruction is not implemented";
694         status_ = VerificationStatus::ERROR;
695         return false;
696     }
697 
698     template <BytecodeInstructionSafe::Format format>
HandleLdaStr()699     bool HandleLdaStr()
700     {
701         LOG_INST();
702         DBGBRK();
703         Sync();
704         const auto *cached_class = GetCachedClass();
705         if (cached_class == nullptr) {
706             SET_STATUS_FOR_MSG(CannotResolveClassId);
707             return false;
708         }
709         auto type = Types().TypeOf(*cached_class);
710         SetAcc(type);
711         MoveToNextInst<format>();
712         return true;
713     }
714 
715     template <BytecodeInstructionSafe::Format format>
HandleLdaConst()716     bool HandleLdaConst()
717     {
718         LOG_INST();
719         DBGBRK();
720         uint16_t vd = inst_.GetVReg<format, 0>();
721         Sync();
722         const CachedClass *cached_class = GetCachedClass();
723         if (cached_class == nullptr) {
724             // TODO(vdyadov): refactor to verifier-messages
725             LOG(ERROR, VERIFIER) << "Verifier error: HandleLdaConst cache error";
726             status_ = VerificationStatus::ERROR;
727             return false;
728         }
729         auto type = Types().TypeOf(*cached_class);
730         SetReg(vd, type);
731         MoveToNextInst<format>();
732         return true;
733     }
734 
735     template <BytecodeInstructionSafe::Format format>
HandleLdaType()736     bool HandleLdaType()
737     {
738         LOG_INST();
739         DBGBRK();
740         Sync();
741         auto *cached_class = GetCachedClass();
742         if (cached_class == nullptr) {
743             SET_STATUS_FOR_MSG(CannotResolveClassId);
744             return false;
745         }
746         auto type = Types().TypeOf(*cached_class);
747         if (!type.IsValid()) {
748             LOG(DEBUG, VERIFIER) << "LDA_TYPE type of class is not valid.";
749             return false;
750         }
751         auto lang = CurrentJob.JobCachedMethod().GetSourceLang();
752         SetAcc(Types().Class(lang));
753         MoveToNextInst<format>();
754         return true;
755     }
756 
757     template <BytecodeInstructionSafe::Format format>
HandleLdaNull()758     bool HandleLdaNull()
759     {
760         LOG_INST();
761         DBGBRK();
762         Sync();
763         SetAcc(Types().NullRefType());
764         MoveToNextInst<format>();
765         return true;
766     }
767 
768     template <BytecodeInstructionSafe::Format format>
HandleSta()769     bool HandleSta()
770     {
771         LOG_INST();
772         DBGBRK();
773         uint16_t vd = inst_.GetVReg<format>();
774         Sync();
775         if (!CheckRegTypes(ACC, {Types().Bits32Type()})) {
776             SET_STATUS_FOR_MSG(BadRegisterType);
777             SET_STATUS_FOR_MSG(UndefinedRegister);
778             return false;
779         }
780         AssignRegToAcc(vd);
781         MoveToNextInst<format>();
782         return true;
783     }
784 
785     template <BytecodeInstructionSafe::Format format>
HandleStaDyn()786     bool HandleStaDyn()
787     {
788         LOG_INST();
789         DBGBRK();
790         // TODO(vdyadov): implement
791         Sync();
792         MoveToNextInst<format>();
793         LOG(ERROR, VERIFIER) << "Verifier error: instruction is not implemented";
794         status_ = VerificationStatus::ERROR;
795         return false;
796     }
797 
798     template <BytecodeInstructionSafe::Format format>
HandleStaWide()799     bool HandleStaWide()
800     {
801         LOG_INST();
802         DBGBRK();
803         uint16_t vd = inst_.GetVReg<format>();
804         Sync();
805         if (!CheckRegTypes(ACC, {Types().Bits64Type()})) {
806             SET_STATUS_FOR_MSG(BadRegisterType);
807             SET_STATUS_FOR_MSG(UndefinedRegister);
808             return false;
809         }
810         AssignRegToAcc(vd);
811         MoveToNextInst<format>();
812         return true;
813     }
814 
815     template <BytecodeInstructionSafe::Format format>
HandleStaObj()816     bool HandleStaObj()
817     {
818         LOG_INST();
819         DBGBRK();
820         uint16_t vd = inst_.GetVReg<format>();
821         Sync();
822         if (!CheckRegTypes(ACC, {Types().RefType()})) {
823             SET_STATUS_FOR_MSG(BadRegisterType);
824             SET_STATUS_FOR_MSG(UndefinedRegister);
825             return false;
826         }
827         AssignRegToAcc(vd);
828         MoveToNextInst<format>();
829         return true;
830     }
831 
832     template <BytecodeInstructionSafe::Format format>
HandleJmp()833     bool HandleJmp()
834     {
835         LOG_INST();
836         DBGBRK();
837         int32_t imm = inst_.GetImm<format>();
838         Sync();
839         ProcessBranching(imm);
840         return false;
841     }
842 
843     template <BytecodeInstructionSafe::Format format>
HandleCmpDyn()844     bool HandleCmpDyn()
845     {
846         LOG_INST();
847         DBGBRK();
848         // TODO(vdyadov): implement
849         Sync();
850         LOG(ERROR, VERIFIER) << "Verifier error: instruction is not implemented";
851         status_ = VerificationStatus::ERROR;
852         return false;
853     }
854 
855     template <BytecodeInstructionSafe::Format format>
HandleCmpWide()856     bool HandleCmpWide()
857     {
858         LOG_INST();
859         DBGBRK();
860         Sync();
861         return CheckBinaryOp2<format>(I64, I64, I32);
862     }
863 
864     template <BytecodeInstructionSafe::Format format>
HandleUcmp()865     bool HandleUcmp()
866     {
867         LOG_INST();
868         DBGBRK();
869         Sync();
870         return CheckBinaryOp2<format>(Types().Integral32Type(), Types().Integral32Type(), I32);
871     }
872 
873     template <BytecodeInstructionSafe::Format format>
HandleUcmpWide()874     bool HandleUcmpWide()
875     {
876         LOG_INST();
877         DBGBRK();
878         Sync();
879         return CheckBinaryOp2<format>(Types().Integral64Type(), Types().Integral64Type(), I32);
880     }
881 
882     template <BytecodeInstructionSafe::Format format>
HandleFcmpl()883     bool HandleFcmpl()
884     {
885         LOG_INST();
886         DBGBRK();
887         Sync();
888         return CheckBinaryOp2<format>(F32, F32, I32);
889     }
890 
891     template <BytecodeInstructionSafe::Format format>
HandleFcmplWide()892     bool HandleFcmplWide()
893     {
894         LOG_INST();
895         DBGBRK();
896         Sync();
897         return CheckBinaryOp2<format>(F64, F64, I32);
898     }
899 
900     template <BytecodeInstructionSafe::Format format>
HandleFcmpg()901     bool HandleFcmpg()
902     {
903         LOG_INST();
904         DBGBRK();
905         Sync();
906         return CheckBinaryOp2<format>(F32, F32, I32);
907     }
908 
909     template <BytecodeInstructionSafe::Format format>
HandleFcmpgWide()910     bool HandleFcmpgWide()
911     {
912         LOG_INST();
913         DBGBRK();
914         Sync();
915         return CheckBinaryOp2<format>(F64, F64, I32);
916     }
917 
918     template <BytecodeInstructionSafe::Format format>
HandleJeqz()919     bool HandleJeqz()
920     {
921         LOG_INST();
922         DBGBRK();
923         Sync();
924         return HandleCondJmpz<format, std::equal_to>();
925     }
926 
927     template <BytecodeInstructionSafe::Format format>
HandleJeqzObj()928     bool HandleJeqzObj()
929     {
930         LOG_INST();
931         DBGBRK();
932         auto imm = inst_.GetImm<format>();
933 
934         Sync();
935 
936         if (!CheckRegTypes(ACC, {Types().RefType()})) {
937             SET_STATUS_FOR_MSG(BadRegisterType);
938             SET_STATUS_FOR_MSG(UndefinedRegister);
939             return false;
940         }
941 
942         // TODO(vdyadov): think of two-pass absint, where we can catch const-null cases
943 
944         if (!ProcessBranching(imm)) {
945             return false;
946         }
947 
948         MoveToNextInst<format>();
949         return true;
950     }
951 
952     template <BytecodeInstructionSafe::Format format>
HandleJnez()953     bool HandleJnez()
954     {
955         LOG_INST();
956         DBGBRK();
957         Sync();
958         return HandleCondJmpz<format, std::not_equal_to>();
959     }
960 
961     template <BytecodeInstructionSafe::Format format>
HandleJnezObj()962     bool HandleJnezObj()
963     {
964         LOG_INST();
965         DBGBRK();
966         auto imm = inst_.GetImm<format>();
967         Sync();
968 
969         if (!CheckRegTypes(ACC, {Types().RefType()})) {
970             SET_STATUS_FOR_MSG(BadRegisterType);
971             SET_STATUS_FOR_MSG(UndefinedRegister);
972             return false;
973         }
974 
975         if (!ProcessBranching(imm)) {
976             return false;
977         }
978 
979         MoveToNextInst<format>();
980         return true;
981     }
982 
983     template <BytecodeInstructionSafe::Format format>
HandleJltz()984     bool HandleJltz()
985     {
986         LOG_INST();
987         DBGBRK();
988         Sync();
989         return HandleCondJmpz<format, std::less>();
990     }
991 
992     template <BytecodeInstructionSafe::Format format>
HandleJgtz()993     bool HandleJgtz()
994     {
995         LOG_INST();
996         DBGBRK();
997         Sync();
998         return HandleCondJmpz<format, std::greater>();
999     }
1000 
1001     template <BytecodeInstructionSafe::Format format>
HandleJlez()1002     bool HandleJlez()
1003     {
1004         LOG_INST();
1005         DBGBRK();
1006         Sync();
1007         return HandleCondJmpz<format, std::less_equal>();
1008     }
1009 
1010     template <BytecodeInstructionSafe::Format format>
HandleJgez()1011     bool HandleJgez()
1012     {
1013         LOG_INST();
1014         DBGBRK();
1015         Sync();
1016         return HandleCondJmpz<format, std::greater_equal>();
1017     }
1018 
1019     template <BytecodeInstructionSafe::Format format>
HandleJeq()1020     bool HandleJeq()
1021     {
1022         LOG_INST();
1023         DBGBRK();
1024         Sync();
1025         return HandleCondJmp<format, std::equal_to>();
1026     }
1027 
1028     template <BytecodeInstructionSafe::Format format>
HandleJeqObj()1029     bool HandleJeqObj()
1030     {
1031         LOG_INST();
1032         DBGBRK();
1033         auto imm = inst_.GetImm<format>();
1034         uint16_t vs = inst_.GetVReg<format>();
1035 
1036         Sync();
1037 
1038         if (!CheckRegTypes(ACC, {Types().RefType()})) {
1039             SET_STATUS_FOR_MSG(BadRegisterType);
1040             SET_STATUS_FOR_MSG(UndefinedRegister);
1041             return false;
1042         }
1043 
1044         if (!CheckRegTypes(vs, {Types().RefType()})) {
1045             SET_STATUS_FOR_MSG(BadRegisterType);
1046             SET_STATUS_FOR_MSG(UndefinedRegister);
1047             return false;
1048         }
1049 
1050         if (!ProcessBranching(imm)) {
1051             return false;
1052         }
1053 
1054         MoveToNextInst<format>();
1055         return true;
1056     }
1057 
1058     template <BytecodeInstructionSafe::Format format>
HandleJne()1059     bool HandleJne()
1060     {
1061         LOG_INST();
1062         DBGBRK();
1063         Sync();
1064         return HandleCondJmp<format, std::not_equal_to>();
1065     }
1066 
1067     template <BytecodeInstructionSafe::Format format>
HandleJneObj()1068     bool HandleJneObj()
1069     {
1070         LOG_INST();
1071         DBGBRK();
1072         auto imm = inst_.GetImm<format>();
1073         uint16_t vs = inst_.GetVReg<format>();
1074 
1075         Sync();
1076 
1077         if (!CheckRegTypes(ACC, {Types().RefType()})) {
1078             SET_STATUS_FOR_MSG(BadRegisterType);
1079             SET_STATUS_FOR_MSG(UndefinedRegister);
1080             return false;
1081         }
1082 
1083         if (!CheckRegTypes(vs, {Types().RefType()})) {
1084             SET_STATUS_FOR_MSG(BadRegisterType);
1085             SET_STATUS_FOR_MSG(UndefinedRegister);
1086             return false;
1087         }
1088 
1089         if (!ProcessBranching(imm)) {
1090             return false;
1091         }
1092 
1093         MoveToNextInst<format>();
1094         return true;
1095     }
1096 
1097     template <BytecodeInstructionSafe::Format format>
HandleJlt()1098     bool HandleJlt()
1099     {
1100         LOG_INST();
1101         DBGBRK();
1102         Sync();
1103         return HandleCondJmp<format, std::less>();
1104     }
1105 
1106     template <BytecodeInstructionSafe::Format format>
HandleJgt()1107     bool HandleJgt()
1108     {
1109         LOG_INST();
1110         DBGBRK();
1111         Sync();
1112         return HandleCondJmp<format, std::greater>();
1113     }
1114 
1115     template <BytecodeInstructionSafe::Format format>
HandleJle()1116     bool HandleJle()
1117     {
1118         LOG_INST();
1119         DBGBRK();
1120         Sync();
1121         return HandleCondJmp<format, std::less_equal>();
1122     }
1123 
1124     template <BytecodeInstructionSafe::Format format>
HandleJge()1125     bool HandleJge()
1126     {
1127         LOG_INST();
1128         DBGBRK();
1129         Sync();
1130         return HandleCondJmp<format, std::greater_equal>();
1131     }
1132 
1133     template <BytecodeInstructionSafe::Format format>
HandleAdd2()1134     bool HandleAdd2()
1135     {
1136         LOG_INST();
1137         DBGBRK();
1138         Sync();
1139         return CheckBinaryOp2<format>(Types().Integral32Type(), Types().Integral32Type(), I32);
1140     }
1141 
1142     template <BytecodeInstructionSafe::Format format>
HandleAdd2Dyn()1143     bool HandleAdd2Dyn()
1144     {
1145         LOG_INST();
1146         DBGBRK();
1147         // TODO(vdyadov): implement
1148         Sync();
1149         LOG(ERROR, VERIFIER) << "Verifier error: instruction is not implemented";
1150         status_ = VerificationStatus::ERROR;
1151         return false;
1152     }
1153 
1154     template <BytecodeInstructionSafe::Format format>
HandleAdd2Wide()1155     bool HandleAdd2Wide()
1156     {
1157         LOG_INST();
1158         DBGBRK();
1159         Sync();
1160         return CheckBinaryOp2<format>(Types().Integral64Type(), Types().Integral64Type(), I64);
1161     }
1162 
1163     template <BytecodeInstructionSafe::Format format>
HandleFadd2()1164     bool HandleFadd2()
1165     {
1166         LOG_INST();
1167         DBGBRK();
1168         Sync();
1169         return CheckBinaryOp2<format>(F32, F32, F32);
1170     }
1171 
1172     template <BytecodeInstructionSafe::Format format>
HandleFadd2Wide()1173     bool HandleFadd2Wide()
1174     {
1175         LOG_INST();
1176         DBGBRK();
1177         Sync();
1178         return CheckBinaryOp2<format>(F64, F64, F64);
1179     }
1180 
1181     template <BytecodeInstructionSafe::Format format>
HandleSub2()1182     bool HandleSub2()
1183     {
1184         LOG_INST();
1185         DBGBRK();
1186         Sync();
1187         return CheckBinaryOp2<format>(Types().Integral32Type(), Types().Integral32Type(), I32);
1188     }
1189 
1190     template <BytecodeInstructionSafe::Format format>
HandleSub2Dyn()1191     bool HandleSub2Dyn()
1192     {
1193         LOG_INST();
1194         DBGBRK();
1195         // TODO(vdyadov): implement
1196         Sync();
1197         LOG(ERROR, VERIFIER) << "Verifier error: instruction is not implemented";
1198         status_ = VerificationStatus::ERROR;
1199         return false;
1200     }
1201 
1202     template <BytecodeInstructionSafe::Format format>
HandleSub2Wide()1203     bool HandleSub2Wide()
1204     {
1205         LOG_INST();
1206         DBGBRK();
1207         Sync();
1208         return CheckBinaryOp2<format>(Types().Integral64Type(), Types().Integral64Type(), I64);
1209     }
1210 
1211     template <BytecodeInstructionSafe::Format format>
HandleFsub2()1212     bool HandleFsub2()
1213     {
1214         LOG_INST();
1215         DBGBRK();
1216         Sync();
1217         return CheckBinaryOp2<format>(F32, F32, F32);
1218     }
1219 
1220     template <BytecodeInstructionSafe::Format format>
HandleFsub2Wide()1221     bool HandleFsub2Wide()
1222     {
1223         LOG_INST();
1224         DBGBRK();
1225         Sync();
1226         return CheckBinaryOp2<format>(F64, F64, F64);
1227     }
1228 
1229     template <BytecodeInstructionSafe::Format format>
HandleMul2()1230     bool HandleMul2()
1231     {
1232         LOG_INST();
1233         DBGBRK();
1234         Sync();
1235         return CheckBinaryOp2<format>(Types().Integral32Type(), Types().Integral32Type(), I32);
1236     }
1237 
1238     template <BytecodeInstructionSafe::Format format>
HandleMul2Dyn()1239     bool HandleMul2Dyn()
1240     {
1241         LOG_INST();
1242         DBGBRK();
1243         // TODO(vdyadov): implement
1244         Sync();
1245         LOG(ERROR, VERIFIER) << "Verifier error: instruction is not implemented";
1246         status_ = VerificationStatus::ERROR;
1247         return false;
1248     }
1249 
1250     template <BytecodeInstructionSafe::Format format>
HandleMul2Wide()1251     bool HandleMul2Wide()
1252     {
1253         LOG_INST();
1254         DBGBRK();
1255         Sync();
1256         return CheckBinaryOp2<format>(Types().Integral64Type(), Types().Integral64Type(), I64);
1257     }
1258 
1259     template <BytecodeInstructionSafe::Format format>
HandleFmul2()1260     bool HandleFmul2()
1261     {
1262         LOG_INST();
1263         DBGBRK();
1264         Sync();
1265         return CheckBinaryOp2<format>(F32, F32, F32);
1266     }
1267 
1268     template <BytecodeInstructionSafe::Format format>
HandleFmul2Wide()1269     bool HandleFmul2Wide()
1270     {
1271         LOG_INST();
1272         DBGBRK();
1273         Sync();
1274         return CheckBinaryOp2<format>(F64, F64, F64);
1275     }
1276 
1277     template <BytecodeInstructionSafe::Format format>
HandleFdiv2()1278     bool HandleFdiv2()
1279     {
1280         LOG_INST();
1281         DBGBRK();
1282         Sync();
1283         // take into consideration possible exception generation
1284         // context is of good precision here
1285         return CheckBinaryOp2<format>(F32, F32, F32);
1286     }
1287 
1288     template <BytecodeInstructionSafe::Format format>
HandleFdiv2Wide()1289     bool HandleFdiv2Wide()
1290     {
1291         LOG_INST();
1292         DBGBRK();
1293         Sync();
1294         // TODO(vdyadov): take into consideration possible exception generation
1295         //                context is of good precision here
1296         return CheckBinaryOp2<format>(F64, F64, F64);
1297     }
1298 
1299     template <BytecodeInstructionSafe::Format format>
HandleFmod2()1300     bool HandleFmod2()
1301     {
1302         LOG_INST();
1303         DBGBRK();
1304         Sync();
1305         return CheckBinaryOp2<format>(F32, F32, F32);
1306     }
1307 
1308     template <BytecodeInstructionSafe::Format format>
HandleFmod2Wide()1309     bool HandleFmod2Wide()
1310     {
1311         LOG_INST();
1312         DBGBRK();
1313         Sync();
1314         return CheckBinaryOp2<format>(F64, F64, F64);
1315     }
1316 
1317     template <BytecodeInstructionSafe::Format format>
HandleAnd2()1318     bool HandleAnd2()
1319     {
1320         LOG_INST();
1321         DBGBRK();
1322         Sync();
1323         return CheckBinaryOp2<format>(Types().Integral32Type(), Types().Integral32Type());
1324     }
1325 
1326     template <BytecodeInstructionSafe::Format format>
HandleAnd2Wide()1327     bool HandleAnd2Wide()
1328     {
1329         LOG_INST();
1330         DBGBRK();
1331         Sync();
1332         return CheckBinaryOp2<format>(Types().Integral64Type(), Types().Integral64Type());
1333     }
1334 
1335     template <BytecodeInstructionSafe::Format format>
HandleOr2()1336     bool HandleOr2()
1337     {
1338         LOG_INST();
1339         DBGBRK();
1340         Sync();
1341         return CheckBinaryOp2<format>(Types().Integral32Type(), Types().Integral32Type());
1342     }
1343 
1344     template <BytecodeInstructionSafe::Format format>
HandleOr2Wide()1345     bool HandleOr2Wide()
1346     {
1347         LOG_INST();
1348         DBGBRK();
1349         Sync();
1350         return CheckBinaryOp2<format>(Types().Integral64Type(), Types().Integral64Type());
1351     }
1352 
1353     template <BytecodeInstructionSafe::Format format>
HandleXor2()1354     bool HandleXor2()
1355     {
1356         LOG_INST();
1357         DBGBRK();
1358         Sync();
1359         return CheckBinaryOp2<format>(Types().Integral32Type(), Types().Integral32Type());
1360     }
1361 
1362     template <BytecodeInstructionSafe::Format format>
HandleXor2Wide()1363     bool HandleXor2Wide()
1364     {
1365         LOG_INST();
1366         DBGBRK();
1367         Sync();
1368         return CheckBinaryOp2<format>(Types().Integral64Type(), Types().Integral64Type());
1369     }
1370 
1371     template <BytecodeInstructionSafe::Format format>
HandleShl2()1372     bool HandleShl2()
1373     {
1374         LOG_INST();
1375         DBGBRK();
1376         Sync();
1377         return CheckBinaryOp2<format>(Types().Integral32Type(), Types().Integral32Type());
1378     }
1379 
1380     template <BytecodeInstructionSafe::Format format>
HandleShl2Wide()1381     bool HandleShl2Wide()
1382     {
1383         LOG_INST();
1384         DBGBRK();
1385         Sync();
1386         return CheckBinaryOp2<format>(Types().Integral64Type(), Types().Integral64Type());
1387     }
1388 
1389     template <BytecodeInstructionSafe::Format format>
HandleShr2()1390     bool HandleShr2()
1391     {
1392         LOG_INST();
1393         DBGBRK();
1394         Sync();
1395         return CheckBinaryOp2<format>(Types().Integral32Type(), Types().Integral32Type());
1396     }
1397 
1398     template <BytecodeInstructionSafe::Format format>
HandleShr2Wide()1399     bool HandleShr2Wide()
1400     {
1401         LOG_INST();
1402         DBGBRK();
1403         Sync();
1404         return CheckBinaryOp2<format>(Types().Integral64Type(), Types().Integral64Type());
1405     }
1406 
1407     template <BytecodeInstructionSafe::Format format>
HandleAshr2()1408     bool HandleAshr2()
1409     {
1410         LOG_INST();
1411         DBGBRK();
1412         Sync();
1413         return CheckBinaryOp2<format>(Types().Integral32Type(), Types().Integral32Type());
1414     }
1415 
1416     template <BytecodeInstructionSafe::Format format>
HandleAshr2Wide()1417     bool HandleAshr2Wide()
1418     {
1419         LOG_INST();
1420         DBGBRK();
1421         Sync();
1422         return CheckBinaryOp2<format>(Types().Integral64Type(), Types().Integral64Type());
1423     }
1424 
1425     template <BytecodeInstructionSafe::Format format>
HandleDiv2()1426     bool HandleDiv2()
1427     {
1428         LOG_INST();
1429         DBGBRK();
1430         Sync();
1431         // TODO(vdyadov): take into consideration possible exception generation
1432         //                context is of good precision here
1433         return CheckBinaryOp2<format>(Types().Integral32Type(), Types().Integral32Type(), I32);
1434     }
1435 
1436     template <BytecodeInstructionSafe::Format format>
HandleDiv2Dyn()1437     bool HandleDiv2Dyn()
1438     {
1439         LOG_INST();
1440         DBGBRK();
1441         // TODO(vdyadov): implement
1442         Sync();
1443         LOG(ERROR, VERIFIER) << "Verifier error: instruction is not implemented";
1444         status_ = VerificationStatus::ERROR;
1445         return false;
1446     }
1447 
1448     template <BytecodeInstructionSafe::Format format>
HandleDiv2Wide()1449     bool HandleDiv2Wide()
1450     {
1451         LOG_INST();
1452         DBGBRK();
1453         Sync();
1454         return CheckBinaryOp2<format>(Types().Integral64Type(), Types().Integral64Type(), I64);
1455     }
1456 
1457     template <BytecodeInstructionSafe::Format format>
HandleMod2()1458     bool HandleMod2()
1459     {
1460         LOG_INST();
1461         DBGBRK();
1462         Sync();
1463         return CheckBinaryOp2<format>(Types().Integral32Type(), Types().Integral32Type(), I32);
1464     }
1465 
1466     template <BytecodeInstructionSafe::Format format>
HandleMod2Dyn()1467     bool HandleMod2Dyn()
1468     {
1469         LOG_INST();
1470         DBGBRK();
1471         // TODO(vdyadov): implement
1472         Sync();
1473         LOG(ERROR, VERIFIER) << "Verifier error: instruction is not implemented";
1474         status_ = VerificationStatus::ERROR;
1475         return false;
1476     }
1477 
1478     template <BytecodeInstructionSafe::Format format>
HandleMod2Wide()1479     bool HandleMod2Wide()
1480     {
1481         LOG_INST();
1482         DBGBRK();
1483         Sync();
1484         return CheckBinaryOp2<format>(Types().Integral64Type(), Types().Integral64Type(), I64);
1485     }
1486 
1487     template <BytecodeInstructionSafe::Format format>
HandleDivu2()1488     bool HandleDivu2()
1489     {
1490         LOG_INST();
1491         DBGBRK();
1492         Sync();
1493         // TODO(vdyadov) : add warnings when actual type is not unsigned
1494         return CheckBinaryOp2<format>(Types().Integral32Type(), Types().Integral32Type(), U32);
1495     }
1496 
1497     template <BytecodeInstructionSafe::Format format>
HandleDivu2Wide()1498     bool HandleDivu2Wide()
1499     {
1500         LOG_INST();
1501         DBGBRK();
1502         Sync();
1503         // TODO(vdyadov) : add warnings when actual type is not unsigned
1504         return CheckBinaryOp2<format>(Types().Integral64Type(), Types().Integral64Type(), U64);
1505     }
1506 
1507     template <BytecodeInstructionSafe::Format format>
HandleModu2()1508     bool HandleModu2()
1509     {
1510         LOG_INST();
1511         DBGBRK();
1512         Sync();
1513         // TODO(vdyadov) : add warnings when actual type is not unsigned
1514         return CheckBinaryOp2<format>(Types().Integral32Type(), Types().Integral32Type(), U32);
1515     }
1516 
1517     template <BytecodeInstructionSafe::Format format>
HandleModu2Wide()1518     bool HandleModu2Wide()
1519     {
1520         LOG_INST();
1521         DBGBRK();
1522         Sync();
1523         // TODO(vdyadov) : add warnings when actual type is not unsigned
1524         return CheckBinaryOp2<format>(Types().Integral64Type(), Types().Integral64Type(), U64);
1525     }
1526 
1527     template <BytecodeInstructionSafe::Format format>
HandleAdd()1528     bool HandleAdd()
1529     {
1530         LOG_INST();
1531         DBGBRK();
1532         Sync();
1533         return CheckBinaryOp<format>(Types().Integral32Type(), Types().Integral32Type(), I32);
1534     }
1535 
1536     template <BytecodeInstructionSafe::Format format>
HandleSub()1537     bool HandleSub()
1538     {
1539         LOG_INST();
1540         DBGBRK();
1541         Sync();
1542         return CheckBinaryOp<format>(Types().Integral32Type(), Types().Integral32Type(), I32);
1543     }
1544 
1545     template <BytecodeInstructionSafe::Format format>
HandleMul()1546     bool HandleMul()
1547     {
1548         LOG_INST();
1549         DBGBRK();
1550         Sync();
1551         return CheckBinaryOp<format>(Types().Integral32Type(), Types().Integral32Type(), I32);
1552     }
1553 
1554     template <BytecodeInstructionSafe::Format format>
HandleAnd()1555     bool HandleAnd()
1556     {
1557         LOG_INST();
1558         DBGBRK();
1559         Sync();
1560         return CheckBinaryOp<format>(Types().Integral32Type(), Types().Integral32Type(), I32);
1561     }
1562 
1563     template <BytecodeInstructionSafe::Format format>
HandleOr()1564     bool HandleOr()
1565     {
1566         LOG_INST();
1567         DBGBRK();
1568         Sync();
1569         return CheckBinaryOp<format>(Types().Integral32Type(), Types().Integral32Type(), I32);
1570     }
1571 
1572     template <BytecodeInstructionSafe::Format format>
HandleXor()1573     bool HandleXor()
1574     {
1575         LOG_INST();
1576         DBGBRK();
1577         Sync();
1578         return CheckBinaryOp<format>(Types().Integral32Type(), Types().Integral32Type(), I32);
1579     }
1580 
1581     template <BytecodeInstructionSafe::Format format>
HandleShl()1582     bool HandleShl()
1583     {
1584         LOG_INST();
1585         DBGBRK();
1586         Sync();
1587         return CheckBinaryOp<format>(Types().Integral32Type(), Types().Integral32Type(), I32);
1588     }
1589 
1590     template <BytecodeInstructionSafe::Format format>
HandleShr()1591     bool HandleShr()
1592     {
1593         LOG_INST();
1594         DBGBRK();
1595         Sync();
1596         return CheckBinaryOp<format>(Types().Integral32Type(), Types().Integral32Type(), I32);
1597     }
1598 
1599     template <BytecodeInstructionSafe::Format format>
HandleAshr()1600     bool HandleAshr()
1601     {
1602         LOG_INST();
1603         DBGBRK();
1604         Sync();
1605         return CheckBinaryOp<format>(Types().Integral32Type(), Types().Integral32Type(), I32);
1606     }
1607 
1608     template <BytecodeInstructionSafe::Format format>
HandleDiv()1609     bool HandleDiv()
1610     {
1611         LOG_INST();
1612         DBGBRK();
1613         Sync();
1614         return CheckBinaryOp<format>(Types().Integral32Type(), Types().Integral32Type(), I32);
1615     }
1616 
1617     template <BytecodeInstructionSafe::Format format>
HandleMod()1618     bool HandleMod()
1619     {
1620         LOG_INST();
1621         DBGBRK();
1622         Sync();
1623         return CheckBinaryOp<format>(Types().Integral32Type(), Types().Integral32Type(), I32);
1624     }
1625 
1626     template <BytecodeInstructionSafe::Format format>
HandleAddi()1627     bool HandleAddi()
1628     {
1629         LOG_INST();
1630         DBGBRK();
1631         Sync();
1632         return CheckBinaryOp2Imm<format>(Types().Integral32Type(), I32);
1633     }
1634 
1635     template <BytecodeInstructionSafe::Format format>
HandleSubi()1636     bool HandleSubi()
1637     {
1638         LOG_INST();
1639         DBGBRK();
1640         Sync();
1641         return CheckBinaryOp2Imm<format>(Types().Integral32Type(), I32);
1642     }
1643 
1644     template <BytecodeInstructionSafe::Format format>
HandleMuli()1645     bool HandleMuli()
1646     {
1647         LOG_INST();
1648         DBGBRK();
1649         Sync();
1650         return CheckBinaryOp2Imm<format>(Types().Integral32Type(), I32);
1651     }
1652 
1653     template <BytecodeInstructionSafe::Format format>
HandleAndi()1654     bool HandleAndi()
1655     {
1656         LOG_INST();
1657         DBGBRK();
1658         Sync();
1659         return CheckBinaryOp2Imm<format>(Types().Integral32Type());
1660     }
1661 
1662     template <BytecodeInstructionSafe::Format format>
HandleOri()1663     bool HandleOri()
1664     {
1665         LOG_INST();
1666         DBGBRK();
1667         Sync();
1668         return CheckBinaryOp2Imm<format>(Types().Integral32Type());
1669     }
1670 
1671     template <BytecodeInstructionSafe::Format format>
HandleXori()1672     bool HandleXori()
1673     {
1674         LOG_INST();
1675         DBGBRK();
1676         Sync();
1677         return CheckBinaryOp2Imm<format>(Types().Integral32Type());
1678     }
1679 
1680     template <BytecodeInstructionSafe::Format format>
HandleShli()1681     bool HandleShli()
1682     {
1683         LOG_INST();
1684         DBGBRK();
1685         Sync();
1686         return CheckBinaryOp2Imm<format>(Types().Integral32Type());
1687     }
1688 
1689     template <BytecodeInstructionSafe::Format format>
HandleShri()1690     bool HandleShri()
1691     {
1692         LOG_INST();
1693         DBGBRK();
1694         Sync();
1695         return CheckBinaryOp2Imm<format>(Types().Integral32Type());
1696     }
1697 
1698     template <BytecodeInstructionSafe::Format format>
HandleAshri()1699     bool HandleAshri()
1700     {
1701         LOG_INST();
1702         DBGBRK();
1703         Sync();
1704         return CheckBinaryOp2Imm<format>(Types().Integral32Type());
1705     }
1706 
1707     template <BytecodeInstructionSafe::Format format>
HandleDivi()1708     bool HandleDivi()
1709     {
1710         LOG_INST();
1711         DBGBRK();
1712         Sync();
1713         return CheckBinaryOp2Imm<format>(Types().Integral32Type(), I32);
1714     }
1715 
1716     template <BytecodeInstructionSafe::Format format>
HandleModi()1717     bool HandleModi()
1718     {
1719         LOG_INST();
1720         DBGBRK();
1721         Sync();
1722         return CheckBinaryOp2Imm<format>(Types().Integral32Type(), I32);
1723     }
1724 
1725     template <BytecodeInstructionSafe::Format format>
HandleNeg()1726     bool HandleNeg()
1727     {
1728         LOG_INST();
1729         DBGBRK();
1730         Sync();
1731         return CheckUnaryOp<format>(Types().Integral32Type(), I32);
1732     }
1733 
1734     template <BytecodeInstructionSafe::Format format>
HandleNegWide()1735     bool HandleNegWide()
1736     {
1737         LOG_INST();
1738         DBGBRK();
1739         Sync();
1740         return CheckUnaryOp<format>(Types().Integral64Type(), I64);
1741     }
1742 
1743     template <BytecodeInstructionSafe::Format format>
HandleFneg()1744     bool HandleFneg()
1745     {
1746         LOG_INST();
1747         DBGBRK();
1748         Sync();
1749         return CheckUnaryOp<format>(F32);
1750     }
1751 
1752     template <BytecodeInstructionSafe::Format format>
HandleFnegWide()1753     bool HandleFnegWide()
1754     {
1755         LOG_INST();
1756         DBGBRK();
1757         Sync();
1758         return CheckUnaryOp<format>(F64);
1759     }
1760 
1761     template <BytecodeInstructionSafe::Format format>
HandleNot()1762     bool HandleNot()
1763     {
1764         LOG_INST();
1765         DBGBRK();
1766         Sync();
1767         return CheckUnaryOp<format>(Types().Integral32Type());
1768     }
1769 
1770     template <BytecodeInstructionSafe::Format format>
HandleNotWide()1771     bool HandleNotWide()
1772     {
1773         LOG_INST();
1774         DBGBRK();
1775         Sync();
1776         return CheckUnaryOp<format>(Types().Integral64Type());
1777     }
1778 
1779     template <BytecodeInstructionSafe::Format format>
HandleInci()1780     bool HandleInci()
1781     {
1782         LOG_INST();
1783         DBGBRK();
1784         uint16_t vx = inst_.GetVReg<format>();
1785         Sync();
1786         if (!CheckRegTypes(vx, {Types().Integral32Type()})) {
1787             SET_STATUS_FOR_MSG(BadRegisterType);
1788             SET_STATUS_FOR_MSG(UndefinedRegister);
1789             return false;
1790         }
1791         MoveToNextInst<format>();
1792         return true;
1793     }
1794 
1795     template <BytecodeInstructionSafe::Format format>
HandleI32toi64()1796     bool HandleI32toi64()
1797     {
1798         LOG_INST();
1799         DBGBRK();
1800         Sync();
1801         return HandleConversion<format>(Types().Integral32Type(), I64);
1802     }
1803 
1804     template <BytecodeInstructionSafe::Format format>
HandleI32toi16()1805     bool HandleI32toi16()
1806     {
1807         LOG_INST();
1808         DBGBRK();
1809         Sync();
1810         return HandleConversion<format>(Types().Integral32Type(), I16);
1811     }
1812 
1813     template <BytecodeInstructionSafe::Format format>
HandleI32tou16()1814     bool HandleI32tou16()
1815     {
1816         LOG_INST();
1817         DBGBRK();
1818         Sync();
1819         return HandleConversion<format>(Types().Integral32Type(), U16);
1820     }
1821 
1822     template <BytecodeInstructionSafe::Format format>
HandleI32toi8()1823     bool HandleI32toi8()
1824     {
1825         LOG_INST();
1826         DBGBRK();
1827         Sync();
1828         return HandleConversion<format>(Types().Integral32Type(), I8);
1829     }
1830 
1831     template <BytecodeInstructionSafe::Format format>
HandleI32tou8()1832     bool HandleI32tou8()
1833     {
1834         LOG_INST();
1835         DBGBRK();
1836         Sync();
1837         return HandleConversion<format>(Types().Integral32Type(), U8);
1838     }
1839 
1840     template <BytecodeInstructionSafe::Format format>
HandleI32tou1()1841     bool HandleI32tou1()
1842     {
1843         LOG_INST();
1844         DBGBRK();
1845         Sync();
1846         return HandleConversion<format>(Types().Integral32Type(), U1);
1847     }
1848 
1849     template <BytecodeInstructionSafe::Format format>
HandleI32tof32()1850     bool HandleI32tof32()
1851     {
1852         LOG_INST();
1853         DBGBRK();
1854         Sync();
1855         return HandleConversion<format>(Types().Integral32Type(), F32);
1856     }
1857 
1858     template <BytecodeInstructionSafe::Format format>
HandleI32tof64()1859     bool HandleI32tof64()
1860     {
1861         LOG_INST();
1862         DBGBRK();
1863         Sync();
1864         return HandleConversion<format>(Types().Integral32Type(), F64);
1865     }
1866 
1867     template <BytecodeInstructionSafe::Format format>
HandleU32toi64()1868     bool HandleU32toi64()
1869     {
1870         LOG_INST();
1871         DBGBRK();
1872         Sync();
1873         return HandleConversion<format>(Types().Integral32Type(), I64);
1874     }
1875 
1876     template <BytecodeInstructionSafe::Format format>
HandleU32toi16()1877     bool HandleU32toi16()
1878     {
1879         LOG_INST();
1880         DBGBRK();
1881         Sync();
1882         return HandleConversion<format>(Types().Integral32Type(), I16);
1883     }
1884 
1885     template <BytecodeInstructionSafe::Format format>
HandleU32tou16()1886     bool HandleU32tou16()
1887     {
1888         LOG_INST();
1889         DBGBRK();
1890         Sync();
1891         return HandleConversion<format>(Types().Integral32Type(), U16);
1892     }
1893 
1894     template <BytecodeInstructionSafe::Format format>
HandleU32toi8()1895     bool HandleU32toi8()
1896     {
1897         LOG_INST();
1898         DBGBRK();
1899         Sync();
1900         return HandleConversion<format>(Types().Integral32Type(), I8);
1901     }
1902 
1903     template <BytecodeInstructionSafe::Format format>
HandleU32tou8()1904     bool HandleU32tou8()
1905     {
1906         LOG_INST();
1907         DBGBRK();
1908         Sync();
1909         return HandleConversion<format>(Types().Integral32Type(), U8);
1910     }
1911 
1912     template <BytecodeInstructionSafe::Format format>
HandleU32tou1()1913     bool HandleU32tou1()
1914     {
1915         LOG_INST();
1916         DBGBRK();
1917         Sync();
1918         return HandleConversion<format>(Types().Integral32Type(), U1);
1919     }
1920 
1921     template <BytecodeInstructionSafe::Format format>
HandleU32tof32()1922     bool HandleU32tof32()
1923     {
1924         LOG_INST();
1925         DBGBRK();
1926         Sync();
1927         return HandleConversion<format>(Types().Integral32Type(), F32);
1928     }
1929 
1930     template <BytecodeInstructionSafe::Format format>
HandleU32tof64()1931     bool HandleU32tof64()
1932     {
1933         LOG_INST();
1934         DBGBRK();
1935         Sync();
1936         return HandleConversion<format>(Types().Integral32Type(), F64);
1937     }
1938 
1939     template <BytecodeInstructionSafe::Format format>
HandleI64toi32()1940     bool HandleI64toi32()
1941     {
1942         LOG_INST();
1943         DBGBRK();
1944         Sync();
1945         return HandleConversion<format>(Types().Integral64Type(), I32);
1946     }
1947 
1948     template <BytecodeInstructionSafe::Format format>
HandleI64tou1()1949     bool HandleI64tou1()
1950     {
1951         LOG_INST();
1952         DBGBRK();
1953         Sync();
1954         return HandleConversion<format>(Types().Integral64Type(), U1);
1955     }
1956 
1957     template <BytecodeInstructionSafe::Format format>
HandleI64tof32()1958     bool HandleI64tof32()
1959     {
1960         LOG_INST();
1961         DBGBRK();
1962         Sync();
1963         return HandleConversion<format>(Types().Integral64Type(), F32);
1964     }
1965 
1966     template <BytecodeInstructionSafe::Format format>
HandleI64tof64()1967     bool HandleI64tof64()
1968     {
1969         LOG_INST();
1970         DBGBRK();
1971         Sync();
1972         return HandleConversion<format>(Types().Integral64Type(), F64);
1973     }
1974 
1975     template <BytecodeInstructionSafe::Format format>
HandleU64toi32()1976     bool HandleU64toi32()
1977     {
1978         LOG_INST();
1979         DBGBRK();
1980         Sync();
1981         return HandleConversion<format>(Types().Integral64Type(), I32);
1982     }
1983 
1984     template <BytecodeInstructionSafe::Format format>
HandleU64tou32()1985     bool HandleU64tou32()
1986     {
1987         LOG_INST();
1988         DBGBRK();
1989         Sync();
1990         return HandleConversion<format>(Types().Integral64Type(), U32);
1991     }
1992 
1993     template <BytecodeInstructionSafe::Format format>
HandleU64tou1()1994     bool HandleU64tou1()
1995     {
1996         LOG_INST();
1997         DBGBRK();
1998         Sync();
1999         return HandleConversion<format>(Types().Integral64Type(), U1);
2000     }
2001 
2002     template <BytecodeInstructionSafe::Format format>
HandleU64tof32()2003     bool HandleU64tof32()
2004     {
2005         LOG_INST();
2006         DBGBRK();
2007         Sync();
2008         return HandleConversion<format>(Types().Integral64Type(), F32);
2009     }
2010 
2011     template <BytecodeInstructionSafe::Format format>
HandleU64tof64()2012     bool HandleU64tof64()
2013     {
2014         LOG_INST();
2015         DBGBRK();
2016         Sync();
2017         return HandleConversion<format>(Types().Integral64Type(), F64);
2018     }
2019 
2020     template <BytecodeInstructionSafe::Format format>
HandleF32tof64()2021     bool HandleF32tof64()
2022     {
2023         LOG_INST();
2024         DBGBRK();
2025         Sync();
2026         return HandleConversion<format>(F32, F64);
2027     }
2028 
2029     template <BytecodeInstructionSafe::Format format>
HandleF32toi32()2030     bool HandleF32toi32()
2031     {
2032         LOG_INST();
2033         DBGBRK();
2034         Sync();
2035         return HandleConversion<format>(F32, I32);
2036     }
2037 
2038     template <BytecodeInstructionSafe::Format format>
HandleF32toi64()2039     bool HandleF32toi64()
2040     {
2041         LOG_INST();
2042         DBGBRK();
2043         Sync();
2044         return HandleConversion<format>(F32, I64);
2045     }
2046 
2047     template <BytecodeInstructionSafe::Format format>
HandleF32tou32()2048     bool HandleF32tou32()
2049     {
2050         LOG_INST();
2051         DBGBRK();
2052         Sync();
2053         return HandleConversion<format>(F32, U32);
2054     }
2055 
2056     template <BytecodeInstructionSafe::Format format>
HandleF32tou64()2057     bool HandleF32tou64()
2058     {
2059         LOG_INST();
2060         DBGBRK();
2061         Sync();
2062         return HandleConversion<format>(F32, U64);
2063     }
2064 
2065     template <BytecodeInstructionSafe::Format format>
HandleF64tof32()2066     bool HandleF64tof32()
2067     {
2068         LOG_INST();
2069         DBGBRK();
2070         Sync();
2071         return HandleConversion<format>(F64, F32);
2072     }
2073 
2074     template <BytecodeInstructionSafe::Format format>
HandleF64toi64()2075     bool HandleF64toi64()
2076     {
2077         LOG_INST();
2078         DBGBRK();
2079         Sync();
2080         return HandleConversion<format>(F64, I64);
2081     }
2082 
2083     template <BytecodeInstructionSafe::Format format>
HandleF64toi32()2084     bool HandleF64toi32()
2085     {
2086         LOG_INST();
2087         DBGBRK();
2088         Sync();
2089         return HandleConversion<format>(F64, I32);
2090     }
2091 
2092     template <BytecodeInstructionSafe::Format format>
HandleF64tou64()2093     bool HandleF64tou64()
2094     {
2095         LOG_INST();
2096         DBGBRK();
2097         Sync();
2098         return HandleConversion<format>(F64, U64);
2099     }
2100 
2101     template <BytecodeInstructionSafe::Format format>
HandleF64tou32()2102     bool HandleF64tou32()
2103     {
2104         LOG_INST();
2105         DBGBRK();
2106         Sync();
2107         return HandleConversion<format>(F64, U32);
2108     }
2109 
2110     template <BytecodeInstructionSafe::Format format>
HandleLdarr8()2111     bool HandleLdarr8()
2112     {
2113         LOG_INST();
2114         DBGBRK();
2115         uint16_t vs = inst_.GetVReg<format>();
2116         Sync();
2117         return CheckArrayLoad<format>(vs, {U1, I8});
2118     }
2119 
2120     template <BytecodeInstructionSafe::Format format>
HandleLdarr16()2121     bool HandleLdarr16()
2122     {
2123         LOG_INST();
2124         DBGBRK();
2125         uint16_t vs = inst_.GetVReg<format>();
2126         Sync();
2127         return CheckArrayLoad<format>(vs, {I16});
2128     }
2129 
2130     template <BytecodeInstructionSafe::Format format>
HandleLdarr()2131     bool HandleLdarr()
2132     {
2133         LOG_INST();
2134         DBGBRK();
2135         uint16_t vs = inst_.GetVReg<format>();
2136         Sync();
2137         return CheckArrayLoad<format>(vs, {I32, U32});
2138     }
2139 
2140     template <BytecodeInstructionSafe::Format format>
HandleLdarrWide()2141     bool HandleLdarrWide()
2142     {
2143         LOG_INST();
2144         DBGBRK();
2145         uint16_t vs = inst_.GetVReg<format>();
2146         Sync();
2147         return CheckArrayLoad<format>(vs, {I64, U64});
2148     }
2149 
2150     template <BytecodeInstructionSafe::Format format>
HandleLdarru8()2151     bool HandleLdarru8()
2152     {
2153         LOG_INST();
2154         DBGBRK();
2155         uint16_t vs = inst_.GetVReg<format>();
2156         Sync();
2157         return CheckArrayLoad<format>(vs, {U1, U8});
2158     }
2159 
2160     template <BytecodeInstructionSafe::Format format>
HandleLdarru16()2161     bool HandleLdarru16()
2162     {
2163         LOG_INST();
2164         DBGBRK();
2165         uint16_t vs = inst_.GetVReg<format>();
2166         Sync();
2167         return CheckArrayLoad<format>(vs, {U16});
2168     }
2169 
2170     template <BytecodeInstructionSafe::Format format>
HandleFldarr32()2171     bool HandleFldarr32()
2172     {
2173         LOG_INST();
2174         DBGBRK();
2175         uint16_t vs = inst_.GetVReg<format>();
2176         Sync();
2177         return CheckArrayLoad<format>(vs, {F32});
2178     }
2179 
2180     template <BytecodeInstructionSafe::Format format>
HandleFldarrWide()2181     bool HandleFldarrWide()
2182     {
2183         LOG_INST();
2184         DBGBRK();
2185         uint16_t vs = inst_.GetVReg<format>();
2186         Sync();
2187         return CheckArrayLoad<format>(vs, {F64});
2188     }
2189 
2190     template <BytecodeInstructionSafe::Format format>
HandleLdarrObj()2191     bool HandleLdarrObj()
2192     {
2193         LOG_INST();
2194         DBGBRK();
2195         uint16_t vs = inst_.GetVReg<format>();
2196         Sync();
2197         if (!CheckRegTypes(ACC, {Types().Integral32Type()})) {
2198             SET_STATUS_FOR_MSG(BadRegisterType);
2199             SET_STATUS_FOR_MSG(UndefinedRegister);
2200             return false;
2201         }
2202         if (!CheckRegTypes(vs, {Types().ArrayType()})) {
2203             SET_STATUS_FOR_MSG(BadRegisterType);
2204             SET_STATUS_FOR_MSG(UndefinedRegister);
2205             return false;
2206         }
2207         auto &&reg_type = GetRegType(vs);
2208         if (reg_type.ForAllTypes([this](auto reg_type1) { return reg_type1 == Types().NullRefType(); })) {
2209             // TODO(vdyadov): redesign next code, after support exception handlers,
2210             //                treat it as always throw NPE
2211             SHOW_MSG(AlwaysNpe)
2212             LOG_VERIFIER_ALWAYS_NPE(vs);
2213             END_SHOW_MSG();
2214             SetAcc(Types().Top());
2215             SET_STATUS_FOR_MSG(AlwaysNpe);
2216             return false;
2217         }
2218         auto ref_type = Types().RefType();
2219         auto &&arr_elt_type = GetArrayEltType(reg_type);
2220         TypeSet subtypes_of_ref_type_in_arr_elt_type(Types().GetKind(), Types().GetThreadNum());
2221         arr_elt_type.ForAllTypes([&](Type arr_elt_type1) {
2222             if (arr_elt_type1 <= ref_type) {
2223                 subtypes_of_ref_type_in_arr_elt_type.Insert(arr_elt_type1);
2224             }
2225             return true;
2226         });
2227         switch (subtypes_of_ref_type_in_arr_elt_type.Size()) {
2228             case 0:
2229                 SHOW_MSG(BadArrayElementType)
2230                 LOG_VERIFIER_BAD_ARRAY_ELEMENT_TYPE(ImageOf(arr_elt_type), ImageOf(Types().RefType()),
2231                                                     ImagesOf(SubtypesOf({Types().RefType()})));
2232                 END_SHOW_MSG();
2233                 SET_STATUS_FOR_MSG(BadArrayElementType);
2234                 return false;
2235             case 1:
2236                 SetAcc(subtypes_of_ref_type_in_arr_elt_type.TheOnlyType());
2237                 break;
2238             default:
2239                 SetAcc(std::move(subtypes_of_ref_type_in_arr_elt_type));
2240         }
2241         MoveToNextInst<format>();
2242         return true;
2243     }
2244 
2245     template <BytecodeInstructionSafe::Format format>
HandleStarr8()2246     bool HandleStarr8()
2247     {
2248         LOG_INST();
2249         DBGBRK();
2250         uint16_t v1 = inst_.GetVReg<format, 0x00>();
2251         uint16_t v2 = inst_.GetVReg<format, 0x01>();
2252         Sync();
2253         return CheckArrayStoreExact<format>(v1, v2, Types().Integral32Type(), {U1, I8, U8});
2254     }
2255 
2256     template <BytecodeInstructionSafe::Format format>
HandleStarr16()2257     bool HandleStarr16()
2258     {
2259         LOG_INST();
2260         DBGBRK();
2261         uint16_t v1 = inst_.GetVReg<format, 0x00>();
2262         uint16_t v2 = inst_.GetVReg<format, 0x01>();
2263         Sync();
2264         return CheckArrayStoreExact<format>(v1, v2, Types().Integral32Type(), {I16, U16});
2265     }
2266 
2267     template <BytecodeInstructionSafe::Format format>
HandleStarr()2268     bool HandleStarr()
2269     {
2270         LOG_INST();
2271         DBGBRK();
2272         uint16_t v1 = inst_.GetVReg<format, 0x00>();
2273         uint16_t v2 = inst_.GetVReg<format, 0x01>();
2274         Sync();
2275         return CheckArrayStoreExact<format>(v1, v2, Types().Integral32Type(), {I32, U32});
2276     }
2277 
2278     template <BytecodeInstructionSafe::Format format>
HandleStarrWide()2279     bool HandleStarrWide()
2280     {
2281         LOG_INST();
2282         DBGBRK();
2283         uint16_t v1 = inst_.GetVReg<format, 0x00>();
2284         uint16_t v2 = inst_.GetVReg<format, 0x01>();
2285         Sync();
2286         return CheckArrayStoreExact<format>(v1, v2, Types().Integral64Type(), {I64, U64});
2287     }
2288 
2289     template <BytecodeInstructionSafe::Format format>
HandleFstarr32()2290     bool HandleFstarr32()
2291     {
2292         LOG_INST();
2293         DBGBRK();
2294         uint16_t v1 = inst_.GetVReg<format, 0x00>();
2295         uint16_t v2 = inst_.GetVReg<format, 0x01>();
2296         Sync();
2297         return CheckArrayStoreExact<format>(v1, v2, Types().Float32Type(), {F32});
2298     }
2299 
2300     template <BytecodeInstructionSafe::Format format>
HandleFstarrWide()2301     bool HandleFstarrWide()
2302     {
2303         LOG_INST();
2304         DBGBRK();
2305         uint16_t v1 = inst_.GetVReg<format, 0x00>();
2306         uint16_t v2 = inst_.GetVReg<format, 0x01>();
2307         Sync();
2308         return CheckArrayStoreExact<format>(v1, v2, Types().Float64Type(), {F64});
2309     }
2310 
2311     template <BytecodeInstructionSafe::Format format>
HandleStarrObj()2312     bool HandleStarrObj()
2313     {
2314         LOG_INST();
2315         DBGBRK();
2316         uint16_t v1 = inst_.GetVReg<format, 0x00>();
2317         uint16_t v2 = inst_.GetVReg<format, 0x01>();
2318         Sync();
2319         return CheckArrayStore<format>(v1, v2, Types().RefType());
2320     }
2321 
2322     template <BytecodeInstructionSafe::Format format>
HandleLenarr()2323     bool HandleLenarr()
2324     {
2325         LOG_INST();
2326         DBGBRK();
2327         uint16_t vs = inst_.GetVReg<format>();
2328         Sync();
2329         if (!CheckRegTypes(vs, {Types().ArrayType()})) {
2330             SET_STATUS_FOR_MSG(BadRegisterType);
2331             SET_STATUS_FOR_MSG(UndefinedRegister);
2332             return false;
2333         }
2334         SetAcc(I32);
2335         MoveToNextInst<format>();
2336         return true;
2337     }
2338 
2339     template <BytecodeInstructionSafe::Format format>
HandleNewarr()2340     bool HandleNewarr()
2341     {
2342         LOG_INST();
2343         DBGBRK();
2344         uint16_t vd = inst_.GetVReg<format, 0>();
2345         uint16_t vs = inst_.GetVReg<format, 1>();
2346         Sync();
2347         if (!CheckRegTypes(vs, {Types().Integral32Type()})) {
2348             SET_STATUS_FOR_MSG(BadRegisterType);
2349             SET_STATUS_FOR_MSG(UndefinedRegister);
2350             return false;
2351         }
2352         const CachedClass *cached_class = GetCachedClass();
2353         if (cached_class == nullptr) {
2354             SET_STATUS_FOR_MSG(CannotResolveClassId);
2355             return false;
2356         }
2357         auto type = Types().TypeOf(*cached_class);
2358         if (!type.IsValid()) {
2359             LOG(ERROR, VERIFIER) << "Verifier error: HandleNewarr type error";
2360             status_ = VerificationStatus::ERROR;
2361             return false;
2362         }
2363         SHOW_MSG(DebugType)
2364         LOG_VERIFIER_DEBUG_TYPE(ImageOf(type));
2365         END_SHOW_MSG();
2366         if (!(type <= Types().ArrayType())) {
2367             // TODO(vdyadov): implement StrictSubtypes function to not include ArrayType in output
2368             SHOW_MSG(ArrayOfNonArrayType)
2369             LOG_VERIFIER_ARRAY_OF_NON_ARRAY_TYPE(ImageOf(type), ImagesOf(SubtypesOf({Types().ArrayType()})));
2370             END_SHOW_MSG();
2371             SET_STATUS_FOR_MSG(ArrayOfNonArrayType);
2372             return false;
2373         }
2374         SetReg(vd, type);
2375         MoveToNextInst<format>();
2376         return true;
2377     }
2378 
2379     template <BytecodeInstructionSafe::Format format>
HandleNewobj()2380     bool HandleNewobj()
2381     {
2382         LOG_INST();
2383         DBGBRK();
2384         uint16_t vd = inst_.GetVReg<format, 0>();
2385         Sync();
2386         const CachedClass *cached_class = GetCachedClass();
2387         if (cached_class == nullptr) {
2388             LOG(ERROR, VERIFIER) << "Verifier error: HandleNewobj cache error";
2389             status_ = VerificationStatus::ERROR;
2390             return false;
2391         }
2392         auto type = Types().TypeOf(*cached_class);
2393         if (!type.IsValid()) {
2394             LOG(ERROR, VERIFIER) << "Verifier error: HandleNewobj type error";
2395             status_ = VerificationStatus::ERROR;
2396             return false;
2397         }
2398         SHOW_MSG(DebugType)
2399         LOG_VERIFIER_DEBUG_TYPE(ImageOf(type));
2400         END_SHOW_MSG();
2401         if (!(type <= Types().ObjectType())) {
2402             SHOW_MSG(ObjectOfNonObjectType)
2403             LOG_VERIFIER_OBJECT_OF_NON_OBJECT_TYPE(ImageOf(type), ImagesOf(SubtypesOf({type})));
2404             END_SHOW_MSG();
2405             SET_STATUS_FOR_MSG(ObjectOfNonObjectType);
2406             return false;
2407         }
2408         SetReg(vd, type);
2409         MoveToNextInst<format>();
2410         return true;
2411     }
2412 
2413     template <BytecodeInstructionSafe::Format format>
HandleNewobjDyn()2414     bool HandleNewobjDyn()
2415     {
2416         LOG_INST();
2417         DBGBRK();
2418         // TODO(vdyadov): implement
2419         Sync();
2420         MoveToNextInst<format>();
2421         LOG(ERROR, VERIFIER) << "Verifier error: instruction is not implemented";
2422         status_ = VerificationStatus::ERROR;
2423         return false;
2424     }
2425 
2426     template <BytecodeInstructionSafe::Format format, typename RegsFetcher>
CheckCallCtor(const CachedMethod & ctor,RegsFetcher regs)2427     bool CheckCallCtor(const CachedMethod &ctor, RegsFetcher regs)
2428     {
2429         Type obj_type = Types().TypeOf(ctor.klass);
2430 
2431         // TODO(vdyadov): put under NDEBUG?
2432         {
2433             if (debug::SkipVerificationOfCall(ctor.id)) {
2434                 SetAcc(obj_type);
2435                 MoveToNextInst<format>();
2436                 return true;
2437             }
2438         }
2439 
2440         auto ctor_name_getter = [&ctor]() { return ctor.GetName(); };
2441 
2442         bool check =
2443             CheckMethodArgs(ctor_name_getter, ctor,
2444                             [self_arg = true, obj_type, regs]() mutable -> std::optional<std::tuple<int, Type>> {
2445                                 if (self_arg) {
2446                                     self_arg = false;
2447                                     return std::make_tuple(INVALID_REG, obj_type);
2448                                 }
2449                                 auto reg = regs();
2450                                 if (reg) {
2451                                     return std::make_tuple(*reg, Type {});
2452                                 }
2453                                 return {};
2454                             });
2455         if (check) {
2456             SetAcc(obj_type);
2457             MoveToNextInst<format>();
2458         }
2459         return check;
2460     }
2461 
2462     template <BytecodeInstructionSafe::Format format, typename Fetcher>
CheckCtor(Fetcher regs)2463     bool CheckCtor(Fetcher regs)
2464     {
2465         const CachedClass *klass = GetCachedClass();
2466         const CachedMethod *ctor = GetCachedMethod();
2467 
2468         if (klass == nullptr || ctor == nullptr) {
2469             SET_STATUS_FOR_MSG(CannotResolveMethodId);
2470             SET_STATUS_FOR_MSG(CannotResolveClassId);
2471             return false;
2472         }
2473 
2474         if (klass->flags[CachedClass::Flag::ARRAY_CLASS] && ctor->flags[CachedMethod::Flag::ARRAY_CONSTRUCTOR]) {
2475             SHOW_MSG(DebugArrayConstructor)
2476             LOG_VERIFIER_DEBUG_ARRAY_CONSTRUCTOR();
2477             END_SHOW_MSG();
2478             return CheckArrayCtor<format>(*ctor, regs);
2479         }
2480 
2481         if (!ctor->flags[CachedMethod::Flag::CONSTRUCTOR]) {
2482             SHOW_MSG(InitobjCallsNotConstructor)
2483             LOG_VERIFIER_INITOBJ_CALLS_NOT_CONSTRUCTOR(ctor->GetName());
2484             END_SHOW_MSG();
2485             SET_STATUS_FOR_MSG(InitobjCallsNotConstructor);
2486             return false;
2487         }
2488 
2489         SHOW_MSG(DebugConstructor)
2490         LOG_VERIFIER_DEBUG_CONSTRUCTOR(ctor->GetName());
2491         END_SHOW_MSG();
2492 
2493         return CheckCallCtor<format>(*ctor, regs);
2494     }
2495 
2496     template <BytecodeInstructionSafe::Format format>
HandleInitobj()2497     bool HandleInitobj()
2498     {
2499         LOG_INST();
2500         DBGBRK();
2501         uint16_t vs1 = inst_.GetVReg<format, 0x00>();
2502         uint16_t vs2 = inst_.GetVReg<format, 0x01>();
2503         uint16_t vs3 = inst_.GetVReg<format, 0x02>();
2504         uint16_t vs4 = inst_.GetVReg<format, 0x03>();
2505         Sync();
2506         const std::array<int, 4> regs {vs1, vs2, vs3, vs4};
2507         auto fetcher = LazyFetch(regs);
2508         return CheckCtor<format>(fetcher);
2509     }
2510 
2511     template <BytecodeInstructionSafe::Format format>
HandleInitobjShort()2512     bool HandleInitobjShort()
2513     {
2514         LOG_INST();
2515         DBGBRK();
2516         uint16_t vs1 = inst_.GetVReg<format, 0x00>();
2517         uint16_t vs2 = inst_.GetVReg<format, 0x01>();
2518         Sync();
2519         const std::array<int, 4> regs {vs1, vs2};
2520         auto fetcher = LazyFetch(regs);
2521         return CheckCtor<format>(fetcher);
2522     }
2523 
2524     template <BytecodeInstructionSafe::Format format>
HandleInitobjRange()2525     bool HandleInitobjRange()
2526     {
2527         LOG_INST();
2528         DBGBRK();
2529         uint16_t vs = inst_.GetVReg<format, 0x00>();
2530         Sync();
2531         auto fetcher = [this, reg_idx = vs]() mutable -> std::optional<int> {
2532             if (!ExecCtx().CurrentRegContext().IsRegDefined(reg_idx)) {
2533                 return std::nullopt;
2534             }
2535             return reg_idx++;
2536         };
2537         return CheckCtor<format>(fetcher);
2538     }
2539 
GetFieldType()2540     Type GetFieldType()
2541     {
2542         const CachedField *field = GetCachedField();
2543 
2544         if (field == nullptr) {
2545             SET_STATUS_FOR_MSG(CannotResolveFieldId);
2546             return {};
2547         }
2548 
2549         return Types().TypeOf(field->GetType());
2550     }
2551 
GetFieldObject()2552     Type GetFieldObject()
2553     {
2554         const CachedField *field = GetCachedField();
2555 
2556         if (field == nullptr) {
2557             SET_STATUS_FOR_MSG(CannotResolveFieldId);
2558             return {};
2559         }
2560         return Types().TypeOf(field->klass);
2561     }
2562 
CheckFieldAccess(int reg_idx,Type expected_field_type,bool is_static)2563     bool CheckFieldAccess(int reg_idx, Type expected_field_type, bool is_static)
2564     {
2565         const CachedField *field = GetCachedField();
2566 
2567         if (field == nullptr) {
2568             SET_STATUS_FOR_MSG(CannotResolveFieldId);
2569             return false;
2570         }
2571 
2572         if (is_static != field->flags[CachedField::Flag::STATIC]) {
2573             SHOW_MSG(ExpectedStaticOrInstanceField)
2574             LOG_VERIFIER_EXPECTED_STATIC_OR_INSTANCE_FIELD(is_static);
2575             END_SHOW_MSG();
2576             SET_STATUS_FOR_MSG(ExpectedStaticOrInstanceField);
2577             return false;
2578         }
2579 
2580         Type field_obj_type = GetFieldObject();
2581         Type field_type = GetFieldType();
2582         if (!field_type.IsValid()) {
2583             LOG_VERIFIER_CANNOT_RESOLVE_FIELD_TYPE(field->GetName());
2584             return false;
2585         }
2586 
2587         if (!is_static) {
2588             if (!IsRegDefined(reg_idx)) {
2589                 SET_STATUS_FOR_MSG(UndefinedRegister);
2590                 return false;
2591             }
2592             const AbstractType &obj_type = GetRegType(reg_idx);
2593             if (obj_type.ForAllTypes([&](Type obj_type1) { return obj_type1 == Types().NullRefType(); })) {
2594                 // TODO(vdyadov): redesign next code, after support exception handlers,
2595                 //                treat it as always throw NPE
2596                 SHOW_MSG(AlwaysNpe)
2597                 LOG_VERIFIER_ALWAYS_NPE(reg_idx);
2598                 END_SHOW_MSG();
2599                 SET_STATUS_FOR_MSG(AlwaysNpe);
2600                 return false;
2601             }
2602             if (!obj_type.ExistsType([&](Type obj_type1) { return obj_type1 <= field_obj_type; })) {
2603                 SHOW_MSG(InconsistentRegisterAndFieldTypes)
2604                 LOG_VERIFIER_INCONSISTENT_REGISTER_AND_FIELD_TYPES(field->GetName(), reg_idx, ImageOf(obj_type),
2605                                                                    ImageOf(field_obj_type),
2606                                                                    ImagesOf(SubtypesOf({field_obj_type})));
2607                 END_SHOW_MSG();
2608                 SET_STATUS_FOR_MSG(InconsistentRegisterAndFieldTypes);
2609             }
2610         }
2611 
2612         if (!(field_type <= expected_field_type)) {
2613             SHOW_MSG(UnexpectedFieldType)
2614             LOG_VERIFIER_UNEXPECTED_FIELD_TYPE(field->GetName(), ImageOf(field_type), ImageOf(expected_field_type),
2615                                                ImagesOf(SubtypesOf({expected_field_type})));
2616             END_SHOW_MSG();
2617             SET_STATUS_FOR_MSG(UnexpectedFieldType);
2618             return false;
2619         }
2620 
2621         auto result = CheckFieldAccessViolation(field, CurrentJob, Types());
2622         if (!result.IsOk()) {
2623             const auto &verif_opts = Runtime::GetCurrent()->GetVerificationOptions();
2624             if (verif_opts.Debug.Allow.FieldAccessViolation && result.IsError()) {
2625                 result.status = VerificationStatus::WARNING;
2626             }
2627             LogInnerMessage(result);
2628             LOG_VERIFIER_DEBUG_FIELD2(field->GetName());
2629             status_ = result.status;
2630             return status_ != VerificationStatus::ERROR;
2631         }
2632 
2633         return !result.IsError();
2634     }
2635 
2636     template <BytecodeInstructionSafe::Format format>
ProcessFieldLoad(int reg_dest,int reg_src,Type expected_field_type,bool is_static)2637     bool ProcessFieldLoad(int reg_dest, int reg_src, Type expected_field_type, bool is_static)
2638     {
2639         if (!CheckFieldAccess(reg_src, expected_field_type, is_static)) {
2640             return false;
2641         }
2642         const CachedField *field = GetCachedField();
2643 
2644         if (field == nullptr) {
2645             SET_STATUS_FOR_MSG(CannotResolveFieldId);
2646             return false;
2647         }
2648 
2649         auto type = GetFieldType();
2650         if (!type.IsValid()) {
2651             return false;
2652         }
2653         SetReg(reg_dest, type);
2654         MoveToNextInst<format>();
2655         return true;
2656     }
2657 
2658     template <BytecodeInstructionSafe::Format format>
ProcessFieldLoad(int reg_idx,Type expected_field_type,bool is_static)2659     bool ProcessFieldLoad(int reg_idx, Type expected_field_type, bool is_static)
2660     {
2661         return ProcessFieldLoad<format>(ACC, reg_idx, expected_field_type, is_static);
2662     }
2663 
2664     template <BytecodeInstructionSafe::Format format>
HandleLdobj()2665     bool HandleLdobj()
2666     {
2667         LOG_INST();
2668         DBGBRK();
2669         uint16_t vs = inst_.GetVReg<format>();
2670         Sync();
2671         return ProcessFieldLoad<format>(vs, Types().Bits32Type(), false);
2672     }
2673 
2674     template <BytecodeInstructionSafe::Format format>
HandleLdobjWide()2675     bool HandleLdobjWide()
2676     {
2677         LOG_INST();
2678         DBGBRK();
2679         uint16_t vs = inst_.GetVReg<format>();
2680         Sync();
2681         return ProcessFieldLoad<format>(vs, Types().Bits64Type(), false);
2682     }
2683 
2684     template <BytecodeInstructionSafe::Format format>
HandleLdobjObj()2685     bool HandleLdobjObj()
2686     {
2687         LOG_INST();
2688         DBGBRK();
2689         uint16_t vs = inst_.GetVReg<format>();
2690         Sync();
2691         return ProcessFieldLoad<format>(vs, Types().RefType(), false);
2692     }
2693 
2694     template <BytecodeInstructionSafe::Format format>
HandleLdobjV()2695     bool HandleLdobjV()
2696     {
2697         LOG_INST();
2698         DBGBRK();
2699         uint16_t vd = inst_.GetVReg<format, 0>();
2700         uint16_t vs = inst_.GetVReg<format, 1>();
2701         Sync();
2702         return ProcessFieldLoad<format>(vd, vs, Types().Bits32Type(), false);
2703     }
2704 
2705     template <BytecodeInstructionSafe::Format format>
HandleLdobjVWide()2706     bool HandleLdobjVWide()
2707     {
2708         LOG_INST();
2709         DBGBRK();
2710         uint16_t vd = inst_.GetVReg<format, 0>();
2711         uint16_t vs = inst_.GetVReg<format, 1>();
2712         Sync();
2713         return ProcessFieldLoad<format>(vd, vs, Types().Bits64Type(), false);
2714     }
2715 
2716     template <BytecodeInstructionSafe::Format format>
HandleLdobjVObj()2717     bool HandleLdobjVObj()
2718     {
2719         LOG_INST();
2720         DBGBRK();
2721         uint16_t vd = inst_.GetVReg<format, 0>();
2722         uint16_t vs = inst_.GetVReg<format, 1>();
2723         Sync();
2724         return ProcessFieldLoad<format>(vd, vs, Types().RefType(), false);
2725     }
2726 
2727     template <BytecodeInstructionSafe::Format format, typename Check>
ProcessStoreField(int vs,int vd,Type expected_field_type,bool is_static,Check check)2728     bool ProcessStoreField(int vs, int vd, Type expected_field_type, bool is_static, Check check)
2729     {
2730         if (!CheckRegTypes(vs, {expected_field_type})) {
2731             SET_STATUS_FOR_MSG(BadRegisterType);
2732             SET_STATUS_FOR_MSG(UndefinedRegister);
2733             return false;
2734         }
2735 
2736         if (!CheckFieldAccess(vd, expected_field_type, is_static)) {
2737             return false;
2738         }
2739 
2740         const CachedField *field = GetCachedField();
2741 
2742         if (field == nullptr) {
2743             SET_STATUS_FOR_MSG(CannotResolveFieldId);
2744             return false;
2745         }
2746         Type field_type = GetFieldType();
2747         if (!field_type.IsValid()) {
2748             return false;
2749         }
2750 
2751         const AbstractType &vs_type = GetRegType(vs);
2752 
2753         TypeId field_type_id = Types().TypeIdOf(field_type);
2754 
2755         PandaVector<CheckResult> results;
2756 
2757         vs_type.ForAllTypes(
2758             [&](auto vs_type1) { return AddCheckResult(results, check(field_type_id, Types().TypeIdOf(vs_type1))); });
2759 
2760         // results is empty if there was an OK, contains all warnings if there were any warnings, all errors if there
2761         // were only errors
2762         if (!results.empty()) {
2763             for (const auto &result : results) {
2764                 LogInnerMessage(result);
2765             }
2766             LOG_VERIFIER_DEBUG_STORE_FIELD(field->GetName(), ImageOf(field_type), ImageOf(vs_type),
2767                                            ImagesOf(SubtypesOf({Types().Integral32Type(), Types().Integral64Type()})),
2768                                            ImagesOf(SubtypesOf({field_type})));
2769             status_ = results[0].status;
2770             if (results[0].IsError()) {
2771                 return false;
2772             }
2773         }
2774 
2775         MoveToNextInst<format>();
2776         return true;
2777     }
2778 
2779     template <BytecodeInstructionSafe::Format format>
ProcessStobj(int vs,int vd,bool is_static)2780     bool ProcessStobj(int vs, int vd, bool is_static)
2781     {
2782         return ProcessStoreField<format>(vs, vd, Types().Bits32Type(), is_static, CheckStobj);
2783     }
2784 
2785     template <BytecodeInstructionSafe::Format format>
ProcessStobj(int vd,bool is_static)2786     bool ProcessStobj(int vd, bool is_static)
2787     {
2788         return ProcessStobj<format>(ACC, vd, is_static);
2789     }
2790 
2791     template <BytecodeInstructionSafe::Format format>
HandleStobj()2792     bool HandleStobj()
2793     {
2794         LOG_INST();
2795         DBGBRK();
2796         uint16_t vd = inst_.GetVReg<format>();
2797         Sync();
2798 
2799         return ProcessStobj<format>(vd, false);
2800     }
2801 
2802     template <BytecodeInstructionSafe::Format format>
HandleStobjV()2803     bool HandleStobjV()
2804     {
2805         LOG_INST();
2806         DBGBRK();
2807         uint16_t vs = inst_.GetVReg<format, 0>();
2808         uint16_t vd = inst_.GetVReg<format, 1>();
2809         Sync();
2810 
2811         return ProcessStobj<format>(vs, vd, false);
2812     }
2813 
2814     template <BytecodeInstructionSafe::Format format>
HandleStobjDyn()2815     bool HandleStobjDyn()
2816     {
2817         LOG_INST();
2818         DBGBRK();
2819         // TODO(vdyadov): implement
2820         Sync();
2821         MoveToNextInst<format>();
2822         LOG(ERROR, VERIFIER) << "Verifier error: instruction is not implemented";
2823         status_ = VerificationStatus::ERROR;
2824         return false;
2825     }
2826 
2827     template <BytecodeInstructionSafe::Format format>
ProcessStobjWide(int vs,int vd,bool is_static)2828     bool ProcessStobjWide(int vs, int vd, bool is_static)
2829     {
2830         return ProcessStoreField<format>(vs, vd, Types().Bits64Type(), is_static, CheckStobjWide);
2831     }
2832 
2833     template <BytecodeInstructionSafe::Format format>
ProcessStobjWide(int vd,bool is_static)2834     bool ProcessStobjWide(int vd, bool is_static)
2835     {
2836         return ProcessStobjWide<format>(ACC, vd, is_static);
2837     }
2838 
2839     template <BytecodeInstructionSafe::Format format>
HandleStobjWide()2840     bool HandleStobjWide()
2841     {
2842         LOG_INST();
2843         DBGBRK();
2844         uint16_t vd = inst_.GetVReg<format>();
2845         Sync();
2846 
2847         return ProcessStobjWide<format>(vd, false);
2848     }
2849 
2850     template <BytecodeInstructionSafe::Format format>
HandleStobjVWide()2851     bool HandleStobjVWide()
2852     {
2853         LOG_INST();
2854         DBGBRK();
2855         uint16_t vs = inst_.GetVReg<format, 0>();
2856         uint16_t vd = inst_.GetVReg<format, 1>();
2857         Sync();
2858 
2859         return ProcessStobjWide<format>(vs, vd, false);
2860     }
2861 
2862     template <BytecodeInstructionSafe::Format format>
ProcessStobjObj(int vs,int vd,bool is_static)2863     bool ProcessStobjObj(int vs, int vd, bool is_static)
2864     {
2865         if (!CheckFieldAccess(vd, Types().RefType(), is_static)) {
2866             return false;
2867         }
2868 
2869         const CachedField *field = GetCachedField();
2870 
2871         if (field == nullptr) {
2872             SET_STATUS_FOR_MSG(CannotResolveFieldId);
2873             return false;
2874         }
2875 
2876         Type field_type = GetFieldType();
2877         if (!field_type.IsValid()) {
2878             return false;
2879         }
2880 
2881         if (!CheckRegTypes(vs, {Types().RefType()})) {
2882             SET_STATUS_FOR_MSG(BadRegisterType);
2883             SET_STATUS_FOR_MSG(UndefinedRegister);
2884             return false;
2885         }
2886 
2887         const AbstractType &vs_type = GetRegType(vs);
2888 
2889         if (vs_type.ForAllTypes([&](Type vs_type1) { return !(vs_type1 <= field_type); })) {
2890             SHOW_MSG(BadAccumulatorType)
2891             LOG_VERIFIER_BAD_ACCUMULATOR_TYPE(ImageOf(vs_type), ImageOf(field_type),
2892                                               ImagesOf(SubtypesOf({field_type})));
2893             END_SHOW_MSG();
2894             SET_STATUS_FOR_MSG(BadAccumulatorType);
2895             return false;
2896         }
2897 
2898         MoveToNextInst<format>();
2899         return true;
2900     }
2901 
2902     template <BytecodeInstructionSafe::Format format>
ProcessStobjObj(int vd,bool is_static)2903     bool ProcessStobjObj(int vd, bool is_static)
2904     {
2905         return ProcessStobjObj<format>(ACC, vd, is_static);
2906     }
2907 
2908     template <BytecodeInstructionSafe::Format format>
HandleStobjObj()2909     bool HandleStobjObj()
2910     {
2911         LOG_INST();
2912         DBGBRK();
2913         uint16_t vd = inst_.GetVReg<format>();
2914         Sync();
2915         return ProcessStobjObj<format>(vd, false);
2916     }
2917 
2918     template <BytecodeInstructionSafe::Format format>
HandleStobjVObj()2919     bool HandleStobjVObj()
2920     {
2921         LOG_INST();
2922         DBGBRK();
2923         uint16_t vs = inst_.GetVReg<format, 0>();
2924         uint16_t vd = inst_.GetVReg<format, 1>();
2925         Sync();
2926         return ProcessStobjObj<format>(vs, vd, false);
2927     }
2928 
2929     template <BytecodeInstructionSafe::Format format>
HandleLdstatic()2930     bool HandleLdstatic()
2931     {
2932         LOG_INST();
2933         DBGBRK();
2934         Sync();
2935         return ProcessFieldLoad<format>(INVALID_REG, Types().Bits32Type(), true);
2936     }
2937 
2938     template <BytecodeInstructionSafe::Format format>
HandleLdstaticWide()2939     bool HandleLdstaticWide()
2940     {
2941         LOG_INST();
2942         DBGBRK();
2943         Sync();
2944         return ProcessFieldLoad<format>(INVALID_REG, Types().Bits64Type(), true);
2945     }
2946 
2947     template <BytecodeInstructionSafe::Format format>
HandleLdstaticObj()2948     bool HandleLdstaticObj()
2949     {
2950         LOG_INST();
2951         DBGBRK();
2952         Sync();
2953         return ProcessFieldLoad<format>(INVALID_REG, Types().RefType(), true);
2954     }
2955 
2956     template <BytecodeInstructionSafe::Format format>
HandleStstatic()2957     bool HandleStstatic()
2958     {
2959         LOG_INST();
2960         DBGBRK();
2961         Sync();
2962         return ProcessStobj<format>(INVALID_REG, true);
2963     }
2964 
2965     template <BytecodeInstructionSafe::Format format>
HandleStstaticWide()2966     bool HandleStstaticWide()
2967     {
2968         LOG_INST();
2969         DBGBRK();
2970         Sync();
2971         return ProcessStobjWide<format>(INVALID_REG, true);
2972     }
2973 
2974     template <BytecodeInstructionSafe::Format format>
HandleStstaticObj()2975     bool HandleStstaticObj()
2976     {
2977         LOG_INST();
2978         DBGBRK();
2979         Sync();
2980         return ProcessStobjObj<format>(INVALID_REG, true);
2981     }
2982 
2983     template <typename Check>
CheckReturn(Type ret_type,Type acc_type,Check check)2984     bool CheckReturn(Type ret_type, Type acc_type, Check check)
2985     {
2986         TypeId ret_type_id = Types().TypeIdOf(ret_type);
2987 
2988         PandaVector<Type> compatible_acc_types;
2989         for (size_t acc_idx = 0; acc_idx < static_cast<size_t>(TypeId::REFERENCE) + 1; ++acc_idx) {
2990             auto acc_type_id = static_cast<TypeId>(acc_idx);
2991             const CheckResult &info = check(ret_type_id, acc_type_id);
2992             if (!info.IsError()) {
2993                 compatible_acc_types.push_back(Types().TypeOf(acc_type_id));
2994             }
2995         }
2996 
2997         if (!CheckTypes(acc_type, {Types().PrimitiveType()}) || acc_type == Types().PrimitiveType()) {
2998             LOG_VERIFIER_BAD_ACCUMULATOR_RETURN_VALUE_TYPE(ImageOf(acc_type), ImagesOf(compatible_acc_types));
2999             SET_STATUS_FOR_MSG(BadAccumulatorReturnValueType);
3000             return false;
3001         }
3002 
3003         TypeId acc_type_id = Types().TypeIdOf(acc_type);
3004 
3005         const auto &result = check(ret_type_id, acc_type_id);
3006 
3007         if (!result.IsOk()) {
3008             LogInnerMessage(result);
3009             if (result.IsError()) {
3010                 LOG_VERIFIER_DEBUG_FUNCTION_RETURN_AND_ACCUMULATOR_TYPES_WITH_COMPATIBLE_TYPES(
3011                     ImageOf(ReturnType()), ImageOf(acc_type), ImagesOf(compatible_acc_types));
3012             } else {
3013                 LOG_VERIFIER_DEBUG_FUNCTION_RETURN_AND_ACCUMULATOR_TYPES(ImageOf(ReturnType()), ImageOf(acc_type));
3014             }
3015         }
3016 
3017         status_ = result.status;
3018         return status_ != VerificationStatus::ERROR;
3019     }
3020 
3021     template <BytecodeInstructionSafe::Format format>
HandleReturn()3022     bool HandleReturn()
3023     {
3024         LOG_INST();
3025         DBGBRK();
3026         Sync();
3027 
3028         if (!CheckTypes(ReturnType(), {Types().Bits32Type()})) {
3029             LOG_VERIFIER_BAD_RETURN_INSTRUCTION_TYPE("", ImageOf(ReturnType()), ImageOf(Types().Bits32Type()),
3030                                                      ImagesOf(Types().SubtypesOf(Types().Bits32Type())));
3031             SET_STATUS_FOR_MSG(BadReturnInstructionType);
3032             return false;
3033         }
3034 
3035         if (!IsRegDefined(ACC)) {
3036             SET_STATUS_FOR_MSG(UndefinedRegister);
3037             return false;
3038         }
3039 
3040         // TODO(vdyadov): handle LUB of compatible primitive types
3041         if (!CheckTypes(GetAccType(), {Types().Bits32Type()})) {
3042             LOG_VERIFIER_BAD_ACCUMULATOR_RETURN_VALUE_TYPE(ImageOf(GetAccType()),
3043                                                            ImagesOf(Types().SubtypesOf(Types().Bits32Type())));
3044             SET_STATUS_FOR_MSG(BadAccumulatorReturnValueType);
3045         }
3046         return false;
3047     }
3048 
3049     template <BytecodeInstructionSafe::Format format>
HandleReturnDyn()3050     bool HandleReturnDyn()
3051     {
3052         LOG_INST();
3053         DBGBRK();
3054         // TODO(vdyadov): implement
3055         Sync();
3056         LOG(ERROR, VERIFIER) << "Verifier error: instruction is not implemented";
3057         status_ = VerificationStatus::ERROR;
3058         return false;
3059     }
3060 
3061     template <BytecodeInstructionSafe::Format format>
HandleReturnWide()3062     bool HandleReturnWide()
3063     {
3064         LOG_INST();
3065         DBGBRK();
3066         Sync();
3067 
3068         if (!CheckTypes(ReturnType(), {Types().Bits64Type()})) {
3069             LOG_VERIFIER_BAD_RETURN_INSTRUCTION_TYPE(".64", ImageOf(ReturnType()), ImageOf(Types().Bits64Type()),
3070                                                      ImagesOf(Types().SubtypesOf(Types().Bits64Type())));
3071             status_ = VerificationStatus::ERROR;
3072             return false;
3073         }
3074 
3075         if (!IsRegDefined(ACC)) {
3076             SET_STATUS_FOR_MSG(UndefinedRegister);
3077             return false;
3078         }
3079 
3080         if (!CheckTypes(GetAccType(), {Types().Bits64Type()})) {
3081             LOG_VERIFIER_BAD_ACCUMULATOR_RETURN_VALUE_TYPE(ImageOf(GetAccType()),
3082                                                            ImagesOf(Types().SubtypesOf(Types().Bits64Type())));
3083             status_ = VerificationStatus::ERROR;
3084         }
3085         return false;
3086     }
3087 
3088     template <BytecodeInstructionSafe::Format format>
HandleReturnObj()3089     bool HandleReturnObj()
3090     {
3091         LOG_INST();
3092         DBGBRK();
3093         Sync();
3094 
3095         if (!CheckTypes(ReturnType(), {Types().RefType()})) {
3096             LOG_VERIFIER_BAD_RETURN_INSTRUCTION_TYPE(".obj", ImageOf(ReturnType()), ImageOf(Types().RefType()),
3097                                                      ImagesOf(Types().SubtypesOf(Types().Bits32Type())));
3098             status_ = VerificationStatus::ERROR;
3099             return false;
3100         }
3101 
3102         if (!IsRegDefined(ACC)) {
3103             SET_STATUS_FOR_MSG(UndefinedRegister);
3104             return false;
3105         }
3106 
3107         auto &&acc_type = GetAccType();
3108 
3109         if (!CheckTypes(acc_type, {ReturnType()})) {
3110             LOG_VERIFIER_BAD_ACCUMULATOR_RETURN_VALUE_TYPE_WITH_SUBTYPE(ImageOf(acc_type), ImageOf(ReturnType()),
3111                                                                         ImagesOf(Types().SubtypesOf(ReturnType())));
3112             // TODO(vdyadov) : after solving issues with set of types in LUB, uncomment next line
3113             status_ = VerificationStatus::WARNING;
3114         }
3115 
3116         return false;
3117     }
3118 
3119     template <BytecodeInstructionSafe::Format format>
HandleReturnVoid()3120     bool HandleReturnVoid()
3121     {
3122         LOG_INST();
3123         DBGBRK();
3124         // TODO(vdyadov): think of introducing void as of separate type, like null
3125         Sync();
3126 
3127         if (ReturnType() != Types().Top()) {
3128             LOG_VERIFIER_BAD_RETURN_VOID_INSTRUCTION_TYPE(ImageOf(ReturnType()));
3129             status_ = VerificationStatus::ERROR;
3130         }
3131 
3132         return false;
3133     }
3134 
3135     template <BytecodeInstructionSafe::Format format>
HandleCheckcast()3136     bool HandleCheckcast()
3137     {
3138         LOG_INST();
3139         DBGBRK();
3140         ExecCtx().SetTypecastPoint(inst_.GetAddress());
3141         Sync();
3142         const CachedClass *cached_class = GetCachedClass();
3143         if (cached_class == nullptr) {
3144             return false;
3145         }
3146         auto type = Types().TypeOf(*cached_class);
3147         if (!type.IsValid()) {
3148             return false;
3149         }
3150         LOG_VERIFIER_DEBUG_TYPE(ImageOf(type));
3151         if (!(type <= Types().ObjectType()) && !(type <= Types().ArrayType())) {
3152             LOG_VERIFIER_CHECK_CAST_TO_NON_OBJECT_TYPE(ImageOf(type), ImagesOf(SubtypesOf({Types().ObjectType()})));
3153             status_ = VerificationStatus::ERROR;
3154             return false;
3155         }
3156         if (!IsRegDefined(ACC)) {
3157             SET_STATUS_FOR_MSG(UndefinedRegister);
3158             return false;
3159         }
3160         auto acc_type = GetAccType();
3161         // TODO(vdyadov): remove this check after #2365
3162         auto res = acc_type.ForAllTypes(
3163             [&](Type acc_type1) { return !(acc_type1 <= Types().RefType() || acc_type1 <= Types().ArrayType()); });
3164         if (res) {
3165             LOG_VERIFIER_NON_OBJECT_ACCUMULATOR_TYPE();
3166             status_ = VerificationStatus::ERROR;
3167             return false;
3168         }
3169 
3170         if (acc_type.ForAllTypes([&](Type acc_type1) { return acc_type1 <= Types().NullRefType(); })) {
3171             LOG_VERIFIER_ACCUMULATOR_ALWAYS_NULL();
3172             status_ = VerificationStatus::WARNING;
3173         } else if (acc_type.ForAllTypes([&](Type acc_type1) { return acc_type1 <= type; })) {
3174             LOG_VERIFIER_REDUNDANT_CHECK_CAST(ImageOf(acc_type), ImageOf(type));
3175             status_ = VerificationStatus::WARNING;
3176         } else if (type <= Types().ArrayType()) {
3177             auto &&elt_type = GetArrayEltType(type);
3178             res = acc_type.ForAllTypes(
3179                 [&](auto acc_type1) { return !(acc_type1 <= Types().ArrayType() || type <= acc_type1); });
3180             if (res) {
3181                 // TODO(vdyadov): add here accounting of array elt subtyping in possible types
3182                 LOG_VERIFIER_IMPOSSIBLE_CHECK_CAST(ImageOf(acc_type), ImagesOf(SubSupTypesOf(type)));
3183                 status_ = VerificationStatus::WARNING;
3184             } else {
3185                 res = acc_type.ForAllTypes([&](Type acc_type1) {
3186                     if (IsConcreteArrayType(acc_type1)) {
3187                         auto &&acc_elt_type = GetArrayEltType(acc_type1);
3188                         return !(acc_elt_type <= elt_type || elt_type <= acc_elt_type);
3189                     } else {
3190                         return true;
3191                     }
3192                 });
3193                 if (res) {
3194                     LOG_VERIFIER_IMPOSSIBLE_ARRAY_CHECK_CAST(ImageOf(GetArrayEltType(acc_type)),
3195                                                              ImagesOf(SubSupTypesOf(elt_type)));
3196                     status_ = VerificationStatus::WARNING;
3197                 }
3198             }
3199         } else if (acc_type.ForAllTypes([&](Type acc_type1) { return !(type <= acc_type1); })) {
3200             // NB: accumulator may be checked several times via checkcast and interface types,
3201             // so incompatibility here should be just a warning
3202             // type in acc and given type should be on same line in type hierarchy
3203             // ACC may be a supertype of given type, because of impresicion of absint,
3204             // real type in ACC during execution may be a subtype of ACC type during absint
3205             LOG_VERIFIER_POSSIBLY_INCOMPATIBLE_ACCUMULATOR_TYPE(ImageOf(acc_type), ImagesOf(SubSupTypesOf(type)));
3206             status_ = VerificationStatus::WARNING;
3207         }
3208 
3209         if (status_ == VerificationStatus::ERROR) {
3210             SetAcc(Types().Top());
3211             return false;
3212         }
3213 
3214         SetAccAndOthersOfSameOrigin(type);
3215 
3216         MoveToNextInst<format>();
3217         return true;
3218     }
3219 
3220     template <BytecodeInstructionSafe::Format format>
HandleIsinstance()3221     bool HandleIsinstance()
3222     {
3223         LOG_INST();
3224         DBGBRK();
3225         Sync();
3226         const CachedClass *cached_class = GetCachedClass();
3227         if (cached_class == nullptr) {
3228             return false;
3229         }
3230         auto type = Types().TypeOf(*cached_class);
3231         if (!type.IsValid()) {
3232             return false;
3233         }
3234         LOG_VERIFIER_DEBUG_TYPE(ImageOf(type));
3235         if (!(type <= Types().ObjectType()) && !(type <= Types().ArrayType())) {
3236             // !(type <= Types().ArrayType()) is redundant, because all arrays
3237             // are subtypes of either panda.Object <: ObjectType or java.lang.Object <: ObjectType
3238             // depending on selected language context
3239             LOG_VERIFIER_BAD_IS_INSTANCE_INSTRUCTION(ImageOf(type), ImagesOf(SubtypesOf({Types().ObjectType()})));
3240             status_ = VerificationStatus::ERROR;
3241             return false;
3242         }
3243         if (!IsRegDefined(ACC)) {
3244             SET_STATUS_FOR_MSG(UndefinedRegister);
3245             return false;
3246         }
3247 
3248         auto result = CheckClassAccessViolation(cached_class, CurrentJob, Types());
3249         if (!result.IsOk()) {
3250             LogInnerMessage(CheckResult::protected_class);
3251             LOG_VERIFIER_DEBUG_CALL_FROM_TO(CurrentJob.JobCachedMethod().klass.GetName(), cached_class->GetName());
3252             status_ = VerificationStatus::ERROR;
3253             return false;
3254         }
3255 
3256         auto acc_type = GetAccType();
3257         // TODO(vdyadov): remove this check after #2365
3258         auto res = acc_type.ForAllTypes(
3259             [&](Type acc_type1) { return !(acc_type1 <= Types().RefType() || acc_type1 <= Types().ArrayType()); });
3260         if (res) {
3261             LOG_VERIFIER_NON_OBJECT_ACCUMULATOR_TYPE();
3262             status_ = VerificationStatus::ERROR;
3263             return false;
3264         }
3265 
3266         if (acc_type.ForAllTypes([&](Type acc_type1) { return acc_type1 <= Types().NullRefType(); })) {
3267             LOG_VERIFIER_ACCUMULATOR_ALWAYS_NULL();
3268             status_ = VerificationStatus::WARNING;
3269         } else if (acc_type.ForAllTypes([&](Type acc_type1) { return acc_type1 <= type; })) {
3270             LOG_VERIFIER_REDUNDANT_IS_INSTANCE(ImageOf(acc_type), ImageOf(type));
3271             status_ = VerificationStatus::WARNING;
3272         } else if (type <= Types().ArrayType()) {
3273             auto &&elt_type = GetArrayEltType(type);
3274             auto &&acc_elt_type = GetArrayEltType(acc_type);
3275             bool acc_elt_type_is_empty = true;
3276             res = acc_elt_type.ForAllTypes([&](Type acc_elt_type1) {
3277                 acc_elt_type_is_empty = false;
3278                 return !(acc_elt_type1 <= elt_type || elt_type <= acc_elt_type1);
3279             });
3280             if (res) {
3281                 if (acc_elt_type_is_empty) {
3282                     // TODO(vdyadov): add here accounting of array elt subtyping in possible types
3283                     LOG_VERIFIER_IMPOSSIBLE_IS_INSTANCE(ImageOf(acc_type), ImagesOf(SubSupTypesOf(type)));
3284                 } else {
3285                     LOG_VERIFIER_IMPOSSIBLE_ARRAY_IS_INSTANCE(ImageOf(acc_elt_type), ImagesOf(SubSupTypesOf(elt_type)));
3286                 }
3287                 status_ = VerificationStatus::WARNING;
3288             }
3289         } else if (acc_type.ForAllTypes([&](Type acc_type1) { return !(type <= acc_type1); })) {
3290             // type in acc and given type should be on same line in type hierarchy
3291             // ACC may be a supertype of given type, because of impresicion of absint,
3292             // real type in ACC during execution may be a subtype of ACC type during absint
3293             LOG_VERIFIER_IMPOSSIBLE_IS_INSTANCE(ImageOf(acc_type), ImagesOf(SubSupTypesOf(type)));
3294             status_ = VerificationStatus::WARNING;
3295         }  // else {
3296         // TODO(vdyadov): here we may increase precision to concrete values in some cases
3297         SetAcc(I32);
3298         MoveToNextInst<format>();
3299         return true;
3300     }
3301 
3302     template <typename Fetcher, typename NameGetter>
CheckMethodArgs(NameGetter name_getter,const CachedMethod & method,Fetcher regs_and_types)3303     bool CheckMethodArgs(NameGetter name_getter, const CachedMethod &method, Fetcher regs_and_types)
3304     {
3305         const auto &sig = Types().MethodSignature(method);
3306         const auto &norm_sig = Types().NormalizedMethodSignature(method);
3307         auto formal_args = ConstLazyFetch(sig);
3308         auto norm_formal_args = ConstLazyFetch(norm_sig);
3309         bool result = false;
3310         size_t args_num = sig.size() - 1;
3311         if (args_num == 0) {
3312             return true;
3313         }
3314         ForEachCond(JoinStreams(regs_and_types, formal_args, norm_formal_args), [this, &result, &name_getter,
3315                                                                                  &args_num](auto &&types) mutable {
3316             do {
3317                 auto &&reg_and_type = std::get<0x0>(types);
3318                 auto &&formal_param = std::get<0x1>(types);
3319                 auto &&norm_param = std::get<0x2>(types);
3320                 int reg_num = std::get<0x0>(reg_and_type);
3321                 if (reg_num != INVALID_REG && !IsRegDefined(reg_num)) {
3322                     LOG_VERIFIER_BAD_CALL_UNDEFINED_REGISTER(name_getter(), reg_num);
3323                     SET_STATUS_FOR_MSG(UndefinedRegister);
3324                     return result = false;
3325                 }
3326                 Type formal_type {Types().TypeOf(formal_param)};
3327                 Type norm_type {Types().TypeOf(norm_param)};
3328                 ASSERT(formal_param.Variance() == norm_param.Variance());
3329                 const AbstractType &actual_type =
3330                     reg_num == INVALID_REG ? std::get<0x1>(reg_and_type) : GetRegType(reg_num);
3331                 TypeSet norm_actual_type(Types().GetKind(), Types().GetThreadNum());
3332                 actual_type.ForAllTypes([&](Type actual_type1) {
3333                     norm_actual_type.Insert(Types().NormalizedTypeOf(actual_type1));
3334                     return true;
3335                 });
3336                 // arg: NormalizedTypeOf(actual_type) <= norm_type
3337                 // check of physical compatibility
3338                 bool incompatible_types = false;
3339                 auto res = actual_type.ExistsType(
3340                     [&](auto actual_type1) { return actual_type1 <= Types().RefType() && !actual_type1.IsBot(); });
3341                 if (reg_num != INVALID_REG && formal_type <= Types().RefType() && !formal_type.IsBot() && res) {
3342                     if (CheckRegTypesTakingIntoAccountTypecasts(reg_num, formal_type)) {
3343                         break;
3344                     }
3345                     if (!Runtime::GetCurrent()->GetVerificationOptions().Debug.Allow.WrongSubclassingInMethodArgs) {
3346                         incompatible_types = true;
3347                     }
3348                 } else if (!formal_type.IsBot() && !formal_type.IsTop() &&
3349                            !norm_actual_type.Exists(
3350                                [&](auto norm_actual_type1) { return norm_actual_type1 <= norm_type; })) {
3351                     incompatible_types = true;
3352                 }
3353                 if (incompatible_types) {
3354                     PandaString reg_or_param =
3355                         reg_num == INVALID_REG ? "Actual parameter" : RegisterName(reg_num, true);
3356                     SHOW_MSG(BadCallIncompatibleParameter)
3357                     LOG_VERIFIER_BAD_CALL_INCOMPATIBLE_PARAMETER(name_getter(), reg_or_param, ImageOf(norm_actual_type),
3358                                                                  ImageOf(norm_type));
3359                     END_SHOW_MSG();
3360                     SET_STATUS_FOR_MSG(BadCallIncompatibleParameter);
3361                     return result = false;
3362                 }
3363                 if (formal_type.IsBot()) {
3364                     if (actual_type.ExistsType([](auto actual_type1) { return actual_type1.IsBot(); })) {
3365                         LOG_VERIFIER_CALL_FORMAL_ACTUAL_BOTH_BOT_OR_TOP("Bot");
3366                         break;
3367                     } else {
3368                         SHOW_MSG(BadCallFormalIsBot)
3369                         LOG_VERIFIER_BAD_CALL_FORMAL_IS_BOT(name_getter(), ImageOf(actual_type));
3370                         END_SHOW_MSG();
3371                         SET_STATUS_FOR_MSG(BadCallFormalIsBot);
3372                         return result = false;
3373                     }
3374                 } else if (formal_type.IsTop()) {
3375                     if (actual_type.ExistsType([](auto actual_type1) { return actual_type1.IsTop(); })) {
3376                         LOG_VERIFIER_CALL_FORMAL_ACTUAL_BOTH_BOT_OR_TOP("Top");
3377                         break;
3378                     } else {
3379                         SHOW_MSG(CallFormalTop)
3380                         LOG_VERIFIER_CALL_FORMAL_TOP();
3381                         END_SHOW_MSG();
3382                         break;
3383                     }
3384                 } else if (formal_type <= Types().PrimitiveType()) {
3385                     // check implicit conversion of primitive types
3386                     TypeId formal_id = Types().TypeIdOf(formal_type);
3387                     const Type &integral32_type = Types().Integral32Type();
3388                     const Type &integral64_type = Types().Integral64Type();
3389                     const Type &float64_type = Types().Float64Type();
3390                     const Type &primitive_type = Types().PrimitiveType();
3391                     bool actual_type_has_primitives = false;
3392                     bool need_to_break = false;
3393                     PandaVector<CheckResult> results;
3394                     actual_type.ForAllTypes([&](Type actual_type1) {
3395                         if (!(actual_type1 <= primitive_type)) {
3396                             return true;
3397                         }
3398                         actual_type_has_primitives = true;
3399                         TypeId actual_id = Types().TypeIdOf(actual_type1);
3400                         if (actual_id != TypeId::INVALID) {
3401                             return AddCheckResult(results, panda::verifier::CheckMethodArgs(formal_id, actual_id));
3402                         }
3403 
3404                         // special case, where type after contexts LUB operation is inexact one, like
3405                         // Integral32Type()
3406                         if ((formal_type <= integral32_type && actual_type1 <= integral32_type) ||
3407                             (formal_type <= integral64_type && actual_type1 <= integral64_type) ||
3408                             (formal_type <= float64_type && actual_type1 <= float64_type)) {
3409                             SHOW_MSG(CallFormalActualDifferent)
3410                             LOG_VERIFIER_CALL_FORMAL_ACTUAL_DIFFERENT(ImageOf(formal_type), ImageOf(actual_type1),
3411                                                                       ImagesOf(SubtypesOf({actual_type1})));
3412                             END_SHOW_MSG();
3413                             need_to_break = true;
3414                             return false;
3415                         }
3416 
3417                         return AddCheckResult(results, panda::verifier::CheckMethodArgs(formal_id, actual_id));
3418                     });
3419 
3420                     if (!actual_type_has_primitives) {
3421                         return result = false;
3422                     }
3423                     if (need_to_break || results.empty()) {
3424                         break;
3425                     }
3426                     for (const auto &r : results) {
3427                         SHOW_MSG(DebugCallParameterTypes)
3428                         LogInnerMessage(r);
3429                         LOG_VERIFIER_DEBUG_CALL_PARAMETER_TYPES(
3430                             name_getter(),
3431                             (reg_num == INVALID_REG
3432                                  ? ""
3433                                  : PandaString {"Actual parameter in "} + RegisterName(reg_num) + ". "),
3434                             ImageOf(actual_type), ImageOf(formal_type));
3435                         END_SHOW_MSG();
3436                         status_ = r.status;
3437                     }
3438                     status_ = results[0].status;
3439                     if (status_ == VerificationStatus::WARNING) {
3440                         break;
3441                     } else {
3442                         return result = false;
3443                     }
3444                 } else if (formal_type <= Types().MethodType()) {
3445                     auto r =
3446                         norm_actual_type.Exists([&](auto norm_actual_type1) { return norm_actual_type1 <= norm_type; });
3447                     if (!r) {
3448                         SHOW_MSG(BadCallIncompatibleLambdaType)
3449                         LOG_VERIFIER_BAD_CALL_INCOMPATIBLE_LAMBDA_TYPE(
3450                             name_getter(),
3451                             (reg_num == INVALID_REG ? "" : PandaString {"in "} + RegisterName(reg_num) + " "),
3452                             ImageOf(actual_type), ImageOf(norm_actual_type), ImageOf(formal_type), ImageOf(norm_type));
3453                         END_SHOW_MSG();
3454                         SET_STATUS_FOR_MSG(BadCallIncompatibleLambdaType);
3455                         return result = false;
3456                     }
3457                     break;
3458                 }
3459                 if (!CheckTypes(actual_type, {formal_type})) {
3460                     if (reg_num == INVALID_REG) {
3461                         SHOW_MSG(BadCallWrongParameter)
3462                         LOG_VERIFIER_BAD_CALL_WRONG_PARAMETER(name_getter(), ImageOf(actual_type),
3463                                                               ImageOf(formal_type));
3464                         END_SHOW_MSG();
3465                         SET_STATUS_FOR_MSG(BadCallWrongParameter);
3466                     } else {
3467                         SHOW_MSG(BadCallWrongRegister)
3468                         LOG_VERIFIER_BAD_CALL_WRONG_REGISTER(name_getter(), reg_num);
3469                         END_SHOW_MSG();
3470                         SET_STATUS_FOR_MSG(BadCallWrongRegister);
3471                     }
3472                     if (!Runtime::GetCurrent()->GetVerificationOptions().Debug.Allow.WrongSubclassingInMethodArgs) {
3473                         status_ = VerificationStatus::ERROR;
3474                         return result = false;
3475                     }
3476                 }
3477             } while (false);
3478             if (--args_num == 0) {
3479                 result = true;
3480                 return false;
3481             }
3482             return true;
3483         });
3484         if (!result && status_ == VerificationStatus::OK) {
3485             // premature end of arguments
3486             SHOW_MSG(BadCallTooFewParameters)
3487             LOG_VERIFIER_BAD_CALL_TOO_FEW_PARAMETERS(name_getter());
3488             END_SHOW_MSG();
3489             SET_STATUS_FOR_MSG(BadCallTooFewParameters);
3490             // we must have set status_ to VerificationStatus::ERROR to make verifier fail
3491         }
3492         return result;
3493     }
3494 
3495     template <BytecodeInstructionSafe::Format format, typename Fetcher>
CheckCall(const CachedMethod * method,Fetcher regs)3496     bool CheckCall(const CachedMethod *method, Fetcher regs)
3497     {
3498         if (method == nullptr) {
3499             SET_STATUS_FOR_MSG(CannotResolveMethodId);
3500             return false;
3501         }
3502 
3503         auto result = CheckMethodAccessViolation(method, CurrentJob, Types());
3504         if (!result.IsOk()) {
3505             const auto &verif_opts = Runtime::GetCurrent()->GetVerificationOptions();
3506             if (verif_opts.Debug.Allow.MethodAccessViolation && result.IsError()) {
3507                 result.status = VerificationStatus::WARNING;
3508             }
3509             LogInnerMessage(result);
3510             LOG_VERIFIER_DEBUG_CALL_FROM_TO(CurrentJob.JobCachedMethod().GetName(), method->GetName());
3511             status_ = result.status;
3512             if (status_ == VerificationStatus::ERROR) {
3513                 return false;
3514             }
3515         }
3516 
3517         const auto &method_sig = Types().MethodSignature(*method);
3518         auto method_name_getter = [&method]() { return method->GetName(); };
3519         Type result_type {Types().TypeOf(method_sig.back())};
3520 
3521         if (!debug::SkipVerificationOfCall(method->id) &&
3522             !CheckMethodArgs(method_name_getter, *method,
3523                              Transform(regs, [](int reg) { return std::make_tuple(reg, Type {}); }))) {
3524             return false;
3525         }
3526         SetAcc(result_type);
3527         MoveToNextInst<format>();
3528         return true;
3529     }
3530 
3531     template <BytecodeInstructionSafe::Format format>
HandleCallShort()3532     bool HandleCallShort()
3533     {
3534         LOG_INST();
3535         DBGBRK();
3536         uint16_t vs1 = inst_.GetVReg<format, 0x00>();
3537         uint16_t vs2 = inst_.GetVReg<format, 0x01>();
3538         const CachedMethod *method = GetCachedMethod();
3539         if (method != nullptr) {
3540             LOG_VERIFIER_DEBUG_METHOD(method->GetName());
3541         }
3542         Sync();
3543         const std::array<int, 2> regs {vs1, vs2};
3544         auto fetcher = LazyFetch(regs);
3545         return CheckCall<format>(method, fetcher);
3546     }
3547 
3548     template <BytecodeInstructionSafe::Format format>
HandleCallAccShort()3549     bool HandleCallAccShort()
3550     {
3551         LOG_INST();
3552         DBGBRK();
3553         uint16_t vs1 = inst_.GetVReg<format, 0x00>();
3554         auto acc_pos = static_cast<unsigned>(inst_.GetImm<format, 0x00>());
3555         static constexpr auto NUM_ARGS = 2;
3556         if (acc_pos >= NUM_ARGS) {
3557             LOG_VERIFIER_ACCUMULATOR_POSITION_IS_OUT_OF_RANGE();
3558             SET_STATUS_FOR_MSG(AccumulatorPositionIsOutOfRange);
3559             return status_ != VerificationStatus::ERROR;
3560         }
3561         const CachedMethod *method = GetCachedMethod();
3562         if (method != nullptr) {
3563             LOG_VERIFIER_DEBUG_METHOD(method->GetName());
3564         }
3565         Sync();
3566         std::array<int, NUM_ARGS> regs;
3567         if (acc_pos == 0) {
3568             regs = {ACC, vs1};
3569         } else {
3570             regs = {vs1, ACC};
3571         }
3572         auto fetcher = LazyFetch(regs);
3573         return CheckCall<format>(method, fetcher);
3574     }
3575 
3576     template <BytecodeInstructionSafe::Format format>
HandleCallDynShort()3577     bool HandleCallDynShort()
3578     {
3579         LOG_INST();
3580         DBGBRK();
3581         // TODO(vdyadov): implement
3582         Sync();
3583         LOG(ERROR, VERIFIER) << "Verifier error: instruction is not implemented";
3584         status_ = VerificationStatus::ERROR;
3585         return false;
3586     }
3587 
3588     template <BytecodeInstructionSafe::Format format>
HandleCalliDynShort()3589     bool HandleCalliDynShort()
3590     {
3591         LOG_INST();
3592         DBGBRK();
3593         // TODO(vdyadov): implement
3594         Sync();
3595         LOG(ERROR, VERIFIER) << "Verifier error: instruction is not implemented";
3596         status_ = VerificationStatus::ERROR;
3597         return false;
3598     }
3599 
3600     template <BytecodeInstructionSafe::Format format>
HandleCallDyn()3601     bool HandleCallDyn()
3602     {
3603         LOG_INST();
3604         DBGBRK();
3605         // TODO(vdyadov): implement
3606         Sync();
3607         LOG(ERROR, VERIFIER) << "Verifier error: instruction is not implemented";
3608         status_ = VerificationStatus::ERROR;
3609         return false;
3610     }
3611 
3612     template <BytecodeInstructionSafe::Format format>
HandleCalliDyn()3613     bool HandleCalliDyn()
3614     {
3615         LOG_INST();
3616         DBGBRK();
3617         // TODO(vdyadov): implement
3618         Sync();
3619         LOG(ERROR, VERIFIER) << "Verifier error: instruction is not implemented";
3620         status_ = VerificationStatus::ERROR;
3621         return false;
3622     }
3623 
3624     template <BytecodeInstructionSafe::Format format>
HandleCallDynRange()3625     bool HandleCallDynRange()
3626     {
3627         LOG_INST();
3628         DBGBRK();
3629         // TODO(vdyadov): implement
3630         Sync();
3631         LOG(ERROR, VERIFIER) << "Verifier error: instruction is not implemented";
3632         status_ = VerificationStatus::ERROR;
3633         return false;
3634     }
3635 
3636     template <BytecodeInstructionSafe::Format format>
HandleCalliDynRange()3637     bool HandleCalliDynRange()
3638     {
3639         LOG_INST();
3640         DBGBRK();
3641         // TODO(vdyadov): implement
3642         Sync();
3643         LOG(ERROR, VERIFIER) << "Verifier error: instruction is not implemented";
3644         status_ = VerificationStatus::ERROR;
3645         return false;
3646     }
3647 
3648     template <BytecodeInstructionSafe::Format format>
HandleCall()3649     bool HandleCall()
3650     {
3651         LOG_INST();
3652         DBGBRK();
3653         uint16_t vs1 = inst_.GetVReg<format, 0x00>();
3654         uint16_t vs2 = inst_.GetVReg<format, 0x01>();
3655         uint16_t vs3 = inst_.GetVReg<format, 0x02>();
3656         uint16_t vs4 = inst_.GetVReg<format, 0x03>();
3657         const CachedMethod *method = GetCachedMethod();
3658         if (method != nullptr) {
3659             LOG_VERIFIER_DEBUG_METHOD(method->GetName());
3660         }
3661         Sync();
3662         const std::array<int, 4> regs {vs1, vs2, vs3, vs4};
3663         auto fetcher = LazyFetch(regs);
3664         return CheckCall<format>(method, fetcher);
3665     }
3666 
3667     template <BytecodeInstructionSafe::Format format>
HandleCallAcc()3668     bool HandleCallAcc()
3669     {
3670         LOG_INST();
3671         DBGBRK();
3672         auto acc_pos = static_cast<unsigned>(inst_.GetImm<format, 0x0>());
3673         static constexpr auto NUM_ARGS = 4;
3674         if (acc_pos >= NUM_ARGS) {
3675             LOG_VERIFIER_ACCUMULATOR_POSITION_IS_OUT_OF_RANGE();
3676             SET_STATUS_FOR_MSG(AccumulatorPositionIsOutOfRange);
3677             return status_ != VerificationStatus::ERROR;
3678         }
3679         const CachedMethod *method = GetCachedMethod();
3680         if (method != nullptr) {
3681             LOG_VERIFIER_DEBUG_METHOD(method->GetName());
3682         }
3683         Sync();
3684         std::array<int, NUM_ARGS> regs;
3685         auto reg_idx = 0;
3686         for (unsigned i = 0; i < NUM_ARGS; ++i) {
3687             if (i == acc_pos) {
3688                 regs[i] = ACC;
3689             } else {
3690                 regs[i] = static_cast<int>(inst_.GetVReg(reg_idx++));
3691             }
3692         }
3693         auto fetcher = LazyFetch(regs);
3694         return CheckCall<format>(method, fetcher);
3695     }
3696 
3697     template <BytecodeInstructionSafe::Format format>
HandleCallRange()3698     bool HandleCallRange()
3699     {
3700         LOG_INST();
3701         DBGBRK();
3702         uint16_t vs = inst_.GetVReg<format, 0x00>();
3703         const CachedMethod *method = GetCachedMethod();
3704         if (method != nullptr) {
3705             LOG_VERIFIER_DEBUG_METHOD(method->GetName());
3706         }
3707         Sync();
3708         return CheckCall<format>(method, [this, reg_idx = vs]() mutable -> std::optional<int> {
3709             if (!ExecCtx().CurrentRegContext().IsRegDefined(reg_idx)) {
3710                 return {};
3711             }
3712             return reg_idx++;
3713         });
3714     }
3715 
3716     template <BytecodeInstructionSafe::Format format>
HandleCallVirtShort()3717     bool HandleCallVirtShort()
3718     {
3719         LOG_INST();
3720         DBGBRK();
3721         uint16_t vs1 = inst_.GetVReg<format, 0x00>();
3722         uint16_t vs2 = inst_.GetVReg<format, 0x01>();
3723         const CachedMethod *method = GetCachedMethod();
3724         if (method != nullptr) {
3725             LOG_VERIFIER_DEBUG_METHOD(method->GetName());
3726         }
3727         if (method != nullptr && method->flags[CachedMethod::Flag::STATIC]) {
3728             LOG_VERIFIER_BAD_CALL_STATIC_METHOD_AS_VIRTUAL(method->GetName());
3729             SET_STATUS_FOR_MSG(BadCallStaticMethodAsVirtual);
3730             return false;
3731         }
3732 
3733         Sync();
3734         const std::array<int, 4> regs {vs1, vs2};
3735         auto fetcher = LazyFetch(regs);
3736         return CheckCall<format>(method, fetcher);
3737     }
3738 
3739     template <BytecodeInstructionSafe::Format format>
HandleCallVirtAccShort()3740     bool HandleCallVirtAccShort()
3741     {
3742         LOG_INST();
3743         DBGBRK();
3744         uint16_t vs1 = inst_.GetVReg<format, 0x00>();
3745         auto acc_pos = static_cast<unsigned>(inst_.GetImm<format, 0x00>());
3746         static constexpr auto NUM_ARGS = 2;
3747         const CachedMethod *method = GetCachedMethod();
3748         if (method != nullptr) {
3749             LOG_VERIFIER_DEBUG_METHOD(method->GetName());
3750         }
3751         if (method != nullptr && method->flags[CachedMethod::Flag::STATIC]) {
3752             LOG_VERIFIER_BAD_CALL_STATIC_METHOD_AS_VIRTUAL(method->GetName());
3753             SET_STATUS_FOR_MSG(BadCallStaticMethodAsVirtual);
3754             return false;
3755         }
3756         Sync();
3757         std::array<int, NUM_ARGS> regs;
3758         if (acc_pos == 0) {
3759             regs = {ACC, vs1};
3760         } else {
3761             regs = {vs1, ACC};
3762         }
3763         auto fetcher = LazyFetch(regs);
3764         return CheckCall<format>(method, fetcher);
3765     }
3766 
3767     template <BytecodeInstructionSafe::Format format>
HandleCallVirt()3768     bool HandleCallVirt()
3769     {
3770         LOG_INST();
3771         DBGBRK();
3772         uint16_t vs1 = inst_.GetVReg<format, 0x00>();
3773         uint16_t vs2 = inst_.GetVReg<format, 0x01>();
3774         uint16_t vs3 = inst_.GetVReg<format, 0x02>();
3775         uint16_t vs4 = inst_.GetVReg<format, 0x03>();
3776         const CachedMethod *method = GetCachedMethod();
3777         if (method != nullptr) {
3778             LOG_VERIFIER_DEBUG_METHOD(method->GetName());
3779         }
3780         if (method != nullptr && method->flags[CachedMethod::Flag::STATIC]) {
3781             LOG_VERIFIER_BAD_CALL_STATIC_METHOD_AS_VIRTUAL(method->GetName());
3782             SET_STATUS_FOR_MSG(BadCallStaticMethodAsVirtual);
3783             return false;
3784         }
3785 
3786         Sync();
3787         const std::array<int, 4> regs {vs1, vs2, vs3, vs4};
3788         auto fetcher = LazyFetch(regs);
3789         return CheckCall<format>(method, fetcher);
3790     }
3791 
3792     template <BytecodeInstructionSafe::Format format>
HandleCallVirtAcc()3793     bool HandleCallVirtAcc()
3794     {
3795         LOG_INST();
3796         DBGBRK();
3797         auto acc_pos = static_cast<unsigned>(inst_.GetImm<format, 0x0>());
3798         static constexpr auto NUM_ARGS = 4;
3799         const CachedMethod *method = GetCachedMethod();
3800         if (method != nullptr) {
3801             LOG_VERIFIER_DEBUG_METHOD(method->GetName());
3802         }
3803         if (method != nullptr && method->flags[CachedMethod::Flag::STATIC]) {
3804             LOG_VERIFIER_BAD_CALL_STATIC_METHOD_AS_VIRTUAL(method->GetName());
3805             SET_STATUS_FOR_MSG(BadCallStaticMethodAsVirtual);
3806             return false;
3807         }
3808         Sync();
3809         std::array<int, NUM_ARGS> regs;
3810         auto reg_idx = 0;
3811         for (unsigned i = 0; i < NUM_ARGS; ++i) {
3812             if (i == acc_pos) {
3813                 regs[i] = ACC;
3814             } else {
3815                 regs[i] = static_cast<int>(inst_.GetVReg(reg_idx++));
3816             }
3817         }
3818         auto fetcher = LazyFetch(regs);
3819         return CheckCall<format>(method, fetcher);
3820     }
3821 
3822     template <BytecodeInstructionSafe::Format format>
HandleCallVirtRange()3823     bool HandleCallVirtRange()
3824     {
3825         LOG_INST();
3826         DBGBRK();
3827         uint16_t vs = inst_.GetVReg<format, 0x00>();
3828 
3829         const CachedMethod *method = GetCachedMethod();
3830         if (method != nullptr) {
3831             LOG_VERIFIER_DEBUG_METHOD(method->GetName());
3832         }
3833         if (method != nullptr && method->flags[CachedMethod::Flag::STATIC]) {
3834             LOG_VERIFIER_BAD_CALL_STATIC_METHOD_AS_VIRTUAL(method->GetName());
3835             SET_STATUS_FOR_MSG(BadCallStaticMethodAsVirtual);
3836             return false;
3837         }
3838 
3839         Sync();
3840         return CheckCall<format>(method, [this, reg_idx = vs]() mutable -> std::optional<int> {
3841             if (!ExecCtx().CurrentRegContext().IsRegDefined(reg_idx)) {
3842                 return {};
3843             }
3844             return reg_idx++;
3845         });
3846     }
3847 
3848     template <BytecodeInstructionSafe::Format format>
HandleThrow()3849     bool HandleThrow()
3850     {
3851         LOG_INST();
3852         DBGBRK();
3853         ExecCtx().SetCheckPoint(inst_.GetAddress());
3854         Sync();
3855         uint16_t vs = inst_.GetVReg<format>();
3856         if (!CheckRegTypes(vs, {Types().ObjectType()})) {
3857             SET_STATUS_FOR_MSG(BadRegisterType);
3858             SET_STATUS_FOR_MSG(UndefinedRegister);
3859             return false;
3860         }
3861         // possible implementation:
3862         // on stage of building checkpoints:
3863         // - add all catch block starts as checkpoints/entries
3864         // on absint stage:
3865         // - find corresponding catch block/checkpoint/entry
3866         // - add context to checkpoint/entry
3867         // - add entry to entry list
3868         // - stop absint
3869         return false;
3870     }
3871 
3872     template <BytecodeInstructionSafe::Format format>
HandleMonitorenter()3873     bool HandleMonitorenter()
3874     {
3875         LOG_INST();
3876         DBGBRK();
3877         Sync();
3878         auto &&acc_type = GetAccType();
3879         if (acc_type.ForAllTypes([&](Type acc_type1) { return acc_type1 == Types().NullRefType(); })) {
3880             // TODO(vdyadov): redesign next code, after support exception handlers,
3881             //                treat it as always throw NPE
3882             SHOW_MSG(AlwaysNpeAccumulator)
3883             LOG_VERIFIER_ALWAYS_NPE_ACCUMULATOR();
3884             END_SHOW_MSG();
3885             SET_STATUS_FOR_MSG(AlwaysNpeAccumulator);
3886             return false;
3887         }
3888         if (!CheckTypes(acc_type, {Types().RefType()})) {
3889             SET_STATUS_FOR_MSG(BadRegisterType);
3890             SET_STATUS_FOR_MSG(UndefinedRegister);
3891             return false;
3892         }
3893         MoveToNextInst<format>();
3894         return true;
3895     }
3896 
3897     template <BytecodeInstructionSafe::Format format>
HandleMonitorexit()3898     bool HandleMonitorexit()
3899     {
3900         LOG_INST();
3901         DBGBRK();
3902         Sync();
3903         auto &&acc_type = GetAccType();
3904         if (acc_type.ForAllTypes([&](Type acc_type1) { return acc_type1 == Types().NullRefType(); })) {
3905             // TODO(vdyadov): redesign next code, after support exception handlers,
3906             //                treat it as always throw NPE
3907             SHOW_MSG(AlwaysNpeAccumulator)
3908             LOG_VERIFIER_ALWAYS_NPE_ACCUMULATOR();
3909             END_SHOW_MSG();
3910             SET_STATUS_FOR_MSG(AlwaysNpeAccumulator);
3911             return false;
3912         }
3913         if (!CheckTypes(acc_type, {Types().RefType()})) {
3914             SET_STATUS_FOR_MSG(BadRegisterType);
3915             SET_STATUS_FOR_MSG(UndefinedRegister);
3916             return false;
3917         }
3918         MoveToNextInst<format>();
3919         return true;
3920     }
3921 
GetInst()3922     BytecodeInstructionSafe GetInst()
3923     {
3924         return inst_;
3925     }
3926 
3927     template <BytecodeInstructionSafe::Format format>
HandleCallPolymorphicShort()3928     bool HandleCallPolymorphicShort()
3929     {
3930         LOG_INST();
3931         DBGBRK();
3932         Sync();
3933         MoveToNextInst<format>();
3934         return true;
3935     }
3936 
3937     template <BytecodeInstructionSafe::Format format>
HandleCallPolymorphic()3938     bool HandleCallPolymorphic()
3939     {
3940         LOG_INST();
3941         DBGBRK();
3942         Sync();
3943         MoveToNextInst<format>();
3944         return true;
3945     }
3946 
3947     template <BytecodeInstructionSafe::Format format>
HandleCallPolymorphicRange()3948     bool HandleCallPolymorphicRange()
3949     {
3950         LOG_INST();
3951         DBGBRK();
3952         Sync();
3953         // It is a runtime (not verifier) responibility to check the MethodHandle.invoke()
3954         // parameter types and throw the WrongMethodTypeException if need
3955         MoveToNextInst<format>();
3956         return true;
3957     }
3958 
3959     template <BytecodeInstructionSafe::Format format>
HandleCallePolymorphicShort()3960     bool HandleCallePolymorphicShort()
3961     {
3962         LOG_INST();
3963         DBGBRK();
3964         Sync();
3965         MoveToNextInst<format>();
3966         return true;
3967     }
3968 
3969     template <BytecodeInstructionSafe::Format format>
HandleCallePolymorphic()3970     bool HandleCallePolymorphic()
3971     {
3972         LOG_INST();
3973         DBGBRK();
3974         Sync();
3975         MoveToNextInst<format>();
3976         return true;
3977     }
3978 
3979     template <BytecodeInstructionSafe::Format format>
HandleCallePolymorphicRange()3980     bool HandleCallePolymorphicRange()
3981     {
3982         LOG_INST();
3983         DBGBRK();
3984         Sync();
3985         // It is a runtime (not verifier) responibility to check the  MethodHandle.invokeExact()
3986         // parameter types and throw the WrongMethodTypeException if need
3987         MoveToNextInst<format>();
3988         return true;
3989     }
3990 
3991     static PandaString RegisterName(int reg_idx, bool capitalize = false)
3992     {
3993         if (reg_idx == ACC) {
3994             return capitalize ? "Accumulator" : "accumulator";
3995         } else {
3996             return PandaString {capitalize ? "Register v" : "register v"} + NumToStr(reg_idx);
3997         }
3998     }
3999 
4000 private:
GetCachedClass()4001     const CachedClass *GetCachedClass() const
4002     {
4003         auto offset = inst_.GetOffset();
4004         if (!CurrentJob.IsClassPresentForOffset(offset)) {
4005             SHOW_MSG(CacheMissForClassAtOffset)
4006             LOG_VERIFIER_CACHE_MISS_FOR_CLASS_AT_OFFSET(offset);
4007             END_SHOW_MSG();
4008 
4009             SHOW_MSG(CannotResolveClassId)
4010             LOG_VERIFIER_CANNOT_RESOLVE_CLASS_ID(inst_.GetId().AsFileId().GetOffset());
4011             END_SHOW_MSG();
4012             return nullptr;
4013         }
4014         return &CurrentJob.GetClass(offset);
4015     }
4016 
GetCachedMethod()4017     const CachedMethod *GetCachedMethod() const
4018     {
4019         auto offset = inst_.GetOffset();
4020         if (!CurrentJob.IsMethodPresentForOffset(offset)) {
4021             SHOW_MSG(CacheMissForMethodAtOffset)
4022             LOG_VERIFIER_CACHE_MISS_FOR_METHOD_AT_OFFSET(offset);
4023             END_SHOW_MSG();
4024 
4025             SHOW_MSG(CannotResolveMethodId)
4026             LOG_VERIFIER_CANNOT_RESOLVE_METHOD_ID(inst_.GetId().AsFileId().GetOffset());
4027             END_SHOW_MSG();
4028             return nullptr;
4029         }
4030         return &CurrentJob.GetMethod(offset);
4031     }
4032 
GetCachedField()4033     const CachedField *GetCachedField() const
4034     {
4035         auto offset = inst_.GetOffset();
4036         if (!CurrentJob.IsFieldPresentForOffset(offset)) {
4037             SHOW_MSG(CacheMissForFieldAtOffset)
4038             LOG_VERIFIER_CACHE_MISS_FOR_FIELD_AT_OFFSET(offset);
4039             END_SHOW_MSG();
4040 
4041             SHOW_MSG(CannotResolveFieldId)
4042             LOG_VERIFIER_CANNOT_RESOLVE_FIELD_ID(inst_.GetId().AsFileId().GetOffset());
4043             END_SHOW_MSG();
4044             return nullptr;
4045         }
4046         return &CurrentJob.GetField(offset);
4047     }
4048 
4049     template <BytecodeInstructionSafe::Format format>
MoveToNextInst()4050     void MoveToNextInst()
4051     {
4052         inst_ = inst_.GetNext<format>();
4053     }
4054 
4055     template <BytecodeInstructionSafe::Format format>
CheckArrayStore(int v1,int v2,const Type & expected_elt_type)4056     bool CheckArrayStore(int v1, int v2, const Type &expected_elt_type)
4057     {
4058         /*
4059         main rules:
4060         1. instruction should be strict in array element size, so for primitive types type equality is used
4061         2. accumulator may be subtype of array element type (under question)
4062         */
4063         if (!CheckRegTypes(v2, {Types().Integral32Type()})) {
4064             SET_STATUS_FOR_MSG(BadRegisterType);
4065             SET_STATUS_FOR_MSG(UndefinedRegister);
4066             return false;
4067         }
4068         if (!CheckRegTypes(v1, {Types().ArrayType()})) {
4069             SET_STATUS_FOR_MSG(BadRegisterType);
4070             SET_STATUS_FOR_MSG(UndefinedRegister);
4071             return false;
4072         }
4073         if (!IsRegDefined(ACC)) {
4074             SET_STATUS_FOR_MSG(UndefinedRegister);
4075             return false;
4076         }
4077         auto &&reg_type = GetRegType(v1);
4078 
4079         if (reg_type.ForAllTypes([&](Type reg_type1) { return reg_type1 == Types().NullRefType(); })) {
4080             // TODO(vdyadov): redesign next code, after support exception handlers,
4081             //                treat it as always throw NPE
4082             SHOW_MSG(AlwaysNpe)
4083             LOG_VERIFIER_ALWAYS_NPE(v1);
4084             END_SHOW_MSG();
4085             SetAcc(Types().Top());
4086             SET_STATUS_FOR_MSG(AlwaysNpe);
4087             return false;
4088         }
4089 
4090         auto &&arr_elt_type = GetArrayEltType(reg_type);
4091 
4092         if (arr_elt_type.ForAllTypes([&](Type arr_elt_type1) { return !(arr_elt_type1 <= expected_elt_type); })) {
4093             SHOW_MSG(BadArrayElementType2)
4094             LOG_VERIFIER_BAD_ARRAY_ELEMENT_TYPE2(ImageOf(arr_elt_type), ImageOf(expected_elt_type));
4095             END_SHOW_MSG();
4096             SET_STATUS_FOR_MSG(BadArrayElementType2);
4097             return false;
4098         }
4099 
4100         auto &&acc_type = GetAccType();
4101 
4102         // TODO(dvyadov): think of subtyping here. Can we really write more precise type into array?
4103         // since there is no problems with storage (all refs are of the same size)
4104         // and no problems with information losses, it seems fine at first sight.
4105         auto res = acc_type.ForAllTypes([&](Type acc_type1) {
4106             return arr_elt_type.ForAllTypes([&](Type arr_elt_type1) { return !(acc_type1 <= arr_elt_type1); });
4107         });
4108         if (res) {
4109             PandaVector<Type> arr_elt_type_members;
4110             arr_elt_type.ForAllTypes([&](Type arr_elt_type1) {
4111                 arr_elt_type_members.push_back(arr_elt_type1);
4112                 return true;
4113             });
4114             // accumulator is of wrong type
4115             SHOW_MSG(BadAccumulatorType)
4116             LOG_VERIFIER_BAD_ACCUMULATOR_TYPE(ImageOf(acc_type), ImageOf(arr_elt_type),
4117                                               ImagesOf(SubtypesOf(arr_elt_type_members)));
4118             END_SHOW_MSG();
4119             SET_STATUS_FOR_MSG(BadAccumulatorType);
4120             return false;
4121         }
4122 
4123         MoveToNextInst<format>();
4124         return true;
4125     }
4126 
4127     template <BytecodeInstructionSafe::Format format>
CheckArrayStoreExact(int v1,int v2,const Type & acc_supertype,const std::initializer_list<Type> & expected_elt_types)4128     bool CheckArrayStoreExact(int v1, int v2, const Type &acc_supertype,
4129                               const std::initializer_list<Type> &expected_elt_types)
4130     {
4131         if (!CheckRegTypes(v2, {Types().Integral32Type()}) || !CheckRegTypes(v1, {Types().ArrayType()}) ||
4132             !IsRegDefined(ACC)) {
4133             SET_STATUS_FOR_MSG(BadRegisterType);
4134             SET_STATUS_FOR_MSG(UndefinedRegister);
4135             return false;
4136         }
4137         auto &&reg_type = GetRegType(v1);
4138 
4139         if (reg_type.ForAllTypes([&](Type reg_type1) { return reg_type1 == Types().NullRefType(); })) {
4140             SHOW_MSG(AlwaysNpe)
4141             LOG_VERIFIER_ALWAYS_NPE(v1);
4142             END_SHOW_MSG();
4143             SetAcc(Types().Top());
4144             SET_STATUS_FOR_MSG(AlwaysNpe);
4145             return false;
4146         }
4147 
4148         auto &&arr_elt_type = GetArrayEltType(reg_type);
4149 
4150         auto find = [&expected_elt_types](const auto &type) {
4151             return type.ExistsType([&expected_elt_types](auto type1) {
4152                 for (const auto &t : expected_elt_types) {
4153                     if (type1 == t) {
4154                         return true;
4155                     }
4156                 }
4157                 return false;
4158             });
4159         };
4160 
4161         if (!find(arr_elt_type)) {
4162             // array elt type is not expected one
4163             LOG_VERIFIER_BAD_ARRAY_ELEMENT_TYPE3(ImageOf(arr_elt_type), ImagesOf(expected_elt_types));
4164             SET_STATUS_FOR_MSG(BadArrayElementType);
4165             return false;
4166         }
4167 
4168         auto &&acc_type = GetAccType();
4169 
4170         if (acc_type.ForAllTypes([&](Type acc_type1) { return !(acc_type1 <= acc_supertype); })) {
4171             LOG_VERIFIER_BAD_ACCUMULATOR_TYPE2(ImageOf(acc_type), ImagesOf(SubtypesOf({acc_supertype})));
4172             SET_STATUS_FOR_MSG(BadArrayElementType);
4173             return false;
4174         }
4175 
4176         if (!find(acc_type)) {
4177             // array elt type is not expected one
4178             LOG_VERIFIER_BAD_ACCUMULATOR_TYPE3(ImageOf(acc_type), ImagesOf(expected_elt_types));
4179             if (status_ != VerificationStatus::ERROR) {
4180                 status_ = VerificationStatus::WARNING;
4181             }
4182         }
4183 
4184         MoveToNextInst<format>();
4185         return true;
4186     }
4187 
4188     template <BytecodeInstructionSafe::Format format, typename T1, typename T2, typename T3>
CheckBinaryOp2(T1 acc_in,T2 reg_in,T3 acc_out)4189     bool CheckBinaryOp2(T1 acc_in, T2 reg_in, T3 acc_out)
4190     {
4191         uint16_t vs = inst_.GetVReg<format>();
4192         if (!CheckRegTypes(ACC, {acc_in})) {
4193             SET_STATUS_FOR_MSG(BadRegisterType);
4194             SET_STATUS_FOR_MSG(UndefinedRegister);
4195             return false;
4196         }
4197         if (!CheckRegTypes(vs, {reg_in})) {
4198             SET_STATUS_FOR_MSG(BadRegisterType);
4199             SET_STATUS_FOR_MSG(UndefinedRegister);
4200             return false;
4201         }
4202         SetAcc(acc_out);
4203         MoveToNextInst<format>();
4204         return true;
4205     }
4206 
4207     template <BytecodeInstructionSafe::Format format, typename T1, typename T2>
CheckBinaryOp2(T1 acc_in,T2 reg_in)4208     bool CheckBinaryOp2(T1 acc_in, T2 reg_in)
4209     {
4210         if (!IsRegDefined(ACC)) {
4211             SET_STATUS_FOR_MSG(UndefinedRegister);
4212             return false;
4213         }
4214         return CheckBinaryOp2<format>(acc_in, reg_in, GetAccType());
4215     }
4216 
4217     template <BytecodeInstructionSafe::Format format, typename T1, typename T2>
CheckBinaryOp2Imm(T1 acc_in,T2 acc_out)4218     bool CheckBinaryOp2Imm(T1 acc_in, T2 acc_out)
4219     {
4220         if (!CheckRegTypes(ACC, {acc_in})) {
4221             SET_STATUS_FOR_MSG(BadRegisterType);
4222             SET_STATUS_FOR_MSG(UndefinedRegister);
4223             return false;
4224         }
4225         SetAcc(acc_out);
4226         MoveToNextInst<format>();
4227         return true;
4228     }
4229 
4230     template <BytecodeInstructionSafe::Format format, typename T1>
CheckBinaryOp2Imm(T1 acc_in)4231     bool CheckBinaryOp2Imm(T1 acc_in)
4232     {
4233         if (!IsRegDefined(ACC)) {
4234             SET_STATUS_FOR_MSG(UndefinedRegister);
4235             return false;
4236         }
4237         return CheckBinaryOp2Imm<format>(acc_in, GetAccType());
4238     }
4239 
4240     template <BytecodeInstructionSafe::Format format, typename T1, typename T2>
CheckUnaryOp(T1 acc_in,T2 acc_out)4241     bool CheckUnaryOp(T1 acc_in, T2 acc_out)
4242     {
4243         if (!CheckRegTypes(ACC, {acc_in})) {
4244             SET_STATUS_FOR_MSG(BadRegisterType);
4245             SET_STATUS_FOR_MSG(UndefinedRegister);
4246             return false;
4247         }
4248         SetAcc(acc_out);
4249         MoveToNextInst<format>();
4250         return true;
4251     }
4252 
4253     template <BytecodeInstructionSafe::Format format, typename T1>
CheckUnaryOp(T1 acc_in)4254     bool CheckUnaryOp(T1 acc_in)
4255     {
4256         if (!IsRegDefined(ACC)) {
4257             SET_STATUS_FOR_MSG(UndefinedRegister);
4258             return false;
4259         }
4260         return CheckUnaryOp<format>(acc_in, GetAccType());
4261     }
4262 
4263     template <BytecodeInstructionSafe::Format format, typename T1, typename T2, typename T3>
CheckBinaryOp(T1 vs1_in,T2 vs2_in,T3 acc_out)4264     bool CheckBinaryOp(T1 vs1_in, T2 vs2_in, T3 acc_out)
4265     {
4266         uint16_t vs1 = inst_.GetVReg<format, 0x00>();
4267         uint16_t vs2 = inst_.GetVReg<format, 0x01>();
4268         if (!CheckRegTypes(vs1, {vs1_in})) {
4269             SET_STATUS_FOR_MSG(BadRegisterType);
4270             SET_STATUS_FOR_MSG(UndefinedRegister);
4271             return false;
4272         }
4273         if (!CheckRegTypes(vs2, {vs2_in})) {
4274             SET_STATUS_FOR_MSG(BadRegisterType);
4275             SET_STATUS_FOR_MSG(UndefinedRegister);
4276             return false;
4277         }
4278         SetAcc(acc_out);
4279         MoveToNextInst<format>();
4280         return true;
4281     }
4282 
4283     template <BytecodeInstructionSafe::Format format, typename T1, typename T2>
CheckBinaryOp(T1 vs1_in,T2 vs2_in)4284     bool CheckBinaryOp(T1 vs1_in, T2 vs2_in)
4285     {
4286         if (!IsRegDefined(ACC)) {
4287             SET_STATUS_FOR_MSG(UndefinedRegister);
4288             return false;
4289         }
4290         return CheckBinaryOp<format>(vs1_in, vs2_in, GetAccType());
4291     }
4292 
4293     template <BytecodeInstructionSafe::Format format>
HandleConversion(Type from,Type to)4294     bool HandleConversion(Type from, Type to)
4295     {
4296         if (!CheckRegTypes(ACC, {from})) {
4297             SET_STATUS_FOR_MSG(BadRegisterType);
4298             SET_STATUS_FOR_MSG(UndefinedRegister);
4299             return false;
4300         }
4301         SetAcc(to);
4302         MoveToNextInst<format>();
4303         return true;
4304     }
4305 
IsConcreteArrayType(Type type)4306     bool IsConcreteArrayType(Type type)
4307     {
4308         return type <= Types().ArrayType() && type.ParamsSize() == 1;
4309     }
4310 
GetArrayEltType(Type arr_type)4311     Type GetArrayEltType(Type arr_type)
4312     {
4313         if (arr_type <= Types().ArrayType()) {
4314             auto &&type_params = arr_type.Params();
4315             ASSERT(type_params.size() == 1);
4316             return Types().TypeOf(type_params[0]);
4317         } else {
4318             return Types().Top();
4319         }
4320     }
4321 
GetArrayEltType(const AbstractType & arr_type)4322     AbstractType GetArrayEltType(const AbstractType &arr_type)
4323     {
4324         if (arr_type.IsType()) {
4325             return GetArrayEltType(arr_type.GetType());
4326         } else if (arr_type.IsTypeSet()) {
4327             TypeSet result(Types().GetKind(), Types().GetThreadNum());
4328             arr_type.GetTypeSet().ForAll([&](Type type1) {
4329                 if (IsConcreteArrayType(type1)) {
4330                     result.Insert(GetArrayEltType(type1));
4331                 }
4332                 return true;
4333             });
4334             return result;
4335         }
4336         return {};
4337     }
4338 
4339     template <BytecodeInstructionSafe::Format format>
CheckArrayLoad(int vs,const PandaVector<Type> & elt_types)4340     bool CheckArrayLoad(int vs, const PandaVector<Type> &elt_types)
4341     {
4342         if (!CheckRegTypes(ACC, {Types().Integral32Type()})) {
4343             SET_STATUS_FOR_MSG(BadRegisterType);
4344             SET_STATUS_FOR_MSG(UndefinedRegister);
4345             return false;
4346         }
4347         if (!CheckRegTypes(vs, {Types().ArrayType()})) {
4348             SET_STATUS_FOR_MSG(BadRegisterType);
4349             SET_STATUS_FOR_MSG(UndefinedRegister);
4350             return false;
4351         }
4352         auto &&reg_type = GetRegType(vs);
4353         if (reg_type.ForAllTypes([&](Type reg_type1) { return reg_type1 == Types().NullRefType(); })) {
4354             // TODO(vdyadov): redesign next code, after support exception handlers,
4355             //                treat it as always throw NPE
4356             SHOW_MSG(AlwaysNpe)
4357             LOG_VERIFIER_ALWAYS_NPE(vs);
4358             END_SHOW_MSG();
4359             SetAcc(Types().Top());
4360             SET_STATUS_FOR_MSG(AlwaysNpe);
4361             return false;
4362         }
4363         auto &&arr_elt_type = GetArrayEltType(reg_type);
4364         auto res = IsItemPresent(elt_types, [&arr_elt_type](const auto &type) {
4365             return arr_elt_type.ExistsType([&](auto arr_elt_type1) { return type == arr_elt_type1; });
4366         });
4367         if (!res) {
4368             LOG_VERIFIER_BAD_ARRAY_ELEMENT_TYPE3(ImageOf(arr_elt_type), ImagesOf(elt_types));
4369             SET_STATUS_FOR_MSG(BadArrayElementType);
4370             return false;
4371         }
4372         SetAcc(arr_elt_type);
4373         MoveToNextInst<format>();
4374         return true;
4375     }
4376 
ProcessBranching(int32_t offset)4377     bool ProcessBranching(int32_t offset)
4378     {
4379         auto new_inst = inst_.JumpTo(offset);
4380         const uint8_t *target = new_inst.GetAddress();
4381         if (!context_.CflowInfo().InstMap().CanJumpTo(target)) {
4382             LOG_VERIFIER_INCORRECT_JUMP();
4383             status_ = VerificationStatus::ERROR;
4384             return false;
4385         }
4386 
4387 #ifndef NDEBUG
4388         ExecCtx().ProcessJump(
4389             inst_.GetAddress(), target,
4390             [this, print_hdr = true](int reg_idx, const auto &src_reg, const auto &dst_reg) mutable {
4391                 if (print_hdr) {
4392                     LOG_VERIFIER_REGISTER_CONFLICT_HEADER();
4393                     print_hdr = false;
4394                 }
4395                 LOG_VERIFIER_REGISTER_CONFLICT(RegisterName(reg_idx), ImageOf(src_reg.GetAbstractType()),
4396                                                ImageOf(dst_reg.GetAbstractType()));
4397                 return true;
4398             },
4399             code_type_);
4400 #else
4401         ExecCtx().ProcessJump(inst_.GetAddress(), target, code_type_);
4402 #endif
4403         return true;
4404     }
4405 
4406     template <BytecodeInstructionSafe::Format format, template <typename OpT> class Op>
HandleCondJmpz()4407     bool HandleCondJmpz()
4408     {
4409         auto imm = inst_.GetImm<format>();
4410 
4411         if (!CheckRegTypes(ACC, {Types().Integral32Type()})) {
4412             SET_STATUS_FOR_MSG(BadRegisterType);
4413             SET_STATUS_FOR_MSG(UndefinedRegister);
4414             return false;
4415         }
4416 
4417         if (!ProcessBranching(imm)) {
4418             return false;
4419         }
4420 
4421         MoveToNextInst<format>();
4422         return true;
4423     }
4424 
4425     template <BytecodeInstructionSafe::Format format, template <typename OpT> class Op>
HandleCondJmp()4426     bool HandleCondJmp()
4427     {
4428         auto imm = inst_.GetImm<format>();
4429         uint16_t vs = inst_.GetVReg<format>();
4430 
4431         if (!CheckRegTypes(ACC, {Types().Integral32Type()})) {
4432             SET_STATUS_FOR_MSG(BadRegisterType);
4433             SET_STATUS_FOR_MSG(UndefinedRegister);
4434             return false;
4435         }
4436 
4437         if (!CheckRegTypes(vs, {Types().Integral32Type()})) {
4438             SET_STATUS_FOR_MSG(BadRegisterType);
4439             SET_STATUS_FOR_MSG(UndefinedRegister);
4440             return false;
4441         }
4442 
4443         if (!ProcessBranching(imm)) {
4444             return false;
4445         }
4446 
4447         MoveToNextInst<format>();
4448         return true;
4449     }
4450 
4451     template <BytecodeInstructionSafe::Format format, typename Fetcher>
CheckArrayCtor(const CachedMethod & ctor,Fetcher reg_nums)4452     bool CheckArrayCtor(const CachedMethod &ctor, Fetcher reg_nums)
4453     {
4454         Type klass = Types().TypeOf(ctor.klass);
4455         if (!klass.IsValid()) {
4456             return false;
4457         }
4458         auto args_num = ctor.signature.size() - 1;
4459         bool result = false;
4460         ForEachCond(reg_nums, [&args_num, &result, this](int reg) {
4461             if (!IsRegDefined(reg)) {
4462                 SET_STATUS_FOR_MSG(UndefinedRegister);
4463                 return result = false;
4464             }
4465             result = CheckRegTypes(reg, {I32});
4466             if (!result) {
4467                 LOG(ERROR, VERIFIER) << "Verifier error: ArrayCtor type error";
4468                 status_ = VerificationStatus::ERROR;
4469             }
4470             --args_num;
4471             return result && args_num > 0;
4472         });
4473         if (result && args_num > 0) {
4474             SHOW_MSG(TooFewArrayConstructorArgs)
4475             LOG_VERIFIER_TOO_FEW_ARRAY_CONSTRUCTOR_ARGS(args_num);
4476             END_SHOW_MSG();
4477             SET_STATUS_FOR_MSG(TooFewArrayConstructorArgs);
4478             result = false;
4479         }
4480         if (result) {
4481             SetAcc(klass);
4482             MoveToNextInst<format>();
4483         }
4484         return result;
4485     }
4486 
LogInnerMessage(const CheckResult & elt)4487     void LogInnerMessage(const CheckResult &elt)
4488     {
4489         if (elt.IsError()) {
4490             LOG(ERROR, VERIFIER) << "Error: " << elt.msg << ". ";
4491         } else if (elt.IsWarning()) {
4492             LOG(WARNING, VERIFIER) << "Warning: " << elt.msg << ". ";
4493         }
4494     }
4495 
SubSupTypesOf(Type type)4496     PandaVector<Type> SubSupTypesOf(Type type)
4497     {
4498         PandaVector<Type> result;
4499         auto callback = [&result](auto t) {
4500             if (!t.IsBot() && !t.IsTop()) {
4501                 result.push_back(t);
4502             }
4503             return true;
4504         };
4505         type.ForAllSubtypes(callback);
4506         type.ForAllSupertypes(callback);
4507         return result;
4508     }
4509 
4510 private:
4511     BytecodeInstructionSafe inst_;
4512     VerificationContext &context_;
4513     VerificationStatus status_;
4514     // #ifndef NDEBUG
4515     bool debug_ {false};
4516     uint32_t debug_offset_ {0};
4517     // #endif
4518     EntryPointType code_type_;
4519 
AddCheckResult(PandaVector<CheckResult> & results,const CheckResult & result)4520     static bool AddCheckResult(PandaVector<CheckResult> &results, const CheckResult &result)
4521     {
4522         if (result.IsOk()) {
4523             results.clear();
4524             return false;
4525         } else if (result.IsWarning() && results.size() > 0 && results[0].IsError()) {
4526             results.clear();
4527         }
4528         results.push_back(std::move(result));
4529         return true;
4530     }
4531 };
4532 }  // namespace panda::verifier
4533 
4534 #endif  // PANDA_VERIFICATION_ABSINT_ABS_INT_INL_H
4535