Merge "Quick compiler: fix array overrun."
diff --git a/compiler/dex/frontend.cc b/compiler/dex/frontend.cc
index 6bb2284..3d22774 100644
--- a/compiler/dex/frontend.cc
+++ b/compiler/dex/frontend.cc
@@ -393,21 +393,22 @@
// Instruction::UNUSED_FE,
// Instruction::UNUSED_FF,
+ // TODO(Arm64): Enable compiler pass
// ----- ExtendedMIROpcode -----
- // kMirOpPhi,
- // kMirOpCopy,
- // kMirOpFusedCmplFloat,
- // kMirOpFusedCmpgFloat,
- // kMirOpFusedCmplDouble,
- // kMirOpFusedCmpgDouble,
- // kMirOpFusedCmpLong,
- // kMirOpNop,
- // kMirOpNullCheck,
- // kMirOpRangeCheck,
+ kMirOpPhi,
+ kMirOpCopy,
+ kMirOpFusedCmplFloat,
+ kMirOpFusedCmpgFloat,
+ kMirOpFusedCmplDouble,
+ kMirOpFusedCmpgDouble,
+ kMirOpFusedCmpLong,
+ kMirOpNop,
+ kMirOpNullCheck,
+ kMirOpRangeCheck,
kMirOpDivZeroCheck,
kMirOpCheck,
- // kMirOpCheckPart2,
- // kMirOpSelect,
+ kMirOpCheckPart2,
+ kMirOpSelect,
// kMirOpLast,
};
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc
index 23f2516..1460ce6 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -416,7 +416,8 @@
// TODO: flesh out support for Mips. NOTE: llvm's select op doesn't quite work here.
// TUNING: expand to support IF_xx compare & branches
if (!cu_->compiler->IsPortable() &&
- (cu_->instruction_set == kThumb2 || cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64) &&
+ (cu_->instruction_set == kArm64 || cu_->instruction_set == kThumb2 ||
+ cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64) &&
IsInstructionIfCcZ(mir->dalvikInsn.opcode)) {
BasicBlock* ft = GetBasicBlock(bb->fall_through);
DCHECK(ft != NULL);
@@ -442,6 +443,8 @@
if (SelectKind(tk->last_mir_insn) == kSelectGoto) {
tk->last_mir_insn->optimization_flags |= (MIR_IGNORE_SUSPEND_CHECK);
}
+
+ // TODO: Add logic for LONG.
// Are the block bodies something we can handle?
if ((ft->first_mir_insn == ft->last_mir_insn) &&
(tk->first_mir_insn != tk->last_mir_insn) &&
diff --git a/compiler/dex/quick/arm64/codegen_arm64.h b/compiler/dex/quick/arm64/codegen_arm64.h
index fddbfd7..16bb701 100644
--- a/compiler/dex/quick/arm64/codegen_arm64.h
+++ b/compiler/dex/quick/arm64/codegen_arm64.h
@@ -222,8 +222,6 @@
bool skip_this);
private:
- void GenFusedLongCmpImmBranch(BasicBlock* bb, RegLocation rl_src1, int64_t val,
- ConditionCode ccode);
LIR* LoadFPConstantValue(int r_dest, int32_t value);
LIR* LoadFPConstantValueWide(int r_dest, int64_t value);
void ReplaceFixup(LIR* prev_lir, LIR* orig_lir, LIR* new_lir);
diff --git a/compiler/dex/quick/arm64/int_arm64.cc b/compiler/dex/quick/arm64/int_arm64.cc
index 8dad90a..d9428f9 100644
--- a/compiler/dex/quick/arm64/int_arm64.cc
+++ b/compiler/dex/quick/arm64/int_arm64.cc
@@ -29,7 +29,6 @@
return OpCondBranch(cond, target);
}
-// TODO(Arm64): remove this.
LIR* Arm64Mir2Lir::OpIT(ConditionCode ccode, const char* guide) {
LOG(FATAL) << "Unexpected use of OpIT for Arm64";
return NULL;
@@ -85,154 +84,58 @@
StoreValueWide(rl_dest, rl_result);
}
-void Arm64Mir2Lir::GenFusedLongCmpImmBranch(BasicBlock* bb, RegLocation rl_src1,
- int64_t val, ConditionCode ccode) {
- LIR* taken = &block_label_list_[bb->taken];
- rl_src1 = LoadValueWide(rl_src1, kCoreReg);
-
- if (val == 0 && (ccode == kCondEq || ccode == kCondNe)) {
- ArmOpcode opcode = (ccode == kCondEq) ? kA64Cbz2rt : kA64Cbnz2rt;
- LIR* branch = NewLIR2(WIDE(opcode), rl_src1.reg.GetLowReg(), 0);
- branch->target = taken;
- } else {
- OpRegImm64(kOpCmp, rl_src1.reg, val);
- OpCondBranch(ccode, taken);
- }
-}
-
void Arm64Mir2Lir::GenSelect(BasicBlock* bb, MIR* mir) {
- // TODO(Arm64): implement this.
- UNIMPLEMENTED(FATAL);
-
RegLocation rl_result;
RegLocation rl_src = mir_graph_->GetSrc(mir, 0);
RegLocation rl_dest = mir_graph_->GetDest(mir);
rl_src = LoadValue(rl_src, kCoreReg);
- ConditionCode ccode = mir->meta.ccode;
- if (mir->ssa_rep->num_uses == 1) {
- // CONST case
- int true_val = mir->dalvikInsn.vB;
- int false_val = mir->dalvikInsn.vC;
- rl_result = EvalLoc(rl_dest, kCoreReg, true);
- // Change kCondNe to kCondEq for the special cases below.
- if (ccode == kCondNe) {
- ccode = kCondEq;
- std::swap(true_val, false_val);
- }
- bool cheap_false_val = InexpensiveConstantInt(false_val);
- if (cheap_false_val && ccode == kCondEq && (true_val == 0 || true_val == -1)) {
- OpRegRegImm(kOpSub, rl_result.reg, rl_src.reg, -true_val);
- DCHECK(last_lir_insn_->u.m.def_mask & ENCODE_CCODE);
- OpIT(true_val == 0 ? kCondNe : kCondUge, "");
- LoadConstant(rl_result.reg, false_val);
- GenBarrier(); // Add a scheduling barrier to keep the IT shadow intact
- } else if (cheap_false_val && ccode == kCondEq && true_val == 1) {
- OpRegRegImm(kOpRsub, rl_result.reg, rl_src.reg, 1);
- DCHECK(last_lir_insn_->u.m.def_mask & ENCODE_CCODE);
- OpIT(kCondLs, "");
- LoadConstant(rl_result.reg, false_val);
- GenBarrier(); // Add a scheduling barrier to keep the IT shadow intact
- } else if (cheap_false_val && InexpensiveConstantInt(true_val)) {
- OpRegImm(kOpCmp, rl_src.reg, 0);
- OpIT(ccode, "E");
- LoadConstant(rl_result.reg, true_val);
- LoadConstant(rl_result.reg, false_val);
- GenBarrier(); // Add a scheduling barrier to keep the IT shadow intact
- } else {
- // Unlikely case - could be tuned.
- RegStorage t_reg1 = AllocTemp();
- RegStorage t_reg2 = AllocTemp();
- LoadConstant(t_reg1, true_val);
- LoadConstant(t_reg2, false_val);
- OpRegImm(kOpCmp, rl_src.reg, 0);
- OpIT(ccode, "E");
- OpRegCopy(rl_result.reg, t_reg1);
- OpRegCopy(rl_result.reg, t_reg2);
- GenBarrier(); // Add a scheduling barrier to keep the IT shadow intact
- }
- } else {
- // MOVE case
- RegLocation rl_true = mir_graph_->reg_location_[mir->ssa_rep->uses[1]];
- RegLocation rl_false = mir_graph_->reg_location_[mir->ssa_rep->uses[2]];
- rl_true = LoadValue(rl_true, kCoreReg);
- rl_false = LoadValue(rl_false, kCoreReg);
- rl_result = EvalLoc(rl_dest, kCoreReg, true);
- OpRegImm(kOpCmp, rl_src.reg, 0);
- if (rl_result.reg.GetReg() == rl_true.reg.GetReg()) { // Is the "true" case already in place?
- OpIT(NegateComparison(ccode), "");
- OpRegCopy(rl_result.reg, rl_false.reg);
- } else if (rl_result.reg.GetReg() == rl_false.reg.GetReg()) { // False case in place?
- OpIT(ccode, "");
- OpRegCopy(rl_result.reg, rl_true.reg);
- } else { // Normal - select between the two.
- OpIT(ccode, "E");
- OpRegCopy(rl_result.reg, rl_true.reg);
- OpRegCopy(rl_result.reg, rl_false.reg);
- }
- GenBarrier(); // Add a scheduling barrier to keep the IT shadow intact
- }
+ ArmConditionCode code = ArmConditionEncoding(mir->meta.ccode);
+
+ RegLocation rl_true = mir_graph_->reg_location_[mir->ssa_rep->uses[1]];
+ RegLocation rl_false = mir_graph_->reg_location_[mir->ssa_rep->uses[2]];
+ rl_true = LoadValue(rl_true, kCoreReg);
+ rl_false = LoadValue(rl_false, kCoreReg);
+ rl_result = EvalLoc(rl_dest, kCoreReg, true);
+ OpRegImm(kOpCmp, rl_src.reg, 0);
+ NewLIR4(kA64Csel4rrrc, rl_result.reg.GetReg(), rl_true.reg.GetReg(),
+ rl_false.reg.GetReg(), code);
StoreValue(rl_dest, rl_result);
}
void Arm64Mir2Lir::GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) {
- // TODO(Arm64): implement this.
- UNIMPLEMENTED(FATAL);
-
RegLocation rl_src1 = mir_graph_->GetSrcWide(mir, 0);
RegLocation rl_src2 = mir_graph_->GetSrcWide(mir, 2);
+ LIR* taken = &block_label_list_[bb->taken];
+ LIR* not_taken = &block_label_list_[bb->fall_through];
+ rl_src1 = LoadValueWide(rl_src1, kCoreReg);
// Normalize such that if either operand is constant, src2 will be constant.
ConditionCode ccode = mir->meta.ccode;
if (rl_src1.is_const) {
std::swap(rl_src1, rl_src2);
ccode = FlipComparisonOrder(ccode);
}
+
if (rl_src2.is_const) {
- RegLocation rl_temp = UpdateLocWide(rl_src2);
- // Do special compare/branch against simple const operand if not already in registers.
+ rl_src2 = UpdateLocWide(rl_src2);
int64_t val = mir_graph_->ConstantValueWide(rl_src2);
- if ((rl_temp.location != kLocPhysReg)
- /*&& ((ModifiedImmediate(Low32Bits(val)) >= 0) && (ModifiedImmediate(High32Bits(val)) >= 0))*/) {
- GenFusedLongCmpImmBranch(bb, rl_src1, val, ccode);
+ // Special handling using cbz & cbnz.
+ if (val == 0 && (ccode == kCondEq || ccode == kCondNe)) {
+ OpCmpImmBranch(ccode, rl_src1.reg, 0, taken);
+ OpCmpImmBranch(NegateComparison(ccode), rl_src1.reg, 0, not_taken);
+ return;
+ // Only handle Imm if src2 is not already in a register.
+ } else if (rl_src2.location != kLocPhysReg) {
+ OpRegImm64(kOpCmp, rl_src1.reg, val);
+ OpCondBranch(ccode, taken);
+ OpCondBranch(NegateComparison(ccode), not_taken);
return;
}
}
- LIR* taken = &block_label_list_[bb->taken];
- LIR* not_taken = &block_label_list_[bb->fall_through];
- rl_src1 = LoadValueWide(rl_src1, kCoreReg);
+
rl_src2 = LoadValueWide(rl_src2, kCoreReg);
- OpRegReg(kOpCmp, rl_src1.reg.GetHigh(), rl_src2.reg.GetHigh());
- switch (ccode) {
- case kCondEq:
- OpCondBranch(kCondNe, not_taken);
- break;
- case kCondNe:
- OpCondBranch(kCondNe, taken);
- break;
- case kCondLt:
- OpCondBranch(kCondLt, taken);
- OpCondBranch(kCondGt, not_taken);
- ccode = kCondUlt;
- break;
- case kCondLe:
- OpCondBranch(kCondLt, taken);
- OpCondBranch(kCondGt, not_taken);
- ccode = kCondLs;
- break;
- case kCondGt:
- OpCondBranch(kCondGt, taken);
- OpCondBranch(kCondLt, not_taken);
- ccode = kCondHi;
- break;
- case kCondGe:
- OpCondBranch(kCondGt, taken);
- OpCondBranch(kCondLt, not_taken);
- ccode = kCondUge;
- break;
- default:
- LOG(FATAL) << "Unexpected ccode: " << ccode;
- }
- OpRegReg(kOpCmp, rl_src1.reg.GetLow(), rl_src2.reg.GetLow());
+ OpRegReg(kOpCmp, rl_src1.reg, rl_src2.reg);
OpCondBranch(ccode, taken);
+ OpCondBranch(NegateComparison(ccode), not_taken);
}
/*
@@ -468,7 +371,7 @@
RegLocation rl_dest = InlineTarget(info);
RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
OpRegReg(kOpCmp, rl_src1.reg, rl_src2.reg);
- OpIT((is_min) ? kCondGt : kCondLt, "E");
+ // OpIT((is_min) ? kCondGt : kCondLt, "E");
OpRegReg(kOpMov, rl_result.reg, rl_src2.reg);
OpRegReg(kOpMov, rl_result.reg, rl_src1.reg);
GenBarrier();
@@ -668,7 +571,7 @@
NewLIR3(kA64Ldxr2rX, r_tmp.GetReg(), r_ptr.GetReg(), 0);
OpRegReg(kOpSub, r_tmp, rl_expected.reg);
DCHECK(last_lir_insn_->u.m.def_mask & ENCODE_CCODE);
- OpIT(kCondEq, "T");
+ // OpIT(kCondEq, "T");
NewLIR4(kA64Stxr3wrX /* eq */, r_tmp.GetReg(), rl_new_value.reg.GetReg(), r_ptr.GetReg(), 0);
}
@@ -684,7 +587,7 @@
RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
OpRegRegImm(kOpRsub, rl_result.reg, r_tmp, 1);
DCHECK(last_lir_insn_->u.m.def_mask & ENCODE_CCODE);
- OpIT(kCondUlt, "");
+ // OpIT(kCondUlt, "");
LoadConstant(rl_result.reg, 0); /* cc */
FreeTemp(r_tmp); // Now unneeded.
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index 84afb2d..9d8888c 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -37,19 +37,19 @@
return FindClass(self, descriptor, NullHandle<mirror::ClassLoader>());
}
-inline mirror::Class* ClassLinker::FindArrayClass(Thread* self, mirror::Class* element_class) {
+inline mirror::Class* ClassLinker::FindArrayClass(Thread* self, mirror::Class** element_class) {
for (size_t i = 0; i < kFindArrayCacheSize; ++i) {
// Read the cached array class once to avoid races with other threads setting it.
mirror::Class* array_class = find_array_class_cache_[i];
- if (array_class != nullptr && array_class->GetComponentType() == element_class) {
+ if (array_class != nullptr && array_class->GetComponentType() == *element_class) {
return array_class;
}
}
- DCHECK(!element_class->IsPrimitiveVoid());
- std::string descriptor("[");
- descriptor += element_class->GetDescriptor();
- StackHandleScope<1> hs(Thread::Current());
- Handle<mirror::ClassLoader> class_loader(hs.NewHandle(element_class->GetClassLoader()));
+ DCHECK(!(*element_class)->IsPrimitiveVoid());
+ std::string descriptor = "[" + (*element_class)->GetDescriptor();
+ StackHandleScope<2> hs(Thread::Current());
+ Handle<mirror::ClassLoader> class_loader(hs.NewHandle((*element_class)->GetClassLoader()));
+ HandleWrapper<mirror::Class> h_element_class(hs.NewHandleWrapper(element_class));
mirror::Class* array_class = FindClass(self, descriptor.c_str(), class_loader);
// Benign races in storing array class and incrementing index.
size_t victim_index = find_array_class_cache_next_victim_;
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index a8271ed..ccf0558 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -84,7 +84,7 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Finds the array class given for the element class.
- mirror::Class* FindArrayClass(Thread* self, mirror::Class* element_class)
+ mirror::Class* FindArrayClass(Thread* self, mirror::Class** element_class)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Reutrns true if the class linker is initialized.
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index c11aecc..e397a5c 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -147,7 +147,8 @@
EXPECT_STREQ(direct_interface0->GetDescriptor().c_str(), "Ljava/lang/Cloneable;");
mirror::Class* direct_interface1 = mirror::Class::GetDirectInterface(self, array, 1);
EXPECT_STREQ(direct_interface1->GetDescriptor().c_str(), "Ljava/io/Serializable;");
- EXPECT_EQ(class_linker_->FindArrayClass(self, array->GetComponentType()), array.Get());
+ mirror::Class* array_ptr = array->GetComponentType();
+ EXPECT_EQ(class_linker_->FindArrayClass(self, &array_ptr), array.Get());
}
void AssertMethod(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
diff --git a/runtime/gc/space/large_object_space_test.cc b/runtime/gc/space/large_object_space_test.cc
index 23c67ff..f733584 100644
--- a/runtime/gc/space/large_object_space_test.cc
+++ b/runtime/gc/space/large_object_space_test.cc
@@ -24,6 +24,10 @@
class LargeObjectSpaceTest : public SpaceTest {
public:
void LargeObjectTest();
+
+ static constexpr size_t kNumThreads = 10;
+ static constexpr size_t kNumIterations = 1000;
+ void RaceTest();
};
@@ -89,11 +93,64 @@
}
}
+class AllocRaceTask : public Task {
+ public:
+ AllocRaceTask(size_t id, size_t iterations, size_t size, LargeObjectSpace* los) :
+ id_(id), iterations_(iterations), size_(size), los_(los) {}
+
+ void Run(Thread* self) {
+ for (size_t i = 0; i < iterations_ ; ++i) {
+ size_t alloc_size;
+ mirror::Object* ptr = los_->Alloc(self, size_, &alloc_size, nullptr);
+
+ NanoSleep((id_ + 3) * 1000); // (3+id) mu s
+
+ los_->Free(self, ptr);
+ }
+ }
+
+ virtual void Finalize() {
+ delete this;
+ }
+
+ private:
+ size_t id_;
+ size_t iterations_;
+ size_t size_;
+ LargeObjectSpace* los_;
+};
+
+void LargeObjectSpaceTest::RaceTest() {
+ for (size_t los_type = 0; los_type < 2; ++los_type) {
+ LargeObjectSpace* los = nullptr;
+ if (los_type == 0) {
+ los = space::LargeObjectMapSpace::Create("large object space");
+ } else {
+ los = space::FreeListSpace::Create("large object space", nullptr, 128 * MB);
+ }
+
+ Thread* self = Thread::Current();
+ ThreadPool thread_pool("Large object space test thread pool", kNumThreads);
+ for (size_t i = 0; i < kNumThreads; ++i) {
+ thread_pool.AddTask(self, new AllocRaceTask(i, kNumIterations, 16 * KB, los));
+ }
+
+ thread_pool.StartWorkers(self);
+
+ thread_pool.Wait(self, true, false);
+
+ delete los;
+ }
+}
TEST_F(LargeObjectSpaceTest, LargeObjectTest) {
LargeObjectTest();
}
+TEST_F(LargeObjectSpaceTest, RaceTest) {
+ RaceTest();
+}
+
} // namespace space
} // namespace gc
} // namespace art
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index f77a0f6..9cfba8d 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -33,7 +33,7 @@
DCHECK_GE(length, 0);
mirror::Class* element_class = reinterpret_cast<Object*>(args[0])->AsClass();
Runtime* runtime = Runtime::Current();
- mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(self, element_class);
+ mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(self, &element_class);
DCHECK(array_class != nullptr);
gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
result->SetL(mirror::Array::Alloc<true>(self, array_class, length,
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index a660183..f1284db 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -2058,7 +2058,7 @@
return nullptr;
}
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- array_class = class_linker->FindArrayClass(soa.Self(), element_class);
+ array_class = class_linker->FindArrayClass(soa.Self(), &element_class);
if (UNLIKELY(array_class == nullptr)) {
return nullptr;
}
diff --git a/runtime/mirror/array.cc b/runtime/mirror/array.cc
index 1076643..f7b5737 100644
--- a/runtime/mirror/array.cc
+++ b/runtime/mirror/array.cc
@@ -93,15 +93,17 @@
// Find/generate the array class.
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ mirror::Class* element_class_ptr = element_class.Get();
StackHandleScope<1> hs(self);
Handle<mirror::Class> array_class(
- hs.NewHandle(class_linker->FindArrayClass(self, element_class.Get())));
+ hs.NewHandle(class_linker->FindArrayClass(self, &element_class_ptr)));
if (UNLIKELY(array_class.Get() == nullptr)) {
CHECK(self->IsExceptionPending());
return nullptr;
}
for (int32_t i = 1; i < dimensions->GetLength(); ++i) {
- array_class.Assign(class_linker->FindArrayClass(self, array_class.Get()));
+ mirror::Class* array_class_ptr = array_class.Get();
+ array_class.Assign(class_linker->FindArrayClass(self, &array_class_ptr));
if (UNLIKELY(array_class.Get() == nullptr)) {
CHECK(self->IsExceptionPending());
return nullptr;
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index d55b545..e5cc671 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -67,7 +67,8 @@
return nullptr;
}
Runtime* runtime = Runtime::Current();
- mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(soa.Self(), element_class);
+ mirror::Class* array_class =
+ runtime->GetClassLinker()->FindArrayClass(soa.Self(), &element_class);
if (UNLIKELY(array_class == nullptr)) {
return nullptr;
}
@@ -90,7 +91,7 @@
return nullptr;
}
Runtime* runtime = Runtime::Current();
- mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(soa.Self(), element_class);
+ mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(soa.Self(), &element_class);
if (UNLIKELY(array_class == nullptr)) {
return nullptr;
}
diff --git a/runtime/native/java_lang_reflect_Array.cc b/runtime/native/java_lang_reflect_Array.cc
index db77437..eae4584 100644
--- a/runtime/native/java_lang_reflect_Array.cc
+++ b/runtime/native/java_lang_reflect_Array.cc
@@ -46,14 +46,14 @@
static jobject Array_createObjectArray(JNIEnv* env, jclass, jclass javaElementClass, jint length) {
ScopedFastNativeObjectAccess soa(env);
DCHECK(javaElementClass != NULL);
- mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass);
if (UNLIKELY(length < 0)) {
ThrowNegativeArraySizeException(length);
return NULL;
}
+ mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass);
Runtime* runtime = Runtime::Current();
ClassLinker* class_linker = runtime->GetClassLinker();
- mirror::Class* array_class = class_linker->FindArrayClass(soa.Self(), element_class);
+ mirror::Class* array_class = class_linker->FindArrayClass(soa.Self(), &element_class);
if (UNLIKELY(array_class == NULL)) {
CHECK(soa.Self()->IsExceptionPending());
return NULL;
diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc
index 8df1e5d..e24c920 100644
--- a/runtime/verifier/reg_type.cc
+++ b/runtime/verifier/reg_type.cc
@@ -929,7 +929,7 @@
}
mirror::Class* common_elem = ClassJoin(s_ct, t_ct);
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- mirror::Class* array_class = class_linker->FindArrayClass(Thread::Current(), common_elem);
+ mirror::Class* array_class = class_linker->FindArrayClass(Thread::Current(), &common_elem);
DCHECK(array_class != NULL);
return array_class;
} else {