diff options
author | 2012-04-13 15:59:59 -0700 | |
---|---|---|
committer | 2012-04-14 11:44:21 -0700 | |
commit | a0e180632411f7fe0edf454e571c42209ee7b540 (patch) | |
tree | 97dc85e76c5449ec1a901226c44e0f68fec89870 | |
parent | e5eb1914de86129d78e965fb9f2e1bfb2aa68640 (diff) |
Add a SafeMap equivalent to std::map but without the error-prone operator[].
Change-Id: Iae5ba2091c55a34dbd1005cf3d25fce2a8d5c1f9
34 files changed, 283 insertions, 189 deletions
diff --git a/src/class_linker.cc b/src/class_linker.cc index 567415c431..423bd72a5e 100644 --- a/src/class_linker.cc +++ b/src/class_linker.cc @@ -2674,12 +2674,12 @@ bool ClassLinker::EnsureInitialized(Class* c, bool can_run_clinit, bool can_init } void ClassLinker::ConstructFieldMap(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def, - Class* c, std::map<uint32_t, Field*>& field_map) { + Class* c, SafeMap<uint32_t, Field*>& field_map) { const ClassLoader* cl = c->GetClassLoader(); const byte* class_data = dex_file.GetClassData(dex_class_def); ClassDataItemIterator it(dex_file, class_data); for (size_t i = 0; it.HasNextStaticField(); i++, it.Next()) { - field_map[i] = ResolveField(dex_file, it.GetMemberIndex(), c->GetDexCache(), cl, true); + field_map.Put(i, ResolveField(dex_file, it.GetMemberIndex(), c->GetDexCache(), cl, true)); } } @@ -2701,10 +2701,10 @@ bool ClassLinker::InitializeStaticFields(Class* klass) { if (it.HasNext()) { // We reordered the fields, so we need to be able to map the field indexes to the right fields. - std::map<uint32_t, Field*> field_map; + SafeMap<uint32_t, Field*> field_map; ConstructFieldMap(dex_file, *dex_class_def, klass, field_map); for (size_t i = 0; it.HasNext(); i++, it.Next()) { - it.ReadValueToField(field_map[i]); + it.ReadValueToField(field_map.Get(i)); } return true; } diff --git a/src/class_linker.h b/src/class_linker.h index 86b02ad2d4..a8fa01d10b 100644 --- a/src/class_linker.h +++ b/src/class_linker.h @@ -17,7 +17,6 @@ #ifndef ART_SRC_CLASS_LINKER_H_ #define ART_SRC_CLASS_LINKER_H_ -#include <map> #include <string> #include <utility> #include <vector> @@ -30,6 +29,7 @@ #include "mutex.h" #include "oat_file.h" #include "object.h" +#include "safe_map.h" #include "stack_indirect_reference_table.h" namespace art { @@ -342,7 +342,7 @@ class ClassLinker { void AppendToBootClassPath(const DexFile& dex_file, SirtRef<DexCache>& dex_cache); void ConstructFieldMap(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def, - Class* c, std::map<uint32_t, Field*>& field_map); + Class* c, SafeMap<uint32_t, Field*>& field_map); size_t SizeOfClass(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def); diff --git a/src/compiler.cc b/src/compiler.cc index 7369535e2b..0a88cff434 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -1215,7 +1215,7 @@ void Compiler::InitializeClassesWithoutClinit(const ClassLoader* class_loader, c CompiledClass* compiled_class = GetCompiledClass(ref); if (compiled_class == NULL) { compiled_class = new CompiledClass(status); - compiled_classes_[ref] = compiled_class; + compiled_classes_.Put(ref, compiled_class); } else { DCHECK_EQ(status, compiled_class->GetStatus()); } @@ -1301,6 +1301,14 @@ void Compiler::CompileDexFile(const ClassLoader* class_loader, const DexFile& de ForAll(&context, 0, dex_file.NumClassDefs(), Compiler::CompileClass, thread_count_); } +static std::string MakeInvokeStubKey(bool is_static, const char* shorty) { + std::string key(shorty); + if (is_static) { + key += "$"; // Must not be a shorty type character. + } + return key; +} + void Compiler::CompileMethod(const DexFile::CodeItem* code_item, uint32_t access_flags, uint32_t method_idx, const ClassLoader* class_loader, const DexFile& dex_file) { @@ -1326,33 +1334,30 @@ void Compiler::CompileMethod(const DexFile::CodeItem* code_item, uint32_t access MethodReference ref(&dex_file, method_idx); CHECK(GetCompiledMethod(ref) == NULL) << PrettyMethod(method_idx, dex_file); MutexLock mu(compiled_methods_lock_); - compiled_methods_[ref] = compiled_method; + compiled_methods_.Put(ref, compiled_method); DCHECK(GetCompiledMethod(ref) != NULL) << PrettyMethod(method_idx, dex_file); } uint32_t shorty_len; const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx), &shorty_len); bool is_static = (access_flags & kAccStatic) != 0; - const CompiledInvokeStub* compiled_invoke_stub = FindInvokeStub(is_static, shorty); + std::string key(MakeInvokeStubKey(is_static, shorty)); + const CompiledInvokeStub* compiled_invoke_stub = FindInvokeStub(key); if (compiled_invoke_stub == NULL) { compiled_invoke_stub = (*create_invoke_stub_)(*this, is_static, shorty, shorty_len); CHECK(compiled_invoke_stub != NULL); - InsertInvokeStub(is_static, shorty, compiled_invoke_stub); + InsertInvokeStub(key, compiled_invoke_stub); } CHECK(!Thread::Current()->IsExceptionPending()) << PrettyMethod(method_idx, dex_file); } -static std::string MakeInvokeStubKey(bool is_static, const char* shorty) { - std::string key(shorty); - if (is_static) { - key += "$"; // Must not be a shorty type character. - } - return key; +const CompiledInvokeStub* Compiler::FindInvokeStub(bool is_static, const char* shorty) const { + const std::string key(MakeInvokeStubKey(is_static, shorty)); + return FindInvokeStub(key); } -const CompiledInvokeStub* Compiler::FindInvokeStub(bool is_static, const char* shorty) const { +const CompiledInvokeStub* Compiler::FindInvokeStub(const std::string& key) const { MutexLock mu(compiled_invoke_stubs_lock_); - const std::string key(MakeInvokeStubKey(is_static, shorty)); InvokeStubTable::const_iterator it = compiled_invoke_stubs_.find(key); if (it == compiled_invoke_stubs_.end()) { return NULL; @@ -1362,11 +1367,16 @@ const CompiledInvokeStub* Compiler::FindInvokeStub(bool is_static, const char* s } } -void Compiler::InsertInvokeStub(bool is_static, const char* shorty, +void Compiler::InsertInvokeStub(const std::string& key, const CompiledInvokeStub* compiled_invoke_stub) { MutexLock mu(compiled_invoke_stubs_lock_); - std::string key(MakeInvokeStubKey(is_static, shorty)); - compiled_invoke_stubs_[key] = compiled_invoke_stub; + InvokeStubTable::iterator it = compiled_invoke_stubs_.find(key); + if (it != compiled_invoke_stubs_.end()) { + // Someone else won the race. + delete compiled_invoke_stub; + } else { + compiled_invoke_stubs_.Put(key, compiled_invoke_stub); + } } CompiledClass* Compiler::GetCompiledClass(ClassReference ref) const { diff --git a/src/compiler.h b/src/compiler.h index cb6023b53d..9b8a3ab731 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -17,7 +17,6 @@ #ifndef ART_SRC_COMPILER_H_ #define ART_SRC_COMPILER_H_ -#include <map> #include <set> #include <string> #include <vector> @@ -32,6 +31,7 @@ #include "oat_file.h" #include "object.h" #include "runtime.h" +#include "safe_map.h" namespace art { @@ -92,6 +92,7 @@ class Compiler { CompiledMethod* GetCompiledMethod(MethodReference ref) const; const CompiledInvokeStub* FindInvokeStub(bool is_static, const char* shorty) const; + const CompiledInvokeStub* FindInvokeStub(const std::string& key) const; // Callbacks from OAT/ART compiler to see what runtime checks must be generated @@ -274,25 +275,24 @@ class Compiler { void SetGcMapsDexFile(const ClassLoader* class_loader, const DexFile& dex_file); void SetGcMapsMethod(const DexFile& dex_file, Method* method); - void InsertInvokeStub(bool is_static, const char* shorty, - const CompiledInvokeStub* compiled_invoke_stub); + void InsertInvokeStub(const std::string& key, const CompiledInvokeStub* compiled_invoke_stub); std::vector<const PatchInformation*> code_to_patch_; std::vector<const PatchInformation*> methods_to_patch_; InstructionSet instruction_set_; - typedef std::map<const ClassReference, CompiledClass*> ClassTable; + typedef SafeMap<const ClassReference, CompiledClass*> ClassTable; // All class references that this compiler has compiled mutable Mutex compiled_classes_lock_; ClassTable compiled_classes_; - typedef std::map<const MethodReference, CompiledMethod*> MethodTable; + typedef SafeMap<const MethodReference, CompiledMethod*> MethodTable; // All method references that this compiler has compiled mutable Mutex compiled_methods_lock_; MethodTable compiled_methods_; - typedef std::map<std::string, const CompiledInvokeStub*> InvokeStubTable; + typedef SafeMap<std::string, const CompiledInvokeStub*> InvokeStubTable; // Invocation stubs created to allow invocation of the compiled methods mutable Mutex compiled_invoke_stubs_lock_; InvokeStubTable compiled_invoke_stubs_; diff --git a/src/compiler/CompilerIR.h b/src/compiler/CompilerIR.h index 0fc26dea4c..88593bd09e 100644 --- a/src/compiler/CompilerIR.h +++ b/src/compiler/CompilerIR.h @@ -17,10 +17,12 @@ #ifndef ART_SRC_COMPILER_COMPILER_IR_H_ #define ART_SRC_COMPILER_COMPILER_IR_H_ +#include <vector> + #include "codegen/Optimizer.h" #include "CompilerUtility.h" -#include <vector> #include "oat_compilation_unit.h" +#include "safe_map.h" namespace art { @@ -519,8 +521,8 @@ struct CompilationUnit { const u2* insns; u4 insnsSize; bool disableDataflow; // Skip dataflow analysis if possible - std::map<unsigned int, BasicBlock*> blockMap; // findBlock lookup cache - std::map<unsigned int, LIR*> boundaryMap; // boundary lookup cache + SafeMap<unsigned int, BasicBlock*> blockMap; // findBlock lookup cache + SafeMap<unsigned int, LIR*> boundaryMap; // boundary lookup cache int defCount; // Used to estimate number of SSA names // If non-empty, apply optimizer/debug flags only to matching methods. diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc index 309bcf82d8..dbaf323a2d 100644 --- a/src/compiler/Frontend.cc +++ b/src/compiler/Frontend.cc @@ -136,8 +136,7 @@ BasicBlock *splitBlock(CompilationUnit* cUnit, unsigned int codeOffset, bottomBlock->lastMIRInsn = origBlock->lastMIRInsn; /* Add it to the quick lookup cache */ - cUnit->blockMap.insert(std::make_pair(bottomBlock->startOffset, - bottomBlock)); + cUnit->blockMap.Put(bottomBlock->startOffset, bottomBlock); /* Handle the taken path */ bottomBlock->taken = origBlock->taken; @@ -211,7 +210,7 @@ BasicBlock *findBlock(CompilationUnit* cUnit, unsigned int codeOffset, GrowableList* blockList = &cUnit->blockList; BasicBlock* bb; unsigned int i; - std::map<unsigned int, BasicBlock*>::iterator it; + SafeMap<unsigned int, BasicBlock*>::iterator it; it = cUnit->blockMap.find(codeOffset); if (it != cUnit->blockMap.end()) { @@ -239,7 +238,7 @@ BasicBlock *findBlock(CompilationUnit* cUnit, unsigned int codeOffset, bb = oatNewBB(cUnit, kDalvikByteCode, cUnit->numBlocks++); oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t) bb); bb->startOffset = codeOffset; - cUnit->blockMap.insert(std::make_pair(bb->startOffset, bb)); + cUnit->blockMap.Put(bb->startOffset, bb); return bb; } @@ -853,7 +852,7 @@ CompiledMethod* oatCompileMethod(Compiler& compiler, curBlock->startOffset = 0; oatInsertGrowableList(cUnit.get(), &cUnit->blockList, (intptr_t) curBlock); /* Add first block to the fast lookup cache */ - cUnit->blockMap.insert(std::make_pair(curBlock->startOffset, curBlock)); + cUnit->blockMap.Put(curBlock->startOffset, curBlock); entryBlock->fallThrough = curBlock; oatInsertGrowableList(cUnit.get(), curBlock->predecessors, (intptr_t)entryBlock); diff --git a/src/compiler/codegen/CodegenUtil.cc b/src/compiler/codegen/CodegenUtil.cc index 00e78ecf4b..777cf57345 100644 --- a/src/compiler/codegen/CodegenUtil.cc +++ b/src/compiler/codegen/CodegenUtil.cc @@ -857,7 +857,7 @@ void oatAssembleLIR(CompilationUnit* cUnit) */ LIR* insertCaseLabel(CompilationUnit* cUnit, int vaddr, int keyVal) { - std::map<unsigned int, LIR*>::iterator it; + SafeMap<unsigned int, LIR*>::iterator it; it = cUnit->boundaryMap.find(vaddr); if (it == cUnit->boundaryMap.end()) { LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr; diff --git a/src/compiler/codegen/MethodCodegenDriver.cc b/src/compiler/codegen/MethodCodegenDriver.cc index 0b8a19dddb..dd473590dd 100644 --- a/src/compiler/codegen/MethodCodegenDriver.cc +++ b/src/compiler/codegen/MethodCodegenDriver.cc @@ -883,8 +883,7 @@ bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb) oatGetDalvikDisassembly(cUnit, mir->dalvikInsn, "") : NULL; boundaryLIR = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary, (intptr_t) instStr); - cUnit->boundaryMap.insert(std::make_pair(mir->offset, - (LIR*)boundaryLIR)); + cUnit->boundaryMap.Overwrite(mir->offset, boundaryLIR); /* Remember the first LIR for this block */ if (headLIR == NULL) { headLIR = boundaryLIR; diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc index fa51266ee5..5451d57e02 100644 --- a/src/compiler/codegen/arm/Thumb2/Gen.cc +++ b/src/compiler/codegen/arm/Thumb2/Gen.cc @@ -133,8 +133,7 @@ void genPrintLabel(CompilationUnit *cUnit, MIR* mir) oatGetDalvikDisassembly(cUnit, mir->dalvikInsn, "") : NULL; boundaryLIR = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary, (intptr_t) instStr); - cUnit->boundaryMap.insert(std::make_pair(mir->offset, - (LIR*)boundaryLIR)); + cUnit->boundaryMap.Put(mir->offset, boundaryLIR); /* Don't generate the SSA annotation unless verbose mode is on */ if (cUnit->printMe && mir->ssaRep) { char* ssaString = oatGetSSAString(cUnit, mir->ssaRep); diff --git a/src/compiler_llvm/inferred_reg_category_map.h b/src/compiler_llvm/inferred_reg_category_map.h index f05627430e..14bc05286a 100644 --- a/src/compiler_llvm/inferred_reg_category_map.h +++ b/src/compiler_llvm/inferred_reg_category_map.h @@ -21,7 +21,8 @@ #include <stdint.h> #include <vector> -#include <map> + +#include "safe_map.h" namespace art { namespace compiler_llvm { @@ -31,8 +32,7 @@ class InferredRegCategoryMap { private: class RegCategoryLine { private: - // TODO: Use hashmap (unordered_map). - typedef std::map<uint16_t, uint8_t> Table; + typedef SafeMap<uint16_t, uint8_t> Table; Table reg_category_line_; public: diff --git a/src/debugger.cc b/src/debugger.cc index 553bfc73bb..fe9bc491c1 100644 --- a/src/debugger.cc +++ b/src/debugger.cc @@ -25,9 +25,10 @@ #include "dex_verifier.h" // For Instruction. #include "oat/runtime/context.h" #include "object_utils.h" +#include "safe_map.h" +#include "scoped_thread_list_lock.h" #include "ScopedLocalRef.h" #include "ScopedPrimitiveArray.h" -#include "scoped_thread_list_lock.h" #include "space.h" #include "stack_indirect_reference_table.h" #include "thread_list.h" @@ -58,7 +59,7 @@ class ObjectRegistry { } JDWP::ObjectId id = static_cast<JDWP::ObjectId>(reinterpret_cast<uintptr_t>(o)); MutexLock mu(lock_); - map_[id] = o; + map_.Overwrite(id, o); return id; } @@ -79,14 +80,14 @@ class ObjectRegistry { } MutexLock mu(lock_); - typedef std::map<JDWP::ObjectId, Object*>::iterator It; // C++0x auto + typedef SafeMap<JDWP::ObjectId, Object*>::iterator It; // C++0x auto It it = map_.find(id); return (it != map_.end()) ? reinterpret_cast<T>(it->second) : reinterpret_cast<T>(kInvalidId); } void VisitRoots(Heap::RootVisitor* visitor, void* arg) { MutexLock mu(lock_); - typedef std::map<JDWP::ObjectId, Object*>::iterator It; // C++0x auto + typedef SafeMap<JDWP::ObjectId, Object*>::iterator It; // C++0x auto for (It it = map_.begin(); it != map_.end(); ++it) { visitor(it->second, arg); } @@ -94,7 +95,7 @@ class ObjectRegistry { private: Mutex lock_; - std::map<JDWP::ObjectId, Object*> map_; + SafeMap<JDWP::ObjectId, Object*> map_; }; struct AllocRecordStackTraceElement { diff --git a/src/dex_file.cc b/src/dex_file.cc index 6168f9e2ec..a054849bcf 100644 --- a/src/dex_file.cc +++ b/src/dex_file.cc @@ -25,9 +25,6 @@ #include <sys/mman.h> #include <sys/stat.h> -#include <map> - -#include "UniquePtr.h" #include "class_linker.h" #include "dex_file_verifier.h" #include "globals.h" @@ -35,8 +32,10 @@ #include "logging.h" #include "object.h" #include "os.h" +#include "safe_map.h" #include "stringprintf.h" #include "thread.h" +#include "UniquePtr.h" #include "utf.h" #include "utils.h" #include "zip_archive.h" @@ -331,7 +330,7 @@ void DexFile::InitIndex() { for (size_t i = 0; i < NumClassDefs(); ++i) { const ClassDef& class_def = GetClassDef(i); const char* descriptor = GetClassDescriptor(class_def); - index_[descriptor] = i; + index_.Put(descriptor, i); } } diff --git a/src/dex_file.h b/src/dex_file.h index 02d0b27db6..2f315a9b20 100644 --- a/src/dex_file.h +++ b/src/dex_file.h @@ -17,17 +17,17 @@ #ifndef ART_SRC_DEX_FILE_H_ #define ART_SRC_DEX_FILE_H_ -#include <map> #include <string> #include <vector> -#include "UniquePtr.h" #include "globals.h" #include "jni.h" #include "logging.h" #include "mem_map.h" #include "mutex.h" +#include "safe_map.h" #include "stringpiece.h" +#include "UniquePtr.h" #include "utils.h" namespace art { @@ -847,7 +847,7 @@ class DexFile { void* context, const byte* stream, LocalInfo* local_in_reg) const; // The index of descriptors to class definition indexes (as opposed to type id indexes) - typedef std::map<const StringPiece, uint32_t> Index; + typedef SafeMap<const StringPiece, uint32_t> Index; Index index_; // The base address of the memory mapping. diff --git a/src/dex_file_verifier.cc b/src/dex_file_verifier.cc index af9d4bb814..b8df69689b 100644 --- a/src/dex_file_verifier.cc +++ b/src/dex_file_verifier.cc @@ -16,12 +16,11 @@ #include "dex_file_verifier.h" -#include <map> - -#include "UniquePtr.h" #include "leb128.h" #include "object.h" +#include "safe_map.h" #include "stringprintf.h" +#include "UniquePtr.h" #include "zip_archive.h" namespace art { @@ -1117,7 +1116,7 @@ bool DexFileVerifier::CheckIntraSectionIterate(uint32_t offset, uint32_t count, } if (IsDataSectionType(type)) { - offset_to_type_map_.insert(std::make_pair(aligned_offset, type)); + offset_to_type_map_.Put(aligned_offset, type); } aligned_offset = reinterpret_cast<uint32_t>(ptr_) - reinterpret_cast<uint32_t>(begin_); @@ -1289,7 +1288,7 @@ bool DexFileVerifier::CheckIntraSection() { } bool DexFileVerifier::CheckOffsetToTypeMap(uint32_t offset, uint16_t type) { - typedef std::map<uint32_t, uint16_t>::iterator It; // TODO: C++0x auto + typedef SafeMap<uint32_t, uint16_t>::iterator It; // TODO: C++0x auto It it = offset_to_type_map_.find(offset); if (it == offset_to_type_map_.end()) { LOG(ERROR) << StringPrintf("No data map entry found @ %x; expected %x", offset, type); diff --git a/src/dex_file_verifier.h b/src/dex_file_verifier.h index 58b598437d..5538d4aa75 100644 --- a/src/dex_file_verifier.h +++ b/src/dex_file_verifier.h @@ -17,9 +17,8 @@ #ifndef ART_SRC_DEX_FILE_VERIFIER_H_ #define ART_SRC_DEX_FILE_VERIFIER_H_ -#include <map> - #include "dex_file.h" +#include "safe_map.h" namespace art { @@ -88,7 +87,7 @@ class DexFileVerifier { size_t size_; const DexFile::Header* header_; - std::map<uint32_t, uint16_t> offset_to_type_map_; + SafeMap<uint32_t, uint16_t> offset_to_type_map_; const byte* ptr_; const void* previous_item_; }; diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc index 91d6ccd4ac..4f523fa449 100644 --- a/src/dex_verifier.cc +++ b/src/dex_verifier.cc @@ -901,7 +901,7 @@ void PcToRegisterLineTable::Init(RegisterTrackingMode mode, InsnFlags* flags, break; } if (interesting) { - pc_to_register_line_[i] = new RegisterLine(registers_size, verifier); + pc_to_register_line_.Put(i, new RegisterLine(registers_size, verifier)); } } } @@ -4035,12 +4035,12 @@ void DexVerifier::DeleteGcMaps() { void DexVerifier::SetGcMap(Compiler::MethodReference ref, const std::vector<uint8_t>& gc_map) { MutexLock mu(*gc_maps_lock_); - const std::vector<uint8_t>* existing_gc_map = GetGcMap(ref); - if (existing_gc_map != NULL) { - CHECK(*existing_gc_map == gc_map); - delete existing_gc_map; + GcMapTable::iterator it = gc_maps_->find(ref); + if (it != gc_maps_->end()) { + delete it->second; + gc_maps_->erase(it); } - (*gc_maps_)[ref] = &gc_map; + gc_maps_->Put(ref, &gc_map); CHECK(GetGcMap(ref) != NULL); } diff --git a/src/dex_verifier.h b/src/dex_verifier.h index 043e4f9912..75de207c86 100644 --- a/src/dex_verifier.h +++ b/src/dex_verifier.h @@ -19,7 +19,6 @@ #include <deque> #include <limits> -#include <map> #include <set> #include <vector> @@ -29,6 +28,7 @@ #include "dex_instruction.h" #include "macros.h" #include "object.h" +#include "safe_map.h" #include "stl_util.h" #include "UniquePtr.h" @@ -774,16 +774,16 @@ class RegisterLine { private: void CopyRegToLockDepth(size_t dst, size_t src) { - if (reg_to_lock_depths_.count(src) > 0) { - uint32_t depths = reg_to_lock_depths_[src]; - reg_to_lock_depths_[dst] = depths; + SafeMap<uint32_t, uint32_t>::iterator it = reg_to_lock_depths_.find(src); + if (it != reg_to_lock_depths_.end()) { + reg_to_lock_depths_.Put(dst, it->second); } } bool IsSetLockDepth(size_t reg, size_t depth) { - if (reg_to_lock_depths_.count(reg) > 0) { - uint32_t depths = reg_to_lock_depths_[reg]; - return (depths & (1 << depth)) != 0; + SafeMap<uint32_t, uint32_t>::iterator it = reg_to_lock_depths_.find(reg); + if (it != reg_to_lock_depths_.end()) { + return (it->second & (1 << depth)) != 0; } else { return false; } @@ -792,25 +792,24 @@ class RegisterLine { void SetRegToLockDepth(size_t reg, size_t depth) { CHECK_LT(depth, 32u); DCHECK(!IsSetLockDepth(reg, depth)); - uint32_t depths; - if (reg_to_lock_depths_.count(reg) > 0) { - depths = reg_to_lock_depths_[reg]; - depths = depths | (1 << depth); + SafeMap<uint32_t, uint32_t>::iterator it = reg_to_lock_depths_.find(reg); + if (it == reg_to_lock_depths_.end()) { + reg_to_lock_depths_.Put(reg, 1 << depth); } else { - depths = 1 << depth; + it->second |= (1 << depth); } - reg_to_lock_depths_[reg] = depths; } void ClearRegToLockDepth(size_t reg, size_t depth) { CHECK_LT(depth, 32u); DCHECK(IsSetLockDepth(reg, depth)); - uint32_t depths = reg_to_lock_depths_[reg]; - depths = depths ^ (1 << depth); + SafeMap<uint32_t, uint32_t>::iterator it = reg_to_lock_depths_.find(reg); + DCHECK(it != reg_to_lock_depths_.end()); + uint32_t depths = it->second ^ (1 << depth); if (depths != 0) { - reg_to_lock_depths_[reg] = depths; + it->second = depths; } else { - reg_to_lock_depths_.erase(reg); + reg_to_lock_depths_.erase(it); } } @@ -834,7 +833,7 @@ class RegisterLine { // A map from register to a bit vector of indices into the monitors_ stack. As we pop the monitor // stack we verify that monitor-enter/exit are correctly nested. That is, if there was a // monitor-enter on v5 and then on v6, we expect the monitor-exit to be on v6 then on v5 - std::map<uint32_t, uint32_t> reg_to_lock_depths_; + SafeMap<uint32_t, uint32_t> reg_to_lock_depths_; }; std::ostream& operator<<(std::ostream& os, const RegisterLine& rhs); @@ -870,9 +869,8 @@ class PcToRegisterLineTable { } private: - // TODO: Use hashmap (unordered_map). - typedef std::map<int32_t, RegisterLine*> Table; // Map from a dex pc to the register status associated with it + typedef SafeMap<int32_t, RegisterLine*> Table; Table pc_to_register_line_; // Number of registers we track for each instruction. This is equal to the method's declared @@ -1306,15 +1304,15 @@ class DexVerifier { } // All the GC maps that the verifier has created - typedef std::map<const Compiler::MethodReference, const std::vector<uint8_t>*> GcMapTable; + typedef SafeMap<const Compiler::MethodReference, const std::vector<uint8_t>*> GcMapTable; static Mutex* gc_maps_lock_; static GcMapTable* gc_maps_; static void SetGcMap(Compiler::MethodReference ref, const std::vector<uint8_t>& gc_map); #if defined(ART_USE_LLVM_COMPILER) // All the inferred register category maps that the verifier has created - typedef std::map<const Compiler::MethodReference, - const compiler_llvm::InferredRegCategoryMap*> InferredRegCategoryMapTable; + typedef SafeMap<const Compiler::MethodReference, + const compiler_llvm::InferredRegCategoryMap*> InferredRegCategoryMapTable; static Mutex* inferred_reg_category_maps_lock_; static InferredRegCategoryMapTable* inferred_reg_category_maps_; static void SetInferredRegCategoryMap(Compiler::MethodReference ref, diff --git a/src/hprof/hprof.cc b/src/hprof/hprof.cc index b118b5cfd5..d6771d01d6 100644 --- a/src/hprof/hprof.cc +++ b/src/hprof/hprof.cc @@ -649,10 +649,13 @@ HprofStringId Hprof::LookupStringId(const char* string) { } HprofStringId Hprof::LookupStringId(std::string string) { - if (strings_.find(string) == strings_.end()) { - strings_[string] = next_string_id_++; + StringMapIterator it = strings_.find(string); + if (it != strings_.end()) { + return it->second; } - return strings_[string]; + HprofStringId id = next_string_id_++; + strings_.Put(string, id); + return id; } int Hprof::DumpStrings() { diff --git a/src/hprof/hprof.h b/src/hprof/hprof.h index c4a0dd3285..bcdbef8111 100644 --- a/src/hprof/hprof.h +++ b/src/hprof/hprof.h @@ -18,12 +18,12 @@ #include <stdio.h> -#include <map> #include <set> #include "file.h" #include "globals.h" #include "object.h" +#include "safe_map.h" #include "thread_list.h" namespace art { @@ -80,8 +80,8 @@ typedef HprofId HprofObjectId; typedef HprofId HprofClassObjectId; typedef std::set<Class*> ClassSet; typedef std::set<Class*>::iterator ClassSetIterator; -typedef std::map<std::string, size_t> StringMap; -typedef std::map<std::string, size_t>::iterator StringMapIterator; +typedef SafeMap<std::string, size_t> StringMap; +typedef SafeMap<std::string, size_t>::iterator StringMapIterator; enum HprofBasicType { hprof_basic_object = 2, diff --git a/src/image_writer.h b/src/image_writer.h index f62bea1286..5f78863269 100644 --- a/src/image_writer.h +++ b/src/image_writer.h @@ -20,7 +20,6 @@ #include <stdint.h> #include <cstddef> -#include <map> #include <set> #include <string> @@ -30,6 +29,7 @@ #include "oat_file.h" #include "object.h" #include "os.h" +#include "safe_map.h" #include "space.h" #include "UniquePtr.h" @@ -65,7 +65,7 @@ class ImageWriter { DCHECK(object != NULL); DCHECK_NE(offset, 0U); DCHECK(!IsImageOffsetAssigned(object)); - offsets_[object] = offset; + offsets_.Put(object, offset); } size_t IsImageOffsetAssigned(const Object* object) const { @@ -142,7 +142,7 @@ class ImageWriter { void PatchOatCodeAndMethods(const Compiler& compiler); void SetPatchLocation(const Compiler::PatchInformation* patch, uint32_t value); - std::map<const Object*, size_t> offsets_; + SafeMap<const Object*, size_t> offsets_; // oat file with code for this image OatFile* oat_file_; diff --git a/src/intern_table.h b/src/intern_table.h index bb8e0315da..58d87d0d52 100644 --- a/src/intern_table.h +++ b/src/intern_table.h @@ -18,11 +18,11 @@ #define ART_SRC_INTERN_TABLE_H_ #include <iosfwd> -#include <map> #include "heap.h" #include "mutex.h" #include "object.h" +#include "safe_map.h" namespace art { diff --git a/src/jni_internal.cc b/src/jni_internal.cc index e192ce825f..1e2760453f 100644 --- a/src/jni_internal.cc +++ b/src/jni_internal.cc @@ -20,12 +20,9 @@ #include <sys/mman.h> #include <cstdarg> -#include <map> #include <utility> #include <vector> -#include "ScopedLocalRef.h" -#include "UniquePtr.h" #include "class_linker.h" #include "class_loader.h" #include "jni.h" @@ -33,10 +30,13 @@ #include "object.h" #include "object_utils.h" #include "runtime.h" +#include "safe_map.h" #include "scoped_jni_thread_state.h" +#include "ScopedLocalRef.h" #include "stl_util.h" #include "stringpiece.h" #include "thread.h" +#include "UniquePtr.h" namespace art { @@ -665,7 +665,7 @@ class Libraries { } void Put(const std::string& path, SharedLibrary* library) { - libraries_[path] = library; + libraries_.Put(path, library); } // See section 11.3 "Linking Native Methods" of the JNI spec. @@ -698,9 +698,9 @@ class Libraries { } private: - typedef std::map<std::string, SharedLibrary*>::iterator It; // TODO: C++0x auto + typedef SafeMap<std::string, SharedLibrary*>::iterator It; // TODO: C++0x auto - std::map<std::string, SharedLibrary*> libraries_; + SafeMap<std::string, SharedLibrary*> libraries_; }; JValue InvokeWithJValues(JNIEnv* public_env, jobject obj, jmethodID mid, jvalue* args) { diff --git a/src/oat_file.cc b/src/oat_file.cc index 261fd60a67..7196222ecb 100644 --- a/src/oat_file.cc +++ b/src/oat_file.cc @@ -177,11 +177,11 @@ bool OatFile::Map(File& file, oat += (sizeof(*methods_offsets_pointer) * header->class_defs_size_); CHECK_LE(oat, map->End()) << GetLocation(); - oat_dex_files_[dex_file_location] = new OatDexFile(this, - dex_file_location, - dex_file_checksum, - dex_file_pointer, - methods_offsets_pointer); + oat_dex_files_.Put(dex_file_location, new OatDexFile(this, + dex_file_location, + dex_file_checksum, + dex_file_pointer, + methods_offsets_pointer)); } #if !defined(ART_USE_LLVM_COMPILER) diff --git a/src/oat_file.h b/src/oat_file.h index 0bd9d339ea..0b1ebac884 100644 --- a/src/oat_file.h +++ b/src/oat_file.h @@ -315,7 +315,7 @@ class OatFile { // backing memory map for oat file UniquePtr<MemMap> mem_map_; - typedef std::map<std::string, const OatDexFile*> Table; + typedef SafeMap<std::string, const OatDexFile*> Table; Table oat_dex_files_; #if defined(ART_USE_LLVM_COMPILER) diff --git a/src/oat_writer.cc b/src/oat_writer.cc index f08aa8d773..2ccf2075d8 100644 --- a/src/oat_writer.cc +++ b/src/oat_writer.cc @@ -16,16 +16,17 @@ #include "oat_writer.h" +#include <zlib.h> + #include "class_linker.h" #include "class_loader.h" #include "elf_image.h" #include "file.h" #include "os.h" +#include "safe_map.h" #include "space.h" #include "stl_util.h" -#include <zlib.h> - namespace art { bool OatWriter::Create(File* file, @@ -286,11 +287,11 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, code_offset = offset + sizeof(code_size) + thumb_offset; // Deduplicate code arrays - std::map<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code); + SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code); if (code_iter != code_offsets_.end()) { code_offset = code_iter->second; } else { - code_offsets_.insert(std::pair<const std::vector<uint8_t>*, uint32_t>(&code, code_offset)); + code_offsets_.Put(&code, code_offset); offset += sizeof(code_size); // code size is prepended before code offset += code_size; oat_header_->UpdateChecksum(&code[0], code_size); @@ -304,11 +305,11 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, mapping_table_offset = (mapping_table_size == 0) ? 0 : offset; // Deduplicate mapping tables - std::map<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter = mapping_table_offsets_.find(&mapping_table); + SafeMap<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter = mapping_table_offsets_.find(&mapping_table); if (mapping_iter != mapping_table_offsets_.end()) { mapping_table_offset = mapping_iter->second; } else { - mapping_table_offsets_.insert(std::pair<const std::vector<uint32_t>*, uint32_t>(&mapping_table, mapping_table_offset)); + mapping_table_offsets_.Put(&mapping_table, mapping_table_offset); offset += mapping_table_size; oat_header_->UpdateChecksum(&mapping_table[0], mapping_table_size); } @@ -318,11 +319,11 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, vmap_table_offset = (vmap_table_size == 0) ? 0 : offset; // Deduplicate vmap tables - std::map<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter = vmap_table_offsets_.find(&vmap_table); + SafeMap<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter = vmap_table_offsets_.find(&vmap_table); if (vmap_iter != vmap_table_offsets_.end()) { vmap_table_offset = vmap_iter->second; } else { - vmap_table_offsets_.insert(std::pair<const std::vector<uint16_t>*, uint32_t>(&vmap_table, vmap_table_offset)); + vmap_table_offsets_.Put(&vmap_table, vmap_table_offset); offset += vmap_table_size; oat_header_->UpdateChecksum(&vmap_table[0], vmap_table_size); } @@ -342,11 +343,11 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, #endif // Deduplicate GC maps - std::map<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter = gc_map_offsets_.find(&gc_map); + SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter = gc_map_offsets_.find(&gc_map); if (gc_map_iter != gc_map_offsets_.end()) { gc_map_offset = gc_map_iter->second; } else { - gc_map_offsets_.insert(std::pair<const std::vector<uint8_t>*, uint32_t>(&gc_map, gc_map_offset)); + gc_map_offsets_.Put(&gc_map, gc_map_offset); offset += gc_map_size; oat_header_->UpdateChecksum(&gc_map[0], gc_map_size); } @@ -368,11 +369,11 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, invoke_stub_offset = offset + sizeof(invoke_stub_size); // Deduplicate invoke stubs - std::map<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = code_offsets_.find(&invoke_stub); + SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = code_offsets_.find(&invoke_stub); if (stub_iter != code_offsets_.end()) { invoke_stub_offset = stub_iter->second; } else { - code_offsets_.insert(std::pair<const std::vector<uint8_t>*, uint32_t>(&invoke_stub, invoke_stub_offset)); + code_offsets_.Put(&invoke_stub, invoke_stub_offset); offset += sizeof(invoke_stub_size); // invoke stub size is prepended before code offset += invoke_stub_size; oat_header_->UpdateChecksum(&invoke_stub[0], invoke_stub_size); @@ -627,7 +628,7 @@ size_t OatWriter::WriteCodeMethod(File* file, size_t code_offset, size_t oat_cla // Deduplicate code arrays size_t offset = code_offset + sizeof(code_size) + compiled_method->CodeDelta(); - std::map<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code); + SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code); if (code_iter != code_offsets_.end() && offset != method_offsets.code_offset_) { DCHECK(code_iter->second == method_offsets.code_offset_) << PrettyMethod(method_idx, dex_file); } else { @@ -653,7 +654,7 @@ size_t OatWriter::WriteCodeMethod(File* file, size_t code_offset, size_t oat_cla size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]); // Deduplicate mapping tables - std::map<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter = + SafeMap<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter = mapping_table_offsets_.find(&mapping_table); if (mapping_iter != mapping_table_offsets_.end() && code_offset != method_offsets.mapping_table_offset_) { @@ -676,7 +677,7 @@ size_t OatWriter::WriteCodeMethod(File* file, size_t code_offset, size_t oat_cla size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]); // Deduplicate vmap tables - std::map<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter = + SafeMap<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter = vmap_table_offsets_.find(&vmap_table); if (vmap_iter != vmap_table_offsets_.end() && code_offset != method_offsets.vmap_table_offset_) { @@ -699,7 +700,7 @@ size_t OatWriter::WriteCodeMethod(File* file, size_t code_offset, size_t oat_cla size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]); // Deduplicate GC maps - std::map<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter = + SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter = gc_map_offsets_.find(&gc_map); if (gc_map_iter != gc_map_offsets_.end() && code_offset != method_offsets.gc_map_offset_) { @@ -743,7 +744,7 @@ size_t OatWriter::WriteCodeMethod(File* file, size_t code_offset, size_t oat_cla // Deduplicate invoke stubs size_t offset = code_offset + sizeof(invoke_stub_size); - std::map<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = + SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = code_offsets_.find(&invoke_stub); if (stub_iter != code_offsets_.end() && offset != method_offsets.invoke_stub_offset_) { DCHECK(stub_iter->second == method_offsets.invoke_stub_offset_) << PrettyMethod(method_idx, dex_file); diff --git a/src/oat_writer.h b/src/oat_writer.h index e0d257fa80..956475c697 100644 --- a/src/oat_writer.h +++ b/src/oat_writer.h @@ -21,13 +21,14 @@ #include <cstddef> -#include "UniquePtr.h" #include "compiler.h" #include "dex_cache.h" #include "mem_map.h" #include "oat.h" #include "object.h" #include "os.h" +#include "safe_map.h" +#include "UniquePtr.h" namespace art { @@ -203,10 +204,10 @@ class OatWriter { }; // code mappings for deduplication - std::map<const std::vector<uint8_t>*, uint32_t, MapCompare<std::vector<uint8_t> > > code_offsets_; - std::map<const std::vector<uint16_t>*, uint32_t, MapCompare<std::vector<uint16_t> > > vmap_table_offsets_; - std::map<const std::vector<uint32_t>*, uint32_t, MapCompare<std::vector<uint32_t> > > mapping_table_offsets_; - std::map<const std::vector<uint8_t>*, uint32_t, MapCompare<std::vector<uint8_t> > > gc_map_offsets_; + SafeMap<const std::vector<uint8_t>*, uint32_t, MapCompare<std::vector<uint8_t> > > code_offsets_; + SafeMap<const std::vector<uint16_t>*, uint32_t, MapCompare<std::vector<uint16_t> > > vmap_table_offsets_; + SafeMap<const std::vector<uint32_t>*, uint32_t, MapCompare<std::vector<uint32_t> > > mapping_table_offsets_; + SafeMap<const std::vector<uint8_t>*, uint32_t, MapCompare<std::vector<uint8_t> > > gc_map_offsets_; DISALLOW_COPY_AND_ASSIGN(OatWriter); }; diff --git a/src/oatdump.cc b/src/oatdump.cc index 6680b57fed..93eb9a17c5 100644 --- a/src/oatdump.cc +++ b/src/oatdump.cc @@ -19,7 +19,6 @@ #include <fstream> #include <iostream> -#include <map> #include <string> #include <vector> @@ -33,6 +32,7 @@ #include "object_utils.h" #include "os.h" #include "runtime.h" +#include "safe_map.h" #include "space.h" #include "stringpiece.h" @@ -901,35 +901,35 @@ class ImageDumper { size_t dex_instruction_bytes = code_item->insns_size_in_code_units_ * 2; state->stats_.dex_instruction_bytes += dex_instruction_bytes; - bool first_occurance; - size_t gc_map_bytes = state->ComputeOatSize(method->GetGcMapRaw(), &first_occurance); - if (first_occurance) { + bool first_occurrence; + size_t gc_map_bytes = state->ComputeOatSize(method->GetGcMapRaw(), &first_occurrence); + if (first_occurrence) { state->stats_.gc_map_bytes += gc_map_bytes; } size_t pc_mapping_table_bytes = - state->ComputeOatSize(method->GetMappingTableRaw(), &first_occurance); - if (first_occurance) { + state->ComputeOatSize(method->GetMappingTableRaw(), &first_occurrence); + if (first_occurrence) { state->stats_.pc_mapping_table_bytes += pc_mapping_table_bytes; } size_t vmap_table_bytes = - state->ComputeOatSize(method->GetVmapTableRaw(), &first_occurance); - if (first_occurance) { + state->ComputeOatSize(method->GetVmapTableRaw(), &first_occurrence); + if (first_occurrence) { state->stats_.vmap_table_bytes += vmap_table_bytes; } // TODO: compute invoke stub using length from oat file. size_t invoke_stub_size = state->ComputeOatSize( - reinterpret_cast<const void*>(method->GetInvokeStub()), &first_occurance); - if (first_occurance) { + reinterpret_cast<const void*>(method->GetInvokeStub()), &first_occurrence); + if (first_occurrence) { state->stats_.native_to_managed_code_bytes += invoke_stub_size; } const void* oat_code_begin = state->GetOatCodeBegin(method); const void* oat_code_end = state->GetOatCodeEnd(method); uint32_t oat_code_size = state->GetOatCodeSize(method); - state->ComputeOatSize(oat_code_begin, &first_occurance); - if (first_occurance) { + state->ComputeOatSize(oat_code_begin, &first_occurrence); + if (first_occurrence) { state->stats_.managed_code_bytes += oat_code_size; if (method->IsConstructor()) { if (method->IsStatic()) { @@ -955,9 +955,7 @@ class ImageDumper { state->stats_.ComputeOutliers(total_size, expansion, method); } } - std::string descriptor(ClassHelper(obj_class).GetDescriptor()); - state->stats_.descriptor_to_bytes[descriptor] += object_bytes; - state->stats_.descriptor_to_count[descriptor] += 1; + state->stats_.Update(ClassHelper(obj_class).GetDescriptor(), object_bytes); state->os_ << summary << std::flush; } @@ -965,12 +963,12 @@ class ImageDumper { std::set<const void*> already_seen_; // Compute the size of the given data within the oat file and whether this is the first time // this data has been requested - size_t ComputeOatSize(const void* oat_data, bool* first_occurance) { + size_t ComputeOatSize(const void* oat_data, bool* first_occurrence) { if (already_seen_.count(oat_data) == 0) { - *first_occurance = true; + *first_occurrence = true; already_seen_.insert(oat_data); } else { - *first_occurance = false; + *first_occurrence = false; } return oat_dumper_->ComputeSize(oat_data); } @@ -1020,11 +1018,23 @@ class ImageDumper { vmap_table_bytes(0), dex_instruction_bytes(0) {} - typedef std::map<std::string, size_t> TableBytes; - TableBytes descriptor_to_bytes; - - typedef std::map<std::string, size_t> TableCount; - TableCount descriptor_to_count; + struct SizeAndCount { + SizeAndCount(size_t bytes, size_t count) : bytes(bytes), count(count) {} + size_t bytes; + size_t count; + }; + typedef SafeMap<std::string, SizeAndCount> SizeAndCountTable; + SizeAndCountTable sizes_and_counts; + + void Update(const std::string& descriptor, size_t object_bytes) { + SizeAndCountTable::iterator it = sizes_and_counts.find(descriptor); + if (it != sizes_and_counts.end()) { + it->second.bytes += object_bytes; + it->second.count += 1; + } else { + sizes_and_counts.Put(descriptor, SizeAndCount(object_bytes, 1)); + } + } double PercentOfOatBytes(size_t size) { return (static_cast<double>(size) / static_cast<double>(oat_file_bytes)) * 100; @@ -1158,21 +1168,18 @@ class ImageDumper { CHECK_EQ(file_bytes, header_bytes + object_bytes + alignment_bytes); - os << "\tobject_bytes = sum of descriptor_to_bytes values below:\n"; + os << "\tobject_bytes breakdown:\n"; size_t object_bytes_total = 0; - typedef TableBytes::const_iterator It; // TODO: C++0x auto - for (It it = descriptor_to_bytes.begin(), end = descriptor_to_bytes.end(); it != end; ++it) { + typedef SizeAndCountTable::const_iterator It; // TODO: C++0x auto + for (It it = sizes_and_counts.begin(), end = sizes_and_counts.end(); it != end; ++it) { const std::string& descriptor(it->first); - size_t bytes = it->second; - size_t count = descriptor_to_count[descriptor]; - double average = static_cast<double>(bytes) / static_cast<double>(count); - double percent = PercentOfObjectBytes(bytes); + double average = static_cast<double>(it->second.bytes) / static_cast<double>(it->second.count); + double percent = PercentOfObjectBytes(it->second.bytes); os << StringPrintf("\t%32s %8zd bytes %6zd instances " - "(%3.0f bytes/instance) %2.0f%% of object_bytes\n", - descriptor.c_str(), bytes, count, + "(%4.0f bytes/instance) %2.0f%% of object_bytes\n", + descriptor.c_str(), it->second.bytes, it->second.count, average, percent); - - object_bytes_total += bytes; + object_bytes_total += it->second.bytes; } os << std::endl << std::flush; CHECK_EQ(object_bytes, object_bytes_total); diff --git a/src/runtime.cc b/src/runtime.cc index d16ee78e79..06c4020dcf 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -1049,7 +1049,7 @@ const std::vector<const DexFile*>& Runtime::GetCompileTimeClassPath(const ClassL void Runtime::SetCompileTimeClassPath(const ClassLoader* class_loader, std::vector<const DexFile*>& class_path) { CHECK(!IsStarted()); use_compile_time_class_path_ = true; - compile_time_class_paths_[class_loader] = class_path; + compile_time_class_paths_.Put(class_loader, class_path); } } // namespace art diff --git a/src/runtime.h b/src/runtime.h index b8fe35ad38..0dea7630d5 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -17,21 +17,20 @@ #ifndef ART_SRC_RUNTIME_H_ #define ART_SRC_RUNTIME_H_ +#include <jni.h> #include <stdio.h> #include <iosfwd> -#include <map> #include <string> #include <utility> #include <vector> -#include <jni.h> - +#include "globals.h" #include "heap.h" #include "instruction_set.h" -#include "globals.h" #include "macros.h" #include "runtime_stats.h" +#include "safe_map.h" #include "stringpiece.h" namespace art { @@ -329,7 +328,7 @@ class Runtime { size_t method_trace_file_size_; Trace* tracer_; - typedef std::map<const ClassLoader*, std::vector<const DexFile*> > CompileTimeClassPaths; + typedef SafeMap<const ClassLoader*, std::vector<const DexFile*> > CompileTimeClassPaths; CompileTimeClassPaths compile_time_class_paths_; bool use_compile_time_class_path_; diff --git a/src/safe_map.h b/src/safe_map.h new file mode 100644 index 0000000000..1544181035 --- /dev/null +++ b/src/safe_map.h @@ -0,0 +1,82 @@ +#ifndef ART_SRC_SAFE_MAP_H_ +#define ART_SRC_SAFE_MAP_H_ + +#include <map> + +#include "logging.h" + +namespace art { + +// Equivalent to std::map, but without operator[] and its bug-prone semantics (in particular, +// the implicit insertion of a default-constructed value on failed lookups). +template <typename K, typename V, typename Comparator = std::less<K> > +class SafeMap { + private: + typedef SafeMap<K, V, Comparator> Self; + + public: + typedef typename ::std::map<K, V, Comparator>::iterator iterator; + typedef typename ::std::map<K, V, Comparator>::const_iterator const_iterator; + typedef typename ::std::map<K, V, Comparator>::size_type size_type; + typedef typename ::std::map<K, V, Comparator>::value_type value_type; + + Self& operator=(const Self& rhs) { map_ = rhs.map_; return *this; } + + iterator begin() { return map_.begin(); } + const_iterator begin() const { return map_.begin(); } + iterator end() { return map_.end(); } + const_iterator end() const { return map_.end(); } + + bool empty() const { return map_.empty(); } + size_type size() const { return map_.size(); } + + void clear() { return map_.clear(); } + void erase(iterator it) { map_.erase(it); } + size_type erase(const K& k) { return map_.erase(k); } + + iterator find(const K& k) { return map_.find(k); } + const_iterator find(const K& k) const { return map_.find(k); } + + size_type count(const K& k) const { return map_.count(k); } + + // Note that unlike std::map's operator[], this doesn't return a reference to the value. + V Get(const K& k) { + iterator it = map_.find(k); + DCHECK(it != map_.end()); + return it->second; + } + + // Used to insert a new mapping. + void Put(const K& k, const V& v) { + std::pair<iterator, bool> result = map_.insert(std::make_pair(k, v)); + DCHECK(result.second); // Check we didn't accidentally overwrite an existing value. + } + + // Used to insert a new mapping or overwrite an existing mapping. Note that if the value type + // of this container is a pointer, any overwritten pointer will be lost and if this container + // was the owner, you have a leak. + void Overwrite(const K& k, const V& v) { + map_.insert(std::make_pair(k, v)); + } + + bool Equals(const Self& rhs) const { + return map_ == rhs.map_; + } + + private: + ::std::map<K, V, Comparator> map_; +}; + +template <typename K, typename V, typename Comparator> +bool operator==(const SafeMap<K, V, Comparator>& lhs, const SafeMap<K, V, Comparator>& rhs) { + return lhs.Equals(rhs); +} + +template <typename K, typename V, typename Comparator> +bool operator!=(const SafeMap<K, V, Comparator>& lhs, const SafeMap<K, V, Comparator>& rhs) { + return !(lhs == rhs); +} + +} // namespace art + +#endif // ART_SRC_SAFE_MAP_H_ diff --git a/src/trace.cc b/src/trace.cc index 3278830948..588979b54f 100644 --- a/src/trace.cc +++ b/src/trace.cc @@ -164,7 +164,7 @@ static void TraceRestoreStack(Thread* t, void*) { } void Trace::AddSavedCodeToMap(const Method* method, const void* code) { - saved_code_map_.insert(std::make_pair(method, code)); + saved_code_map_.Put(method, code); } void Trace::RemoveSavedCodeFromMap(const Method* method) { @@ -172,7 +172,7 @@ void Trace::RemoveSavedCodeFromMap(const Method* method) { } const void* Trace::GetSavedCodeFromMap(const Method* method) { - typedef std::map<const Method*, const void*>::const_iterator It; // TODO: C++0x auto + typedef SafeMap<const Method*, const void*>::const_iterator It; // TODO: C++0x auto It it = saved_code_map_.find(method); if (it == saved_code_map_.end()) { return NULL; @@ -355,7 +355,7 @@ void Trace::FinishTracing() { void Trace::LogMethodTraceEvent(Thread* self, const Method* method, Trace::TraceEvent event) { if (thread_clock_base_map_.find(self) == thread_clock_base_map_.end()) { uint64_t time = ThreadCpuMicroTime(); - thread_clock_base_map_.insert(std::make_pair(self, time)); + thread_clock_base_map_.Put(self, time); } // Advance cur_offset_ atomically. diff --git a/src/trace.h b/src/trace.h index 8dbf92495b..bcf7f0a411 100644 --- a/src/trace.h +++ b/src/trace.h @@ -17,7 +17,6 @@ #ifndef ART_SRC_TRACE_H_ #define ART_SRC_TRACE_H_ -#include <map> #include <ostream> #include <set> #include <string> @@ -25,6 +24,7 @@ #include "file.h" #include "globals.h" #include "macros.h" +#include "safe_map.h" #include "UniquePtr.h" namespace art { @@ -90,13 +90,13 @@ class Trace { void DumpThreadList(std::ostream& os); // Maps a method to its original code pointer. - std::map<const Method*, const void*> saved_code_map_; + SafeMap<const Method*, const void*> saved_code_map_; // Set of methods visited by the profiler. std::set<const Method*> visited_methods_; // Maps a thread to its clock base. - std::map<Thread*, uint64_t> thread_clock_base_map_; + SafeMap<Thread*, uint64_t> thread_clock_base_map_; // File to write trace data out to, NULL if direct to ddms. UniquePtr<File> trace_file_; diff --git a/src/zip_archive.cc b/src/zip_archive.cc index fd7086f599..5e6b4eb1fc 100644 --- a/src/zip_archive.cc +++ b/src/zip_archive.cc @@ -466,10 +466,7 @@ bool ZipArchive::Parse() { // add the CDE filename to the hash table const char* name = reinterpret_cast<const char*>(ptr + kCDELen); - bool success = dir_entries_.insert(std::make_pair(StringPiece(name, filename_len), ptr)).second; - if (!success) { - return false; - } + dir_entries_.Put(StringPiece(name, filename_len), ptr); ptr += kCDELen + filename_len + extra_len + comment_len; if (ptr > cd_ptr + cd_length) { LOG(WARNING) << "Zip: bad CD advance " diff --git a/src/zip_archive.h b/src/zip_archive.h index 4f952845f5..3889fcbbb4 100644 --- a/src/zip_archive.h +++ b/src/zip_archive.h @@ -21,12 +21,11 @@ #include <sys/mman.h> #include <zlib.h> -#include <map> - #include "file.h" #include "globals.h" #include "logging.h" #include "mem_map.h" +#include "safe_map.h" #include "stringpiece.h" #include "UniquePtr.h" @@ -120,7 +119,7 @@ class ZipArchive { uint16_t num_entries_; off_t dir_offset_; UniquePtr<MemMap> dir_map_; - typedef std::map<StringPiece, const byte*> DirEntries; + typedef SafeMap<StringPiece, const byte*> DirEntries; DirEntries dir_entries_; friend class ZipEntry; |