diff options
| -rw-r--r-- | runtime/verifier/reg_type.cc | 24 | ||||
| -rw-r--r-- | test/800-smali/smali/b_22331663.smali | 17 |
2 files changed, 19 insertions, 22 deletions
diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc index 1435607e48..9c528190b2 100644 --- a/runtime/verifier/reg_type.cc +++ b/runtime/verifier/reg_type.cc @@ -583,24 +583,20 @@ static const RegType& SelectNonConstant(const RegType& a, const RegType& b) { const RegType& RegType::Merge(const RegType& incoming_type, RegTypeCache* reg_types) const { DCHECK(!Equals(incoming_type)); // Trivial equality handled by caller - // Perform pointer equality tests for conflict to avoid virtual method dispatch. + // Perform pointer equality tests for undefined and conflict to avoid virtual method dispatch. + const UndefinedType& undefined = reg_types->Undefined(); const ConflictType& conflict = reg_types->Conflict(); - if (IsUndefined() || incoming_type.IsUndefined()) { + DCHECK_EQ(this == &undefined, IsUndefined()); + DCHECK_EQ(&incoming_type == &undefined, incoming_type.IsUndefined()); + DCHECK_EQ(this == &conflict, IsConflict()); + DCHECK_EQ(&incoming_type == &conflict, incoming_type.IsConflict()); + if (this == &undefined || &incoming_type == &undefined) { // There is a difference between undefined and conflict. Conflicts may be copied around, but // not used. Undefined registers must not be copied. So any merge with undefined should return // undefined. - if (IsUndefined()) { - return *this; - } - return incoming_type; - } else if (this == &conflict) { - DCHECK(IsConflict()); - return *this; // Conflict MERGE * => Conflict - } else if (&incoming_type == &conflict) { - DCHECK(incoming_type.IsConflict()); - return incoming_type; // * MERGE Conflict => Conflict - } else if (IsUndefined() || incoming_type.IsUndefined()) { - return conflict; // Unknown MERGE * => Conflict + return undefined; + } else if (this == &conflict || &incoming_type == &conflict) { + return conflict; // (Conflict MERGE *) or (* MERGE Conflict) => Conflict } else if (IsConstant() && incoming_type.IsConstant()) { const ConstantType& type1 = *down_cast<const ConstantType*>(this); const ConstantType& type2 = *down_cast<const ConstantType*>(&incoming_type); diff --git a/test/800-smali/smali/b_22331663.smali b/test/800-smali/smali/b_22331663.smali index 057fc7f2a5..bae75c2924 100644 --- a/test/800-smali/smali/b_22331663.smali +++ b/test/800-smali/smali/b_22331663.smali @@ -4,29 +4,29 @@ .method public static run(Z)V .registers 6 - # Make v4 defined, just use null. - const v4, 0 + if-eqz v5, :if_eqz_target - if-eqz v5, :Label2 - -:Label1 # Construct a java.lang.Object completely, and throw a new exception. new-instance v4, Ljava/lang/Object; invoke-direct {v4}, Ljava/lang/Object;-><init>()V new-instance v3, Ljava/lang/RuntimeException; invoke-direct {v3}, Ljava/lang/RuntimeException;-><init>()V +:throw1_begin throw v3 +:throw1_end -:Label2 +:if_eqz_target # Allocate a java.lang.Object (do not initialize), and throw a new exception. new-instance v4, Ljava/lang/Object; new-instance v3, Ljava/lang/RuntimeException; invoke-direct {v3}, Ljava/lang/RuntimeException;-><init>()V +:throw2_begin throw v3 +:throw2_end -:Label3 +:catch_entry # Catch handler. Here we had to merge the uninitialized with the initialized reference, # which creates a conflict. Copy the conflict, and then return. This should not make the # verifier fail the method. @@ -34,5 +34,6 @@ return-void -.catchall {:Label1 .. :Label3} :Label3 +.catchall {:throw1_begin .. :throw1_end} :catch_entry +.catchall {:throw2_begin .. :throw2_end} :catch_entry .end method |