bool StackMapFrame::is_assignable_to(const StackMapFrame* target, TRAPS) const { if (_max_locals != target->max_locals() || _stack_size != target->stack_size()) { return false; } // Only need to compare type elements up to target->locals() or target->stack(). // The remaining type elements in this state can be ignored because they are // assignable to bogus type. bool match_locals = is_assignable_to( _locals, target->locals(), target->locals_size(), CHECK_false); bool match_stack = is_assignable_to( _stack, target->stack(), _stack_size, CHECK_false); bool match_flags = (_flags | target->flags()) == target->flags(); return (match_locals && match_stack && match_flags); }
match_t<DexType, std::tuple<const DexType*> > is_assignable_to(const DexType* parent) { return { [](const DexType* child, const DexType* const& parent) { return is_assignable_to(child, parent); }, parent }; }
bool StackMapFrame::is_assignable_to( const StackMapFrame* target, bool is_exception_handler, ErrorContext* ctx, TRAPS) const { if (_max_locals != target->max_locals()) { *ctx = ErrorContext::locals_size_mismatch( _offset, (StackMapFrame*)this, (StackMapFrame*)target); return false; } if (_stack_size != target->stack_size()) { *ctx = ErrorContext::stack_size_mismatch( _offset, (StackMapFrame*)this, (StackMapFrame*)target); return false; } // Only need to compare type elements up to target->locals() or target->stack(). // The remaining type elements in this state can be ignored because they are // assignable to bogus type. int mismatch_loc; mismatch_loc = is_assignable_to( _locals, target->locals(), target->locals_size(), THREAD); if (mismatch_loc != target->locals_size()) { *ctx = ErrorContext::bad_type(target->offset(), TypeOrigin::local(mismatch_loc, (StackMapFrame*)this), TypeOrigin::sm_local(mismatch_loc, (StackMapFrame*)target)); return false; } mismatch_loc = is_assignable_to(_stack, target->stack(), _stack_size, THREAD); if (mismatch_loc != _stack_size) { *ctx = ErrorContext::bad_type(target->offset(), TypeOrigin::stack(mismatch_loc, (StackMapFrame*)this), TypeOrigin::sm_stack(mismatch_loc, (StackMapFrame*)target)); return false; } bool match_flags = (_flags | target->flags()) == target->flags(); if (match_flags || is_exception_handler && has_flag_match_exception(target)) { return true; } else { *ctx = ErrorContext::bad_flags(target->offset(), (StackMapFrame*)this, (StackMapFrame*)target); return false; } }