diff options
-rw-r--r-- | compiler/dex/quick/gen_common.cc | 135 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.cc | 26 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.h | 7 | ||||
-rw-r--r-- | compiler/image_writer.cc | 1 | ||||
-rw-r--r-- | compiler/llvm/gbc_expander.cc | 61 | ||||
-rw-r--r-- | compiler/llvm/intrinsic_func_list.def | 7 | ||||
-rw-r--r-- | runtime/asm_support.h | 4 | ||||
-rw-r--r-- | runtime/class_linker.cc | 12 | ||||
-rw-r--r-- | runtime/class_linker_test.cc | 14 | ||||
-rw-r--r-- | runtime/entrypoints/entrypoint_utils.h | 9 | ||||
-rw-r--r-- | runtime/mirror/art_method-inl.h | 6 | ||||
-rw-r--r-- | runtime/mirror/art_method.cc | 5 | ||||
-rw-r--r-- | runtime/mirror/art_method.h | 12 | ||||
-rw-r--r-- | runtime/mirror/class.h | 13 | ||||
-rw-r--r-- | runtime/mirror/dex_cache.cc | 22 | ||||
-rw-r--r-- | runtime/mirror/dex_cache.h | 15 | ||||
-rw-r--r-- | runtime/mirror/dex_cache_test.cc | 4 | ||||
-rw-r--r-- | runtime/native/dalvik_system_VMRuntime.cc | 16 | ||||
-rw-r--r-- | runtime/oat.cc | 2 |
19 files changed, 147 insertions, 224 deletions
diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc index a426cc7..6b4cbd4 100644 --- a/compiler/dex/quick/gen_common.cc +++ b/compiler/dex/quick/gen_common.cc @@ -330,21 +330,22 @@ void Mir2Lir::GenFilledNewArray(CallInfo* info) { void Mir2Lir::GenSput(uint32_t field_idx, RegLocation rl_src, bool is_long_or_double, bool is_object) { int field_offset; - int ssb_index; + int storage_index; bool is_volatile; bool is_referrers_class; + bool is_initialized; bool fast_path = cu_->compiler_driver->ComputeStaticFieldInfo( field_idx, mir_graph_->GetCurrentDexCompilationUnit(), true, - &field_offset, &ssb_index, &is_referrers_class, &is_volatile); + &field_offset, &storage_index, &is_referrers_class, &is_volatile, &is_initialized); if (fast_path && !SLOW_FIELD_PATH) { DCHECK_GE(field_offset, 0); - int rBase; + int r_base; if (is_referrers_class) { // Fast path, static storage base is this method's class RegLocation rl_method = LoadCurrMethod(); - rBase = AllocTemp(); + r_base = AllocTemp(); LoadWordDisp(rl_method.low_reg, - mirror::ArtMethod::DeclaringClassOffset().Int32Value(), rBase); + mirror::ArtMethod::DeclaringClassOffset().Int32Value(), r_base); if (IsTemp(rl_method.low_reg)) { FreeTemp(rl_method.low_reg); } @@ -352,33 +353,44 @@ void Mir2Lir::GenSput(uint32_t field_idx, RegLocation rl_src, bool is_long_or_do // Medium path, static storage base in a different class which requires checks that the other // class is initialized. // TODO: remove initialized check now that we are initializing classes in the compiler driver. - DCHECK_GE(ssb_index, 0); + DCHECK_GE(storage_index, 0); // May do runtime call so everything to home locations. FlushAllRegs(); // Using fixed register to sync with possible call to runtime support. int r_method = TargetReg(kArg1); LockTemp(r_method); LoadCurrMethodDirect(r_method); - rBase = TargetReg(kArg0); - LockTemp(rBase); + r_base = TargetReg(kArg0); + LockTemp(r_base); LoadWordDisp(r_method, - mirror::ArtMethod::DexCacheInitializedStaticStorageOffset().Int32Value(), - rBase); - LoadWordDisp(rBase, - mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() + - sizeof(int32_t*) * ssb_index, rBase); - // rBase now points at appropriate static storage base (Class*) - // or NULL if not initialized. Check for NULL and call helper if NULL. - // TUNING: fast path should fall through - LIR* branch_over = OpCmpImmBranch(kCondNe, rBase, 0, NULL); - LoadConstant(TargetReg(kArg0), ssb_index); - CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(pInitializeStaticStorage), ssb_index, true); - if (cu_->instruction_set == kMips) { - // For Arm, kRet0 = kArg0 = rBase, for Mips, we need to copy - OpRegCopy(rBase, TargetReg(kRet0)); + mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(), + r_base); + LoadWordDisp(r_base, mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() + + sizeof(int32_t*) * storage_index, r_base); + // r_base now points at static storage (Class*) or NULL if the type is not yet resolved. + if (!is_initialized) { + // Check if r_base is NULL or a not yet initialized class. + // TUNING: fast path should fall through + LIR* unresolved_branch = OpCmpImmBranch(kCondEq, r_base, 0, NULL); + int r_tmp = TargetReg(kArg2); + LockTemp(r_tmp); + // TODO: Fuse the compare of a constant with memory on X86 and avoid the load. + LoadWordDisp(r_base, mirror::Class::StatusOffset().Int32Value(), r_tmp); + LIR* initialized_branch = OpCmpImmBranch(kCondGe, r_tmp, mirror::Class::kStatusInitialized, + NULL); + + LIR* unresolved_target = NewLIR0(kPseudoTargetLabel); + unresolved_branch->target = unresolved_target; + CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(pInitializeStaticStorage), storage_index, + true); + // Copy helper's result into r_base, a no-op on all but MIPS. + OpRegCopy(r_base, TargetReg(kRet0)); + + LIR* initialized_target = NewLIR0(kPseudoTargetLabel); + initialized_branch->target = initialized_target; + + FreeTemp(r_tmp); } - LIR* skip_target = NewLIR0(kPseudoTargetLabel); - branch_over->target = skip_target; FreeTemp(r_method); } // rBase now holds static storage base @@ -391,18 +403,18 @@ void Mir2Lir::GenSput(uint32_t field_idx, RegLocation rl_src, bool is_long_or_do GenMemBarrier(kStoreStore); } if (is_long_or_double) { - StoreBaseDispWide(rBase, field_offset, rl_src.low_reg, + StoreBaseDispWide(r_base, field_offset, rl_src.low_reg, rl_src.high_reg); } else { - StoreWordDisp(rBase, field_offset, rl_src.low_reg); + StoreWordDisp(r_base, field_offset, rl_src.low_reg); } if (is_volatile) { GenMemBarrier(kStoreLoad); } if (is_object && !mir_graph_->IsConstantNullRef(rl_src)) { - MarkGCCard(rl_src.low_reg, rBase); + MarkGCCard(rl_src.low_reg, r_base); } - FreeTemp(rBase); + FreeTemp(r_base); } else { FlushAllRegs(); // Everything to home locations ThreadOffset setter_offset = @@ -416,64 +428,77 @@ void Mir2Lir::GenSput(uint32_t field_idx, RegLocation rl_src, bool is_long_or_do void Mir2Lir::GenSget(uint32_t field_idx, RegLocation rl_dest, bool is_long_or_double, bool is_object) { int field_offset; - int ssb_index; + int storage_index; bool is_volatile; bool is_referrers_class; + bool is_initialized; bool fast_path = cu_->compiler_driver->ComputeStaticFieldInfo( field_idx, mir_graph_->GetCurrentDexCompilationUnit(), false, - &field_offset, &ssb_index, &is_referrers_class, &is_volatile); + &field_offset, &storage_index, &is_referrers_class, &is_volatile, &is_initialized); if (fast_path && !SLOW_FIELD_PATH) { DCHECK_GE(field_offset, 0); - int rBase; + int r_base; if (is_referrers_class) { // Fast path, static storage base is this method's class RegLocation rl_method = LoadCurrMethod(); - rBase = AllocTemp(); + r_base = AllocTemp(); LoadWordDisp(rl_method.low_reg, - mirror::ArtMethod::DeclaringClassOffset().Int32Value(), rBase); + mirror::ArtMethod::DeclaringClassOffset().Int32Value(), r_base); } else { // Medium path, static storage base in a different class which requires checks that the other // class is initialized - // TODO: remove initialized check now that we are initializing classes in the compiler driver. - DCHECK_GE(ssb_index, 0); + DCHECK_GE(storage_index, 0); // May do runtime call so everything to home locations. FlushAllRegs(); // Using fixed register to sync with possible call to runtime support. int r_method = TargetReg(kArg1); LockTemp(r_method); LoadCurrMethodDirect(r_method); - rBase = TargetReg(kArg0); - LockTemp(rBase); + r_base = TargetReg(kArg0); + LockTemp(r_base); LoadWordDisp(r_method, - mirror::ArtMethod::DexCacheInitializedStaticStorageOffset().Int32Value(), - rBase); - LoadWordDisp(rBase, mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() + - sizeof(int32_t*) * ssb_index, rBase); - // rBase now points at appropriate static storage base (Class*) - // or NULL if not initialized. Check for NULL and call helper if NULL. - // TUNING: fast path should fall through - LIR* branch_over = OpCmpImmBranch(kCondNe, rBase, 0, NULL); - CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(pInitializeStaticStorage), ssb_index, true); - if (cu_->instruction_set == kMips) { - // For Arm, kRet0 = kArg0 = rBase, for Mips, we need to copy - OpRegCopy(rBase, TargetReg(kRet0)); + mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(), + r_base); + LoadWordDisp(r_base, mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() + + sizeof(int32_t*) * storage_index, r_base); + // r_base now points at static storage (Class*) or NULL if the type is not yet resolved. + if (!is_initialized) { + // Check if r_base is NULL or a not yet initialized class. + // TUNING: fast path should fall through + LIR* unresolved_branch = OpCmpImmBranch(kCondEq, r_base, 0, NULL); + int r_tmp = TargetReg(kArg2); + LockTemp(r_tmp); + // TODO: Fuse the compare of a constant with memory on X86 and avoid the load. + LoadWordDisp(r_base, mirror::Class::StatusOffset().Int32Value(), r_tmp); + LIR* initialized_branch = OpCmpImmBranch(kCondGe, r_tmp, mirror::Class::kStatusInitialized, + NULL); + + LIR* unresolved_target = NewLIR0(kPseudoTargetLabel); + unresolved_branch->target = unresolved_target; + CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(pInitializeStaticStorage), storage_index, + true); + // Copy helper's result into r_base, a no-op on all but MIPS. + OpRegCopy(r_base, TargetReg(kRet0)); + + LIR* initialized_target = NewLIR0(kPseudoTargetLabel); + initialized_branch->target = initialized_target; + + FreeTemp(r_tmp); } - LIR* skip_target = NewLIR0(kPseudoTargetLabel); - branch_over->target = skip_target; FreeTemp(r_method); } - // rBase now holds static storage base + // r_base now holds static storage base RegLocation rl_result = EvalLoc(rl_dest, kAnyReg, true); if (is_volatile) { GenMemBarrier(kLoadLoad); } if (is_long_or_double) { - LoadBaseDispWide(rBase, field_offset, rl_result.low_reg, + LoadBaseDispWide(r_base, field_offset, rl_result.low_reg, rl_result.high_reg, INVALID_SREG); } else { - LoadWordDisp(rBase, field_offset, rl_result.low_reg); + LoadWordDisp(r_base, field_offset, rl_result.low_reg); } - FreeTemp(rBase); + FreeTemp(r_base); if (is_long_or_double) { StoreValueWide(rl_dest, rl_result); } else { diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 9cffb3c..5edc8b6 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -992,14 +992,16 @@ bool CompilerDriver::ComputeInstanceFieldInfo(uint32_t field_idx, const DexCompi } bool CompilerDriver::ComputeStaticFieldInfo(uint32_t field_idx, const DexCompilationUnit* mUnit, - bool is_put, int* field_offset, int* ssb_index, - bool* is_referrers_class, bool* is_volatile) { + bool is_put, int* field_offset, int* storage_index, + bool* is_referrers_class, bool* is_volatile, + bool* is_initialized) { ScopedObjectAccess soa(Thread::Current()); // Conservative defaults. *field_offset = -1; - *ssb_index = -1; + *storage_index = -1; *is_referrers_class = false; *is_volatile = true; + *is_initialized = false; // Try to resolve field and ignore if an Incompatible Class Change Error (ie isn't static). mirror::ArtField* resolved_field = ComputeFieldReferencedFromCompilingMethod(soa, mUnit, field_idx); if (resolved_field != NULL && resolved_field->IsStatic()) { @@ -1010,6 +1012,7 @@ bool CompilerDriver::ComputeStaticFieldInfo(uint32_t field_idx, const DexCompila mirror::Class* fields_class = resolved_field->GetDeclaringClass(); if (fields_class == referrer_class) { *is_referrers_class = true; // implies no worrying about class initialization + *is_initialized = true; *field_offset = resolved_field->GetOffset().Int32Value(); *is_volatile = resolved_field->IsVolatile(); stats_->ResolvedLocalStaticField(); @@ -1034,17 +1037,19 @@ bool CompilerDriver::ComputeStaticFieldInfo(uint32_t field_idx, const DexCompila } bool is_write_to_final_from_wrong_class = is_put && resolved_field->IsFinal(); if (access_ok && !is_write_to_final_from_wrong_class) { - // We have the resolved field, we must make it into a ssbIndex for the referrer - // in its static storage base (which may fail if it doesn't have a slot for it) + // We have the resolved field, we must make it into a index for the referrer + // in its static storage (which may fail if it doesn't have a slot for it) // TODO: for images we can elide the static storage base null check // if we know there's a non-null entry in the image mirror::DexCache* dex_cache = mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile()); if (fields_class->GetDexCache() == dex_cache) { // common case where the dex cache of both the referrer and the field are the same, // no need to search the dex file - *ssb_index = fields_class->GetDexTypeIndex(); + *storage_index = fields_class->GetDexTypeIndex(); *field_offset = resolved_field->GetOffset().Int32Value(); *is_volatile = resolved_field->IsVolatile(); + *is_initialized = fields_class->IsInitialized() && + CanAssumeTypeIsPresentInDexCache(*mUnit->GetDexFile(), *storage_index); stats_->ResolvedStaticField(); return true; } @@ -1057,9 +1062,11 @@ bool CompilerDriver::ComputeStaticFieldInfo(uint32_t field_idx, const DexCompila mUnit->GetDexFile()->FindTypeId(mUnit->GetDexFile()->GetIndexForStringId(*string_id)); if (type_id != NULL) { // medium path, needs check of static storage base being initialized - *ssb_index = mUnit->GetDexFile()->GetIndexForTypeId(*type_id); + *storage_index = mUnit->GetDexFile()->GetIndexForTypeId(*type_id); *field_offset = resolved_field->GetOffset().Int32Value(); *is_volatile = resolved_field->IsVolatile(); + *is_initialized = fields_class->IsInitialized() && + CanAssumeTypeIsPresentInDexCache(*mUnit->GetDexFile(), *storage_index); stats_->ResolvedStaticField(); return true; } @@ -2184,11 +2191,6 @@ static void InitializeClass(const ParallelCompilationManager* manager, size_t cl } soa.Self()->AssertNoPendingException(); } - // If successfully initialized place in SSB array. - if (klass->IsInitialized()) { - int32_t ssb_index = klass->GetDexTypeIndex(); - klass->GetDexCache()->GetInitializedStaticStorage()->Set(ssb_index, klass.get()); - } } // Record the final class status if necessary. ClassReference ref(manager->GetDexFile(), class_def_index); diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index f4cc84d..9e31624 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -172,8 +172,7 @@ class CompilerDriver { // Callbacks from compiler to see what runtime checks must be generated. - bool CanAssumeTypeIsPresentInDexCache(const DexFile& dex_file, uint32_t type_idx) - LOCKS_EXCLUDED(Locks::mutator_lock_); + bool CanAssumeTypeIsPresentInDexCache(const DexFile& dex_file, uint32_t type_idx); bool CanAssumeStringIsPresentInDexCache(const DexFile& dex_file, uint32_t string_idx) LOCKS_EXCLUDED(Locks::mutator_lock_); @@ -198,8 +197,8 @@ class CompilerDriver { // Can we fastpath static field access? Computes field's offset, volatility and whether the // field is within the referrer (which can avoid checking class initialization). bool ComputeStaticFieldInfo(uint32_t field_idx, const DexCompilationUnit* mUnit, bool is_put, - int* field_offset, int* ssb_index, - bool* is_referrers_class, bool* is_volatile) + int* field_offset, int* storage_index, + bool* is_referrers_class, bool* is_volatile, bool* is_initialized) LOCKS_EXCLUDED(Locks::mutator_lock_); // Can we fastpath a interface, super class or virtual method call? Computes method's vtable diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc index 02654ad..556dec2 100644 --- a/compiler/image_writer.cc +++ b/compiler/image_writer.cc @@ -316,7 +316,6 @@ void ImageWriter::PruneNonImageClasses() { Class* klass = dex_cache->GetResolvedType(i); if (klass != NULL && !IsImageClass(klass)) { dex_cache->SetResolvedType(i, NULL); - dex_cache->GetInitializedStaticStorage()->Set(i, NULL); } } for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) { diff --git a/compiler/llvm/gbc_expander.cc b/compiler/llvm/gbc_expander.cc index b206a25..6423cd7 100644 --- a/compiler/llvm/gbc_expander.cc +++ b/compiler/llvm/gbc_expander.cc @@ -199,8 +199,6 @@ class GBCExpanderPass : public llvm::FunctionPass { //---------------------------------------------------------------------------- llvm::Value* EmitLoadDexCacheAddr(art::MemberOffset dex_cache_offset); - llvm::Value* EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx); - llvm::Value* EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx); llvm::Value* EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx); @@ -287,8 +285,6 @@ class GBCExpanderPass : public llvm::FunctionPass { llvm::Value* Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr); - llvm::Value* Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value); - llvm::Value* Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value); @@ -720,16 +716,6 @@ llvm::Value* GBCExpanderPass::EmitLoadDexCacheAddr(art::MemberOffset offset) { } llvm::Value* -GBCExpanderPass::EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx) { - llvm::Value* static_storage_dex_cache_addr = - EmitLoadDexCacheAddr(art::mirror::ArtMethod::DexCacheInitializedStaticStorageOffset()); - - llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx); - - return EmitArrayGEP(static_storage_dex_cache_addr, type_idx_value, kObject); -} - -llvm::Value* GBCExpanderPass::EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx) { llvm::Value* resolved_type_dex_cache_addr = EmitLoadDexCacheAddr(art::mirror::ArtMethod::DexCacheResolvedTypesOffset()); @@ -1213,17 +1199,6 @@ GBCExpanderPass::Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr) { } llvm::Value* -GBCExpanderPass::Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value) { - uint32_t type_idx = - llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue(); - - llvm::Value* storage_field_addr = - EmitLoadDexCacheStaticStorageFieldAddr(type_idx); - - return irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo); -} - -llvm::Value* GBCExpanderPass::Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value) { uint32_t callee_method_idx = llvm::cast<llvm::ConstantInt>(callee_method_idx_value)->getZExtValue(); @@ -1837,21 +1812,31 @@ llvm::Value* GBCExpanderPass::EmitLoadStaticStorage(uint32_t dex_pc, llvm::BasicBlock* block_load_static = CreateBasicBlockWithDexPC(dex_pc, "load_static"); + llvm::BasicBlock* block_check_init = CreateBasicBlockWithDexPC(dex_pc, "init"); llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont"); // Load static storage from dex cache - llvm::Value* storage_field_addr = - EmitLoadDexCacheStaticStorageFieldAddr(type_idx); + llvm::Value* storage_field_addr = EmitLoadDexCacheResolvedTypeFieldAddr(type_idx); llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo); - llvm::BasicBlock* block_original = irb_.GetInsertBlock(); + // Test: Is the class resolved? + llvm::Value* equal_null = irb_.CreateICmpEQ(storage_object_addr, irb_.getJNull()); - // Test: Is the static storage of this class initialized? - llvm::Value* equal_null = - irb_.CreateICmpEQ(storage_object_addr, irb_.getJNull()); + irb_.CreateCondBr(equal_null, block_load_static, block_check_init, kUnlikely); - irb_.CreateCondBr(equal_null, block_load_static, block_cont, kUnlikely); + // storage_object_addr != null, so check if its initialized. + irb_.SetInsertPoint(block_check_init); + + llvm::Value* class_status = + irb_.LoadFromObjectOffset(storage_object_addr, + art::mirror::Class::StatusOffset().Int32Value(), + irb_.getJIntTy(), kTBAAHeapInstance); + + llvm::Value* is_not_initialized = + irb_.CreateICmpULT(class_status, irb_.getInt32(art::mirror::Class::kStatusInitialized)); + + irb_.CreateCondBr(is_not_initialized, block_load_static, block_cont, kUnlikely); // Failback routine to load the class object irb_.SetInsertPoint(block_load_static); @@ -1880,9 +1865,8 @@ llvm::Value* GBCExpanderPass::EmitLoadStaticStorage(uint32_t dex_pc, llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2); - phi->addIncoming(storage_object_addr, block_original); + phi->addIncoming(storage_object_addr, block_check_init); phi->addIncoming(loaded_storage_object_addr, block_after_load_static); - return phi; } @@ -1895,10 +1879,11 @@ llvm::Value* GBCExpanderPass::Expand_HLSget(llvm::CallInst& call_inst, int ssb_index; bool is_referrers_class; bool is_volatile; + bool is_initialized; bool is_fast_path = driver_->ComputeStaticFieldInfo( field_idx, dex_compilation_unit_, false, - &field_offset, &ssb_index, &is_referrers_class, &is_volatile); + &field_offset, &ssb_index, &is_referrers_class, &is_volatile, &is_initialized); llvm::Value* static_field_value; @@ -1979,10 +1964,11 @@ void GBCExpanderPass::Expand_HLSput(llvm::CallInst& call_inst, int ssb_index; bool is_referrers_class; bool is_volatile; + bool is_initialized; bool is_fast_path = driver_->ComputeStaticFieldInfo( field_idx, dex_compilation_unit_, true, - &field_offset, &ssb_index, &is_referrers_class, &is_volatile); + &field_offset, &ssb_index, &is_referrers_class, &is_volatile, &is_initialized); if (!is_fast_path) { llvm::Function* runtime_func; @@ -3360,9 +3346,6 @@ GBCExpanderPass::ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id, case IntrinsicHelper::LoadDeclaringClassSSB: { return Expand_LoadDeclaringClassSSB(call_inst.getArgOperand(0)); } - case IntrinsicHelper::LoadClassSSBFromDexCache: { - return Expand_LoadClassSSBFromDexCache(call_inst.getArgOperand(0)); - } case IntrinsicHelper::InitializeAndLoadClassSSB: { return ExpandToRuntime(InitializeStaticStorage, call_inst); } diff --git a/compiler/llvm/intrinsic_func_list.def b/compiler/llvm/intrinsic_func_list.def index 92537ba..887a626 100644 --- a/compiler/llvm/intrinsic_func_list.def +++ b/compiler/llvm/intrinsic_func_list.def @@ -863,13 +863,6 @@ _EVAL_DEF_INTRINSICS_FUNC(LoadDeclaringClassSSB, kJavaObjectTy, _EXPAND_ARG1(kJavaMethodTy)) -// JavaObject* art_portable_load_class_ssb_from_dex_cache(uint32_t type_idx) -_EVAL_DEF_INTRINSICS_FUNC(LoadClassSSBFromDexCache, - art_portable_load_class_ssb_from_dex_cache, - kAttrReadOnly | kAttrNoThrow, - kJavaObjectTy, - _EXPAND_ARG1(kInt32ConstantTy)) - // JavaObject* art_portable_init_and_load_class_ssb(uint32_t type_idx, // Method* referrer, // Thread* thread) diff --git a/runtime/asm_support.h b/runtime/asm_support.h index e9bbf91..06c7b53 100644 --- a/runtime/asm_support.h +++ b/runtime/asm_support.h @@ -39,7 +39,7 @@ #define STRING_DATA_OFFSET 12 // Offsets within java.lang.Method. -#define METHOD_DEX_CACHE_METHODS_OFFSET 16 -#define METHOD_CODE_OFFSET 40 +#define METHOD_DEX_CACHE_METHODS_OFFSET 12 +#define METHOD_CODE_OFFSET 36 #endif // ART_RUNTIME_ASM_SUPPORT_H_ diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index fbb47bd..dcc50b7 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -1242,15 +1242,8 @@ mirror::DexCache* ClassLinker::AllocDexCache(Thread* self, const DexFile& dex_fi if (fields.get() == NULL) { return NULL; } - SirtRef<mirror::ObjectArray<mirror::StaticStorageBase> > - initialized_static_storage(self, - AllocObjectArray<mirror::StaticStorageBase>(self, dex_file.NumTypeIds())); - if (initialized_static_storage.get() == NULL) { - return NULL; - } - dex_cache->Init(&dex_file, location.get(), strings.get(), types.get(), methods.get(), - fields.get(), initialized_static_storage.get()); + fields.get()); return dex_cache.get(); } @@ -1905,7 +1898,6 @@ mirror::ArtMethod* ClassLinker::LoadMethod(Thread* self, const DexFile& dex_file dst->SetDexCacheStrings(klass->GetDexCache()->GetStrings()); dst->SetDexCacheResolvedMethods(klass->GetDexCache()->GetResolvedMethods()); dst->SetDexCacheResolvedTypes(klass->GetDexCache()->GetResolvedTypes()); - dst->SetDexCacheInitializedStaticStorage(klass->GetDexCache()->GetInitializedStaticStorage()); uint32_t access_flags = it.GetMemberAccessFlags(); @@ -2941,8 +2933,6 @@ static void CheckProxyMethod(mirror::ArtMethod* method, CHECK_EQ(prototype->GetDexCacheStrings(), method->GetDexCacheStrings()); CHECK_EQ(prototype->GetDexCacheResolvedMethods(), method->GetDexCacheResolvedMethods()); CHECK_EQ(prototype->GetDexCacheResolvedTypes(), method->GetDexCacheResolvedTypes()); - CHECK_EQ(prototype->GetDexCacheInitializedStaticStorage(), - method->GetDexCacheInitializedStaticStorage()); CHECK_EQ(prototype->GetDexMethodIndex(), method->GetDexMethodIndex()); MethodHelper mh(method); diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index 34134fa..1744050 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -159,15 +159,12 @@ class ClassLinkerTest : public CommonTest { EXPECT_TRUE(method->GetDexCacheStrings() != NULL); EXPECT_TRUE(method->GetDexCacheResolvedMethods() != NULL); EXPECT_TRUE(method->GetDexCacheResolvedTypes() != NULL); - EXPECT_TRUE(method->GetDexCacheInitializedStaticStorage() != NULL); EXPECT_EQ(method->GetDeclaringClass()->GetDexCache()->GetStrings(), method->GetDexCacheStrings()); EXPECT_EQ(method->GetDeclaringClass()->GetDexCache()->GetResolvedMethods(), method->GetDexCacheResolvedMethods()); EXPECT_EQ(method->GetDeclaringClass()->GetDexCache()->GetResolvedTypes(), method->GetDexCacheResolvedTypes()); - EXPECT_EQ(method->GetDeclaringClass()->GetDexCache()->GetInitializedStaticStorage(), - method->GetDexCacheInitializedStaticStorage()); } void AssertField(mirror::Class* klass, mirror::ArtField* field) @@ -468,7 +465,6 @@ struct ArtMethodOffsets : public CheckOffsets<mirror::ArtMethod> { ArtMethodOffsets() : CheckOffsets<mirror::ArtMethod>(false, "Ljava/lang/reflect/ArtMethod;") { // alphabetical references offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, declaring_class_), "declaringClass")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_cache_initialized_static_storage_), "dexCacheInitializedStaticStorage")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_cache_resolved_methods_), "dexCacheResolvedMethods")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_cache_resolved_types_), "dexCacheResolvedTypes")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_cache_strings_), "dexCacheStrings")); @@ -607,7 +603,6 @@ struct DexCacheOffsets : public CheckOffsets<mirror::DexCache> { DexCacheOffsets() : CheckOffsets<mirror::DexCache>(false, "Ljava/lang/DexCache;") { // alphabetical references offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, dex_), "dex")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, initialized_static_storage_), "initializedStaticStorage")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, location_), "location")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, resolved_fields_), "resolvedFields")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, resolved_methods_), "resolvedMethods")); @@ -1006,13 +1001,12 @@ TEST_F(ClassLinkerTest, ResolveVerifyAndClinit) { const DexFile::TypeId* type_id = dex_file->FindTypeId(dex_file->GetIndexForStringId(*string_id)); ASSERT_TRUE(type_id != NULL); uint32_t type_idx = dex_file->GetIndexForTypeId(*type_id); - EXPECT_TRUE(clinit->GetDexCacheInitializedStaticStorage()->Get(type_idx) == NULL); - mirror::StaticStorageBase* uninit = ResolveVerifyAndClinit(type_idx, clinit, Thread::Current(), true, false); + mirror::Class* uninit = ResolveVerifyAndClinit(type_idx, clinit, Thread::Current(), true, false); EXPECT_TRUE(uninit != NULL); - EXPECT_TRUE(clinit->GetDexCacheInitializedStaticStorage()->Get(type_idx) == NULL); - mirror::StaticStorageBase* init = ResolveVerifyAndClinit(type_idx, getS0, Thread::Current(), true, false); + EXPECT_FALSE(uninit->IsInitialized()); + mirror::Class* init = ResolveVerifyAndClinit(type_idx, getS0, Thread::Current(), true, false); EXPECT_TRUE(init != NULL); - EXPECT_EQ(init, clinit->GetDexCacheInitializedStaticStorage()->Get(type_idx)); + EXPECT_TRUE(init->IsInitialized()); } TEST_F(ClassLinkerTest, FinalizableBit) { diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h index a60446c..e7fe072 100644 --- a/runtime/entrypoints/entrypoint_utils.h +++ b/runtime/entrypoints/entrypoint_utils.h @@ -517,15 +517,15 @@ static inline mirror::Class* ResolveVerifyAndClinit(uint32_t type_idx, SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); mirror::Class* klass = class_linker->ResolveType(type_idx, referrer); - if (UNLIKELY(klass == NULL)) { + if (UNLIKELY(klass == nullptr)) { CHECK(self->IsExceptionPending()); - return NULL; // Failure - Indicate to caller to deliver exception + return nullptr; // Failure - Indicate to caller to deliver exception } // Perform access check if necessary. mirror::Class* referring_class = referrer->GetDeclaringClass(); if (verify_access && UNLIKELY(!referring_class->CanAccess(klass))) { ThrowIllegalAccessErrorClass(referring_class, klass); - return NULL; // Failure - Indicate to caller to deliver exception + return nullptr; // Failure - Indicate to caller to deliver exception } // If we're just implementing const-class, we shouldn't call <clinit>. if (!can_run_clinit) { @@ -541,9 +541,8 @@ static inline mirror::Class* ResolveVerifyAndClinit(uint32_t type_idx, SirtRef<mirror::Class> sirt_class(self, klass); if (!class_linker->EnsureInitialized(sirt_class, true, true)) { CHECK(self->IsExceptionPending()); - return NULL; // Failure - Indicate to caller to deliver exception + return nullptr; // Failure - Indicate to caller to deliver exception } - referrer->GetDexCacheInitializedStaticStorage()->Set(type_idx, sirt_class.get()); return sirt_class.get(); } diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h index c9bf160..088f616 100644 --- a/runtime/mirror/art_method-inl.h +++ b/runtime/mirror/art_method-inl.h @@ -73,12 +73,6 @@ inline ObjectArray<Class>* ArtMethod::GetDexCacheResolvedTypes() const { OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_types_), false); } -inline ObjectArray<StaticStorageBase>* ArtMethod::GetDexCacheInitializedStaticStorage() const { - return GetFieldObject<ObjectArray<StaticStorageBase>*>( - OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_initialized_static_storage_), - false); -} - inline uint32_t ArtMethod::GetCodeSize() const { DCHECK(!IsRuntimeMethod() && !IsProxyMethod()) << PrettyMethod(this); uintptr_t code = reinterpret_cast<uintptr_t>(GetEntryPointFromCompiledCode()); diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc index a4f6b3b..f4a076c 100644 --- a/runtime/mirror/art_method.cc +++ b/runtime/mirror/art_method.cc @@ -86,11 +86,6 @@ void ArtMethod::SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_class new_dex_cache_classes, false); } -void ArtMethod::SetDexCacheInitializedStaticStorage(ObjectArray<StaticStorageBase>* new_value) { - SetFieldObject(OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_initialized_static_storage_), - new_value, false); -} - size_t ArtMethod::NumArgRegisters(const StringPiece& shorty) { CHECK_LE(1, shorty.length()); uint32_t num_registers = 0; diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h index d5524ec..963b4d5 100644 --- a/runtime/mirror/art_method.h +++ b/runtime/mirror/art_method.h @@ -184,11 +184,6 @@ class MANAGED ArtMethod : public Object { return OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_types_); } - static MemberOffset DexCacheInitializedStaticStorageOffset() { - return OFFSET_OF_OBJECT_MEMBER(ArtMethod, - dex_cache_initialized_static_storage_); - } - ObjectArray<ArtMethod>* GetDexCacheResolvedMethods() const; void SetDexCacheResolvedMethods(ObjectArray<ArtMethod>* new_dex_cache_methods) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -197,10 +192,6 @@ class MANAGED ArtMethod : public Object { void SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_types) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ObjectArray<StaticStorageBase>* GetDexCacheInitializedStaticStorage() const; - void SetDexCacheInitializedStaticStorage(ObjectArray<StaticStorageBase>* new_value) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - // Find the method that this method overrides ArtMethod* FindOverriddenMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -391,9 +382,6 @@ class MANAGED ArtMethod : public Object { Class* declaring_class_; // short cuts to declaring_class_->dex_cache_ member for fast compiled code access - ObjectArray<StaticStorageBase>* dex_cache_initialized_static_storage_; - - // short cuts to declaring_class_->dex_cache_ member for fast compiled code access ObjectArray<ArtMethod>* dex_cache_resolved_methods_; // short cuts to declaring_class_->dex_cache_ member for fast compiled code access diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index 50ede66..9aa23d9 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -70,15 +70,8 @@ class ClassLoader; class DexCache; class IfTable; -// Type for the InitializedStaticStorage table. Currently the Class -// provides the static storage. However, this might change to an Array -// to improve image sharing, so we use this type to avoid assumptions -// on the current storage. -class MANAGED StaticStorageBase : public Object { -}; - // C++ mirror of java.lang.Class -class MANAGED Class : public StaticStorageBase { +class MANAGED Class : public Object { public: // Class Status // @@ -133,6 +126,10 @@ class MANAGED Class : public StaticStorageBase { void SetStatus(Status new_status, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + static MemberOffset StatusOffset() { + return OFFSET_OF_OBJECT_MEMBER(Class, status_); + } + // Returns true if the class has failed to link. bool IsErroneous() const { return GetStatus() == kStatusError; diff --git a/runtime/mirror/dex_cache.cc b/runtime/mirror/dex_cache.cc index 00531e3..fa0900c 100644 --- a/runtime/mirror/dex_cache.cc +++ b/runtime/mirror/dex_cache.cc @@ -36,15 +36,13 @@ void DexCache::Init(const DexFile* dex_file, ObjectArray<String>* strings, ObjectArray<Class>* resolved_types, ObjectArray<ArtMethod>* resolved_methods, - ObjectArray<ArtField>* resolved_fields, - ObjectArray<StaticStorageBase>* initialized_static_storage) { - CHECK(dex_file != NULL); - CHECK(location != NULL); - CHECK(strings != NULL); - CHECK(resolved_types != NULL); - CHECK(resolved_methods != NULL); - CHECK(resolved_fields != NULL); - CHECK(initialized_static_storage != NULL); + ObjectArray<ArtField>* resolved_fields) { + CHECK(dex_file != nullptr); + CHECK(location != nullptr); + CHECK(strings != nullptr); + CHECK(resolved_types != nullptr); + CHECK(resolved_methods != nullptr); + CHECK(resolved_fields != nullptr); SetFieldPtr(OFFSET_OF_OBJECT_MEMBER(DexCache, dex_file_), dex_file, false); SetFieldObject(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), location, false); @@ -52,8 +50,6 @@ void DexCache::Init(const DexFile* dex_file, SetFieldObject(OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_types_), resolved_types, false); SetFieldObject(ResolvedMethodsOffset(), resolved_methods, false); SetFieldObject(ResolvedFieldsOffset(), resolved_fields, false); - SetFieldObject(OFFSET_OF_OBJECT_MEMBER(DexCache, initialized_static_storage_), - initialized_static_storage, false); Runtime* runtime = Runtime::Current(); if (runtime->HasResolutionMethod()) { @@ -68,11 +64,11 @@ void DexCache::Init(const DexFile* dex_file, void DexCache::Fixup(ArtMethod* trampoline) { // Fixup the resolve methods array to contain trampoline for resolution. - CHECK(trampoline != NULL); + CHECK(trampoline != nullptr); ObjectArray<ArtMethod>* resolved_methods = GetResolvedMethods(); size_t length = resolved_methods->GetLength(); for (size_t i = 0; i < length; i++) { - if (resolved_methods->GetWithoutChecks(i) == NULL) { + if (resolved_methods->GetWithoutChecks(i) == nullptr) { resolved_methods->SetWithoutChecks(i, trampoline); } } diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h index 0522f13..a5fe598 100644 --- a/runtime/mirror/dex_cache.h +++ b/runtime/mirror/dex_cache.h @@ -47,8 +47,7 @@ class MANAGED DexCache : public Object { ObjectArray<String>* strings, ObjectArray<Class>* types, ObjectArray<ArtMethod>* methods, - ObjectArray<ArtField>* fields, - ObjectArray<StaticStorageBase>* initialized_static_storage) + ObjectArray<ArtField>* fields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void Fixup(ArtMethod* trampoline) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -85,11 +84,6 @@ class MANAGED DexCache : public Object { return GetResolvedFields()->GetLength(); } - size_t NumInitializedStaticStorage() const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return GetInitializedStaticStorage()->GetLength(); - } - String* GetResolvedString(uint32_t string_idx) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return GetStrings()->Get(string_idx); @@ -149,12 +143,6 @@ class MANAGED DexCache : public Object { return GetFieldObject< ObjectArray<ArtField>* >(ResolvedFieldsOffset(), false); } - ObjectArray<StaticStorageBase>* GetInitializedStaticStorage() const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return GetFieldObject< ObjectArray<StaticStorageBase>* >( - OFFSET_OF_OBJECT_MEMBER(DexCache, initialized_static_storage_), false); - } - const DexFile* GetDexFile() const { return GetFieldPtr<const DexFile*>(OFFSET_OF_OBJECT_MEMBER(DexCache, dex_file_), false); } @@ -165,7 +153,6 @@ class MANAGED DexCache : public Object { private: Object* dex_; - ObjectArray<StaticStorageBase>* initialized_static_storage_; String* location_; ObjectArray<ArtField>* resolved_fields_; ObjectArray<ArtMethod>* resolved_methods_; diff --git a/runtime/mirror/dex_cache_test.cc b/runtime/mirror/dex_cache_test.cc index 441c6da..6bed224 100644 --- a/runtime/mirror/dex_cache_test.cc +++ b/runtime/mirror/dex_cache_test.cc @@ -39,13 +39,11 @@ TEST_F(DexCacheTest, Open) { EXPECT_EQ(java_lang_dex_file_->NumTypeIds(), dex_cache->NumResolvedTypes()); EXPECT_EQ(java_lang_dex_file_->NumMethodIds(), dex_cache->NumResolvedMethods()); EXPECT_EQ(java_lang_dex_file_->NumFieldIds(), dex_cache->NumResolvedFields()); - EXPECT_EQ(java_lang_dex_file_->NumTypeIds(), dex_cache->NumInitializedStaticStorage()); EXPECT_LE(0, dex_cache->GetStrings()->GetLength()); EXPECT_LE(0, dex_cache->GetResolvedTypes()->GetLength()); EXPECT_LE(0, dex_cache->GetResolvedMethods()->GetLength()); EXPECT_LE(0, dex_cache->GetResolvedFields()->GetLength()); - EXPECT_LE(0, dex_cache->GetInitializedStaticStorage()->GetLength()); EXPECT_EQ(java_lang_dex_file_->NumStringIds(), static_cast<uint32_t>(dex_cache->GetStrings()->GetLength())); @@ -55,8 +53,6 @@ TEST_F(DexCacheTest, Open) { static_cast<uint32_t>(dex_cache->GetResolvedMethods()->GetLength())); EXPECT_EQ(java_lang_dex_file_->NumFieldIds(), static_cast<uint32_t>(dex_cache->GetResolvedFields()->GetLength())); - EXPECT_EQ(java_lang_dex_file_->NumTypeIds(), - static_cast<uint32_t>(dex_cache->GetInitializedStaticStorage()->GetLength())); } } // namespace mirror diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc index 726a8f1..6f30cc9 100644 --- a/runtime/native/dalvik_system_VMRuntime.cc +++ b/runtime/native/dalvik_system_VMRuntime.cc @@ -234,7 +234,6 @@ static void PreloadDexCachesResolveType(mirror::DexCache* dex_cache, uint32_t ty return; } // LOG(INFO) << "VMRuntime.preloadDexCaches static storage klass=" << class_name; - dex_cache->GetInitializedStaticStorage()->Set(type_idx, klass); } // Based on ClassLinker::ResolveField. @@ -306,12 +305,10 @@ struct DexCacheStats { uint32_t num_types; uint32_t num_fields; uint32_t num_methods; - uint32_t num_static_storage; DexCacheStats() : num_strings(0), num_types(0), num_fields(0), - num_methods(0), - num_static_storage(0) {} + num_methods(0) {} }; static const bool kPreloadDexCachesEnabled = true; @@ -339,7 +336,6 @@ static void PreloadDexCachesStatsTotal(DexCacheStats* total) { total->num_fields += dex_file->NumFieldIds(); total->num_methods += dex_file->NumMethodIds(); total->num_types += dex_file->NumTypeIds(); - total->num_static_storage += dex_file->NumTypeIds(); } } @@ -378,12 +374,6 @@ static void PreloadDexCachesStatsFilled(DexCacheStats* filled) filled->num_methods++; } } - for (size_t i = 0; i < dex_cache->NumInitializedStaticStorage(); i++) { - mirror::StaticStorageBase* klass = dex_cache->GetInitializedStaticStorage()->Get(i); - if (klass != NULL) { - filled->num_static_storage++; - } - } } } @@ -477,10 +467,6 @@ static void VMRuntime_preloadDexCaches(JNIEnv* env, jobject) { total.num_fields, before.num_fields, after.num_fields); LOG(INFO) << StringPrintf("VMRuntime.preloadDexCaches methods total=%d before=%d after=%d", total.num_methods, before.num_methods, after.num_methods); - LOG(INFO) << StringPrintf("VMRuntime.preloadDexCaches storage total=%d before=%d after=%d", - total.num_static_storage, - before.num_static_storage, - after.num_static_storage); LOG(INFO) << StringPrintf("VMRuntime.preloadDexCaches finished"); } } diff --git a/runtime/oat.cc b/runtime/oat.cc index 52e74ab..caf18f1 100644 --- a/runtime/oat.cc +++ b/runtime/oat.cc @@ -22,7 +22,7 @@ namespace art { const uint8_t OatHeader::kOatMagic[] = { 'o', 'a', 't', '\n' }; -const uint8_t OatHeader::kOatVersion[] = { '0', '1', '2', '\0' }; +const uint8_t OatHeader::kOatVersion[] = { '0', '1', '3', '\0' }; OatHeader::OatHeader() { memset(this, 0, sizeof(*this)); |