diff options
| author | 2011-09-08 12:33:17 -0700 | |
|---|---|---|
| committer | 2011-09-08 14:26:18 -0700 | |
| commit | 5fe594f576225dd7d333835e39c448a71ea9b433 (patch) | |
| tree | f9b6203abaf07df1421f6e7cadcbb2c307cef5b2 /src | |
| parent | 4ef765227a0098b6f4dfe47d2d7a6f084cec9560 (diff) | |
A bit further along the track of multiple threads.
This also makes valgrind happy, and tsan mostly happy. (The heap, it turns out,
doesn't have a lock yet.)
The DexVerifier changes are just to make valgrind happy, and the code a little
less unidiomatic.
Change-Id: Ic5d436b4863b9d7088eb0b8fe9d32308919899d8
Diffstat (limited to 'src')
| -rw-r--r-- | src/class_linker.cc | 40 | ||||
| -rw-r--r-- | src/class_linker.h | 3 | ||||
| -rw-r--r-- | src/class_linker_test.cc | 15 | ||||
| -rw-r--r-- | src/dex_verifier.cc | 75 | ||||
| -rw-r--r-- | src/dex_verifier.h | 103 | ||||
| -rw-r--r-- | src/jni_internal.cc | 17 | ||||
| -rw-r--r-- | src/logging.cc | 37 | ||||
| -rw-r--r-- | src/object.cc | 4 | ||||
| -rw-r--r-- | src/object.h | 26 | ||||
| -rw-r--r-- | src/runtime.cc | 19 | ||||
| -rw-r--r-- | src/runtime.h | 2 | ||||
| -rw-r--r-- | src/signal_catcher.cc | 28 | ||||
| -rw-r--r-- | src/signal_catcher.h | 7 | ||||
| -rw-r--r-- | src/thread.cc | 67 | ||||
| -rw-r--r-- | src/thread.h | 9 |
15 files changed, 270 insertions, 182 deletions
diff --git a/src/class_linker.cc b/src/class_linker.cc index 14f4883711..b533a110ec 100644 --- a/src/class_linker.cc +++ b/src/class_linker.cc @@ -633,7 +633,7 @@ Class* ClassLinker::FindClass(const StringPiece& descriptor, } else { klass = AllocClass(SizeOfClass(dex_file, dex_class_def)); } - if (!klass->IsLinked()) { + if (!klass->IsResolved()) { klass->SetDexCache(dex_cache); LoadClass(dex_file, dex_class_def, klass, class_loader); // Check for a pending exception during load @@ -663,27 +663,27 @@ Class* ClassLinker::FindClass(const StringPiece& descriptor, } CHECK(klass->IsLoaded()); // Link the class (if necessary) - CHECK(!klass->IsLinked()); + CHECK(!klass->IsResolved()); if (!LinkClass(klass)) { // Linking failed. // TODO: CHECK(self->IsExceptionPending()); lock.NotifyAll(); return NULL; } - CHECK(klass->IsLinked()); + CHECK(klass->IsResolved()); } } } // Link the class if it has not already been linked. - if (!klass->IsLinked() && !klass->IsErroneous()) { + if (!klass->IsResolved() && !klass->IsErroneous()) { ObjectLock lock(klass); // Check for circular dependencies between classes. - if (!klass->IsLinked() && klass->GetClinitThreadId() == self->GetTid()) { + if (!klass->IsResolved() && klass->GetClinitThreadId() == self->GetTid()) { self->ThrowNewException("Ljava/lang/ClassCircularityError;", NULL); // TODO: detail return NULL; } // Wait for the pending initialization to complete. - while (!klass->IsLinked() && !klass->IsErroneous()) { + while (!klass->IsResolved() && !klass->IsErroneous()) { lock.Wait(); } } @@ -692,7 +692,7 @@ Class* ClassLinker::FindClass(const StringPiece& descriptor, return NULL; } // Return the loaded class. No exceptions should be pending. - CHECK(klass->IsLinked()); + CHECK(klass->IsResolved()); CHECK(!self->IsExceptionPending()); return klass; } @@ -1428,6 +1428,19 @@ StaticStorageBase* ClassLinker::InitializeStaticStorageFromCode(uint32_t type_id return klass; } +void ClassLinker::ConstructFieldMap(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def, + Class* c, std::map<int, Field*>& field_map) { + const ClassLoader* cl = c->GetClassLoader(); + const byte* class_data = dex_file.GetClassData(dex_class_def); + DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data); + uint32_t last_idx = 0; + for (size_t i = 0; i < header.static_fields_size_; ++i) { + DexFile::Field dex_field; + dex_file.dexReadClassDataField(&class_data, &dex_field, &last_idx); + field_map[i] = ResolveField(dex_file, dex_field.field_idx_, c->GetDexCache(), cl, true); + } +} + void ClassLinker::InitializeStaticFields(Class* klass) { size_t num_static_fields = klass->NumStaticFields(); if (num_static_fields == 0) { @@ -1442,6 +1455,11 @@ void ClassLinker::InitializeStaticFields(Class* klass) { const DexFile& dex_file = FindDexFile(dex_cache); const DexFile::ClassDef* dex_class_def = dex_file.FindClassDef(descriptor); CHECK(dex_class_def != NULL); + + // We reordered the fields, so we need to be able to map the field indexes to the right fields. + std::map<int, Field*> field_map; + ConstructFieldMap(dex_file, *dex_class_def, klass, field_map); + const byte* addr = dex_file.GetEncodedArray(*dex_class_def); if (addr == NULL) { // All this class' static fields have default values. @@ -1449,7 +1467,7 @@ void ClassLinker::InitializeStaticFields(Class* klass) { } size_t array_size = DecodeUnsignedLeb128(&addr); for (size_t i = 0; i < array_size; ++i) { - Field* field = klass->GetStaticField(i); + Field* field = field_map[i]; JValue value; DexFile::ValueType type = dex_file.ReadEncodedValue(&addr, &value); switch (type) { @@ -1573,7 +1591,7 @@ bool ClassLinker::LinkSuperClass(Class* klass) { #ifndef NDEBUG // Ensure super classes are fully resolved prior to resolving fields.. while (super != NULL) { - CHECK(super->IsLinked()); + CHECK(super->IsResolved()); super = super->GetSuperClass(); } #endif @@ -1818,7 +1836,7 @@ bool ClassLinker::LinkStaticFields(Class* klass) { return success; } -bool ClassLinker::LinkFields(Class *klass, bool instance) { +bool ClassLinker::LinkFields(Class* klass, bool instance) { size_t num_fields = instance ? klass->NumInstanceFields() : klass->NumStaticFields(); @@ -1833,7 +1851,7 @@ bool ClassLinker::LinkFields(Class *klass, bool instance) { if (instance) { Class* super_class = klass->GetSuperClass(); if (super_class != NULL) { - CHECK(super_class->IsLinked()); + CHECK(super_class->IsResolved()); field_offset = MemberOffset(super_class->GetObjectSize()); if (field_offset.Uint32Value() == 0u) { field_offset = OFFSET_OF_OBJECT_MEMBER(DataObject, fields_); diff --git a/src/class_linker.h b/src/class_linker.h index 4f4ffc79c9..fe375c214d 100644 --- a/src/class_linker.h +++ b/src/class_linker.h @@ -185,6 +185,9 @@ class ClassLinker { void AppendToBootClassPath(const DexFile& dex_file); void AppendToBootClassPath(const DexFile& dex_file, DexCache* dex_cache); + void ConstructFieldMap(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def, + Class* c, std::map<int, Field*>& field_map); + size_t SizeOfClass(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def); diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc index 71cb22eb82..607382b074 100644 --- a/src/class_linker_test.cc +++ b/src/class_linker_test.cc @@ -40,7 +40,7 @@ class ClassLinkerTest : public CommonTest { EXPECT_TRUE(primitive->GetStatus() == Class::kStatusInitialized); EXPECT_FALSE(primitive->IsErroneous()); EXPECT_TRUE(primitive->IsVerified()); - EXPECT_TRUE(primitive->IsLinked()); + EXPECT_TRUE(primitive->IsResolved()); EXPECT_FALSE(primitive->IsArrayInstance()); EXPECT_FALSE(primitive->IsArrayClass()); EXPECT_EQ(0, primitive->GetArrayRank()); @@ -81,7 +81,7 @@ class ClassLinkerTest : public CommonTest { EXPECT_TRUE(array->GetStatus() == Class::kStatusInitialized); EXPECT_FALSE(array->IsErroneous()); EXPECT_TRUE(array->IsVerified()); - EXPECT_TRUE(array->IsLinked()); + EXPECT_TRUE(array->IsResolved()); EXPECT_FALSE(array->IsArrayInstance()); EXPECT_TRUE(array->IsArrayClass()); EXPECT_LE(1, array->GetArrayRank()); @@ -138,10 +138,9 @@ class ClassLinkerTest : public CommonTest { EXPECT_TRUE(klass->GetSuperClass() != NULL); } EXPECT_TRUE(klass->GetDexCache() != NULL); - EXPECT_EQ(Class::kStatusResolved, klass->GetStatus()); + EXPECT_TRUE(klass->IsResolved()); EXPECT_FALSE(klass->IsErroneous()); - EXPECT_FALSE(klass->IsVerified()); - EXPECT_TRUE(klass->IsLinked()); + EXPECT_TRUE(klass->IsResolved()); EXPECT_TRUE(klass->IsLoaded()); EXPECT_FALSE(klass->IsArrayClass()); EXPECT_EQ(0, klass->GetArrayRank()); @@ -309,8 +308,8 @@ TEST_F(ClassLinkerTest, FindClass) { EXPECT_FALSE(JavaLangObject->HasSuperClass()); EXPECT_TRUE(JavaLangObject->GetClassLoader() == NULL); EXPECT_FALSE(JavaLangObject->IsErroneous()); - EXPECT_FALSE(JavaLangObject->IsVerified()); - EXPECT_TRUE(JavaLangObject->IsLinked()); + EXPECT_TRUE(JavaLangObject->IsVerified()); + EXPECT_TRUE(JavaLangObject->IsResolved()); EXPECT_FALSE(JavaLangObject->IsArrayInstance()); EXPECT_FALSE(JavaLangObject->IsArrayClass()); EXPECT_EQ(0, JavaLangObject->GetArrayRank()); @@ -339,7 +338,7 @@ TEST_F(ClassLinkerTest, FindClass) { EXPECT_TRUE(MyClass->GetStatus() == Class::kStatusResolved); EXPECT_FALSE(MyClass->IsErroneous()); EXPECT_FALSE(MyClass->IsVerified()); - EXPECT_TRUE(MyClass->IsLinked()); + EXPECT_TRUE(MyClass->IsResolved()); EXPECT_FALSE(MyClass->IsArrayInstance()); EXPECT_FALSE(MyClass->IsArrayClass()); EXPECT_EQ(0, JavaLangObject->GetArrayRank()); diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc index df9d7cb231..0a93109060 100644 --- a/src/dex_verifier.cc +++ b/src/dex_verifier.cc @@ -12,7 +12,6 @@ #include "logging.h" #include "runtime.h" #include "stringpiece.h" -#include "UniquePtr.h" namespace art { @@ -125,7 +124,7 @@ bool DexVerifier::VerifyMethod(Method* method) { const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache(); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); const DexFile& dex_file = class_linker->FindDexFile(dex_cache); - const DexFile::CodeItem *code_item = + const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->GetCodeItemOffset()); /* @@ -158,8 +157,7 @@ bool DexVerifier::VerifyMethod(Method* method) { /* * Allocate and initialize an array to hold instruction data. */ - UniquePtr<InsnFlags> insn_flags(new InsnFlags[code_item->insns_size_]()); - vdata.insn_flags_ = insn_flags.get(); + vdata.insn_flags_.reset(new InsnFlags[code_item->insns_size_]()); /* * Run through the instructions and see if the width checks out. @@ -194,7 +192,7 @@ bool DexVerifier::VerifyMethod(Method* method) { bool DexVerifier::VerifyInstructions(VerifierData* vdata) { const DexFile::CodeItem* code_item = vdata->code_item_; - InsnFlags* insn_flags = vdata->insn_flags_; + InsnFlags* insn_flags = vdata->insn_flags_.get(); const byte* ptr = reinterpret_cast<const byte*>(code_item->insns_); const Instruction* inst = Instruction::At(ptr); @@ -227,7 +225,7 @@ bool DexVerifier::VerifyInstruction(VerifierData* vdata, const Instruction* inst, uint32_t code_offset) { const DexFile* dex_file = vdata->dex_file_; const DexFile::CodeItem* code_item = vdata->code_item_; - InsnFlags* insn_flags = vdata->insn_flags_; + InsnFlags* insn_flags = vdata->insn_flags_.get(); Instruction::DecodedInstruction dec_insn(inst); bool result = true; @@ -330,14 +328,13 @@ bool DexVerifier::VerifyCodeFlow(VerifierData* vdata) { return false; } - vdata->register_lines_ = reg_table.register_lines_; + vdata->register_lines_ = reg_table.register_lines_.get(); /* Allocate a map to hold the classes of uninitialized instances. */ - UniquePtr<UninitInstanceMap> uninit_map(CreateUninitInstanceMap(vdata)); - vdata->uninit_map_ = uninit_map.get(); + vdata->uninit_map_.reset(CreateUninitInstanceMap(vdata)); /* Initialize register types of method arguments. */ - if (!SetTypesFromSignature(vdata, reg_table.register_lines_[0].reg_types_)) { + if (!SetTypesFromSignature(vdata, reg_table.register_lines_[0].reg_types_.get())) { LOG(ERROR) << "VFY: bad signature '" << method->GetSignature()->ToModifiedUtf8() << "' for " << method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8() @@ -359,7 +356,7 @@ bool DexVerifier::VerifyCodeFlow(VerifierData* vdata) { bool DexVerifier::ComputeWidthsAndCountOps(VerifierData* vdata) { const uint16_t* insns = vdata->code_item_->insns_; uint32_t insns_size = vdata->code_item_->insns_size_; - InsnFlags* insn_flags = vdata->insn_flags_; + InsnFlags* insn_flags = vdata->insn_flags_.get(); const byte* ptr = reinterpret_cast<const byte*>(insns); const Instruction* inst = Instruction::At(ptr); size_t new_instance_count = 0; @@ -392,7 +389,7 @@ bool DexVerifier::ComputeWidthsAndCountOps(VerifierData* vdata) { bool DexVerifier::ScanTryCatchBlocks(VerifierData* vdata) { const DexFile::CodeItem* code_item = vdata->code_item_; - InsnFlags* insn_flags = vdata->insn_flags_; + InsnFlags* insn_flags = vdata->insn_flags_.get(); uint32_t insns_size = code_item->insns_size_; uint32_t tries_size = code_item->tries_size_; @@ -821,7 +818,7 @@ bool DexVerifier::CheckBranchTarget(const DexFile::CodeItem* code_item, bool DexVerifier::InitRegisterTable(VerifierData* vdata, RegisterTable* reg_table, RegisterTrackingMode track_regs_for) { const DexFile::CodeItem* code_item = vdata->code_item_; - InsnFlags* insn_flags = vdata->insn_flags_; + InsnFlags* insn_flags = vdata->insn_flags_.get(); uint16_t registers_size = code_item->registers_size_; uint32_t insns_size = code_item->insns_size_; uint32_t i; @@ -832,7 +829,7 @@ bool DexVerifier::InitRegisterTable(VerifierData* vdata, * indirection. */ reg_table->insn_reg_count_plus_ = registers_size + kExtraRegs; - reg_table->register_lines_ = new RegisterLine[insns_size](); + reg_table->register_lines_.reset(new RegisterLine[insns_size]()); assert(insns_size > 0); @@ -1050,7 +1047,7 @@ bool DexVerifier::SetTypesFromSignature(VerifierData* vdata, RegType* reg_types) Method* method = vdata->method_; const DexFile* dex_file = vdata->dex_file_; const DexFile::CodeItem* code_item = vdata->code_item_; - UninitInstanceMap* uninit_map = vdata->uninit_map_; + UninitInstanceMap* uninit_map = vdata->uninit_map_.get(); int arg_start = code_item->registers_size_ - code_item->ins_size_; int expected_args = code_item->ins_size_; /* long/double count as two */ @@ -1243,7 +1240,7 @@ bool DexVerifier::CodeFlowVerifyMethod(VerifierData* vdata, RegisterTable* reg_table) { const Method* method = vdata->method_; const DexFile::CodeItem* code_item = vdata->code_item_; - InsnFlags* insn_flags = vdata->insn_flags_; + InsnFlags* insn_flags = vdata->insn_flags_.get(); const uint16_t* insns = code_item->insns_; uint32_t insns_size = code_item->insns_size_; size_t insn_idx, start_guess; @@ -1296,7 +1293,7 @@ bool DexVerifier::CodeFlowVerifyMethod(VerifierData* vdata, * a full table) and make sure it actually matches. */ RegisterLine* register_line = GetRegisterLine(reg_table, insn_idx); - if (register_line->reg_types_ != NULL && CompareLineToTable(reg_table, + if (register_line->reg_types_.get() != NULL && CompareLineToTable(reg_table, insn_idx, ®_table->work_line_) != 0) { Class* klass = method->GetDeclaringClass(); LOG(ERROR) << "HUH? work_line diverged in " @@ -1378,9 +1375,9 @@ bool DexVerifier::CodeFlowVerifyInstruction(VerifierData* vdata, const Method* method = vdata->method_; Class* klass = method->GetDeclaringClass(); const DexFile::CodeItem* code_item = vdata->code_item_; - InsnFlags* insn_flags = vdata->insn_flags_; + InsnFlags* insn_flags = vdata->insn_flags_.get(); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - UninitInstanceMap* uninit_map = vdata->uninit_map_; + UninitInstanceMap* uninit_map = vdata->uninit_map_.get(); const uint16_t* insns = code_item->insns_ + insn_idx; uint32_t insns_size = code_item->insns_size_; uint32_t registers_size = code_item->registers_size_; @@ -1437,7 +1434,7 @@ bool DexVerifier::CodeFlowVerifyInstruction(VerifierData* vdata, reg_table->insn_reg_count_plus_); } else { #ifndef NDEBUG - memset(reg_table->saved_line_.reg_types_, 0xdd, + memset(reg_table->saved_line_.reg_types_.get(), 0xdd, reg_table->insn_reg_count_plus_ * sizeof(RegType)); #endif } @@ -1681,7 +1678,7 @@ bool DexVerifier::CodeFlowVerifyInstruction(VerifierData* vdata, * we skip them here); if we can't, then the code path could be * "live" so we still need to check it. */ - if (work_line->monitor_entries_ != NULL) + if (work_line->monitor_entries_.get() != NULL) opcode_flag &= ~Instruction::kThrow; HandleMonitorExit(work_line, dec_insn.vA_, insn_idx, &failure); break; @@ -3450,7 +3447,7 @@ sput_1nr_common: if (!CheckMoveException(code_item->insns_, insn_idx + insn_width)) return false; - if (GetRegisterLine(reg_table, insn_idx + insn_width)->reg_types_ != NULL) { + if (GetRegisterLine(reg_table, insn_idx + insn_width)->reg_types_.get() != NULL) { /* * Merge registers into what we have for the next instruction, * and set the "changed" flag if needed. @@ -3732,7 +3729,7 @@ void DexVerifier::HandleMonitorEnter(RegisterLine* work_line, uint32_t reg_idx, return; } - if (work_line->monitor_entries_ == NULL) { + if (work_line->monitor_entries_.get() == NULL) { return; } @@ -3760,7 +3757,7 @@ void DexVerifier::HandleMonitorExit(RegisterLine* work_line, uint32_t reg_idx, return; } - if (work_line->monitor_entries_ == NULL) { + if (work_line->monitor_entries_.get() == NULL) { return; } @@ -3801,7 +3798,7 @@ Field* DexVerifier::GetInstField(VerifierData* vdata, RegType obj_type, int field_idx, VerifyError* failure) { Method* method = vdata->method_; const DexFile* dex_file = vdata->dex_file_; - UninitInstanceMap* uninit_map = vdata->uninit_map_; + UninitInstanceMap* uninit_map = vdata->uninit_map_.get(); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache(); const ClassLoader* class_loader = @@ -4013,7 +4010,7 @@ DexVerifier::RegType DexVerifier::GetInvocationThis( void DexVerifier::SetRegisterType(RegisterLine* register_line, uint32_t vdst, RegType new_type) { - RegType* insn_regs = register_line->reg_types_; + RegType* insn_regs = register_line->reg_types_.get(); switch (new_type) { case kRegTypeUnknown: @@ -4077,13 +4074,13 @@ void DexVerifier::SetRegisterType(RegisterLine* register_line, uint32_t vdst, /* * Clear the monitor entry bits for this register. */ - if (register_line->monitor_entries_ != NULL) + if (register_line->monitor_entries_.get() != NULL) register_line->monitor_entries_[vdst] = 0; } void DexVerifier::VerifyRegisterType(RegisterLine* register_line, uint32_t vsrc, RegType check_type, VerifyError* failure) { - const RegType* insn_regs = register_line->reg_types_; + const RegType* insn_regs = register_line->reg_types_.get(); RegType src_type = insn_regs[vsrc]; switch (check_type) { @@ -4189,7 +4186,7 @@ void DexVerifier::SetResultRegisterType(RegisterLine* register_line, void DexVerifier::MarkRefsAsInitialized(RegisterLine* register_line, int insn_reg_count, UninitInstanceMap* uninit_map, RegType uninit_type, VerifyError* failure) { - RegType* insn_regs = register_line->reg_types_; + RegType* insn_regs = register_line->reg_types_.get(); Class* klass = GetUninitInstance(uninit_map, RegTypeToUninitIndex(uninit_type)); @@ -4216,12 +4213,12 @@ void DexVerifier::MarkRefsAsInitialized(RegisterLine* register_line, void DexVerifier::MarkUninitRefsAsInvalid(RegisterLine* register_line, int insn_reg_count, UninitInstanceMap* uninit_map, RegType uninit_type) { - RegType* insn_regs = register_line->reg_types_; + RegType* insn_regs = register_line->reg_types_.get(); for (int i = 0; i < insn_reg_count; i++) { if (insn_regs[i] == uninit_type) { insn_regs[i] = kRegTypeConflict; - if (register_line->monitor_entries_ != NULL) + if (register_line->monitor_entries_.get() != NULL) register_line->monitor_entries_[i] = 0; } } @@ -4237,7 +4234,7 @@ void DexVerifier::CopyRegister1(RegisterLine* register_line, uint32_t vdst, << " cat=" << (int) cat; } else { SetRegisterType(register_line, vdst, type); - if (cat == kTypeCategoryRef && register_line->monitor_entries_ != NULL) { + if (cat == kTypeCategoryRef && register_line->monitor_entries_.get() != NULL) { register_line->monitor_entries_[vdst] = register_line->monitor_entries_[vsrc]; } @@ -4489,7 +4486,7 @@ bool DexVerifier::UpdateRegisters(InsnFlags* insn_flags, RegisterTable* reg_table, int next_insn, const RegisterLine* work_line) { const size_t insn_reg_count_plus = reg_table->insn_reg_count_plus_; assert(work_line != NULL); - const RegType* work_regs = work_line->reg_types_; + const RegType* work_regs = work_line->reg_types_.get(); if (!InsnIsVisitedOrChanged(insn_flags, next_insn)) { /* @@ -4504,9 +4501,9 @@ bool DexVerifier::UpdateRegisters(InsnFlags* insn_flags, } else { /* Merge registers, set Changed only if different */ RegisterLine* target_line = GetRegisterLine(reg_table, next_insn); - RegType* target_regs = target_line->reg_types_; - MonitorEntries* work_mon_ents = work_line->monitor_entries_; - MonitorEntries* target_mon_ents = target_line->monitor_entries_; + RegType* target_regs = target_line->reg_types_.get(); + MonitorEntries* work_mon_ents = work_line->monitor_entries_.get(); + MonitorEntries* target_mon_ents = target_line->monitor_entries_.get(); bool changed = false; unsigned int idx; @@ -4520,7 +4517,7 @@ bool DexVerifier::UpdateRegisters(InsnFlags* insn_flags, << std::hex << next_insn << std::dec; return false; } - if (memcmp(target_line->monitor_stack_, work_line->monitor_stack_, + if (memcmp(target_line->monitor_stack_.get(), work_line->monitor_stack_.get(), target_line->monitor_stack_top_ * sizeof(uint32_t)) != 0) { LOG(ERROR) << "VFY: mismatched monitor stacks at 0x" << std::hex << next_insn << std::dec; @@ -4667,7 +4664,7 @@ void DexVerifier::CheckArrayIndexType(const Method* method, RegType reg_type, bool DexVerifier::CheckConstructorReturn(const Method* method, const RegisterLine* register_line, const int insn_reg_count) { - const RegType* insn_regs = register_line->reg_types_; + const RegType* insn_regs = register_line->reg_types_.get(); if (!IsInitMethod(method)) return true; @@ -4955,7 +4952,7 @@ Method* DexVerifier::VerifyInvocationArgs(VerifierData* vdata, Method* method = vdata->method_; const DexFile* dex_file = vdata->dex_file_; const DexFile::CodeItem* code_item = vdata->code_item_; - UninitInstanceMap* uninit_map = vdata->uninit_map_; + UninitInstanceMap* uninit_map = vdata->uninit_map_.get(); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache(); const ClassLoader* class_loader = diff --git a/src/dex_verifier.h b/src/dex_verifier.h index b6fbd46fb5..c89dfaf412 100644 --- a/src/dex_verifier.h +++ b/src/dex_verifier.h @@ -7,6 +7,7 @@ #include "dex_instruction.h" #include "macros.h" #include "object.h" +#include "UniquePtr.h" namespace art { @@ -235,32 +236,21 @@ class DexVerifier { * to the GC). */ struct RegisterLine { - RegType* reg_types_; - MonitorEntries* monitor_entries_; - uint32_t* monitor_stack_; - uint32_t monitor_stack_top_; - - /* Default constructor. */ - RegisterLine() { - reg_types_ = NULL; - monitor_entries_ = NULL; - monitor_stack_ = NULL; - monitor_stack_top_ = 0; - } + UniquePtr<RegType[]> reg_types_; + UniquePtr<MonitorEntries[]> monitor_entries_; + UniquePtr<uint32_t[]> monitor_stack_; + uint32_t monitor_stack_top_; - /* Default destructor. */ - ~RegisterLine() { - delete reg_types_; - delete monitor_entries_; - delete monitor_stack_; + RegisterLine() + : reg_types_(NULL), monitor_entries_(NULL), monitor_stack_(NULL), monitor_stack_top_(0) { } /* Allocate space for the fields. */ void Alloc(size_t size, bool track_monitors) { - reg_types_ = new RegType[size](); + reg_types_.reset(new RegType[size]()); if (track_monitors) { - monitor_entries_ = new MonitorEntries[size]; - monitor_stack_ = new uint32_t[kMaxMonitorStackDepth]; + monitor_entries_.reset(new MonitorEntries[size]); + monitor_stack_.reset(new uint32_t[kMaxMonitorStackDepth]); } } }; @@ -272,7 +262,7 @@ class DexVerifier { * set the pointers for certain addresses, based on instruction widths * and what we're trying to accomplish. */ - RegisterLine* register_lines_; + UniquePtr<RegisterLine[]> register_lines_; /* * Number of registers we track for each instruction. This is equal @@ -286,15 +276,7 @@ class DexVerifier { /* Storage for a register line we're saving for later. */ RegisterLine saved_line_; - /* Default constructor. */ - RegisterTable() { - register_lines_ = NULL; - insn_reg_count_plus_ = 0; - } - - /* Default destructor. */ - ~RegisterTable() { - delete [] register_lines_; + RegisterTable() : register_lines_(NULL), insn_reg_count_plus_(0) { } }; @@ -313,17 +295,11 @@ class DexVerifier { */ struct UninitInstanceMap { int num_entries_; - UninitInstanceMapEntry* map_; - - /* Basic constructor */ - UninitInstanceMap(int num_entries) { - num_entries_ = num_entries; - map_ = new UninitInstanceMapEntry[num_entries](); - } + UniquePtr<UninitInstanceMapEntry[]> map_; - /* Default destructor */ - ~UninitInstanceMap() { - delete map_; + UninitInstanceMap(int num_entries) + : num_entries_(num_entries), + map_(new UninitInstanceMapEntry[num_entries]()) { } }; #define kUninitThisArgAddr (-1) @@ -341,13 +317,13 @@ class DexVerifier { const DexFile::CodeItem* code_item_; /* Instruction widths and flags, one entry per code unit. */ - InsnFlags* insn_flags_; + UniquePtr<InsnFlags[]> insn_flags_; /* * Uninitialized instance map, used for tracking the movement of * objects that have been allocated but not initialized. */ - UninitInstanceMap* uninit_map_; + UniquePtr<UninitInstanceMap> uninit_map_; /* * Array of RegisterLine structs, one entry per code unit. We only need @@ -361,7 +337,6 @@ class DexVerifier { size_t new_instance_count_; size_t monitor_enter_count_; - /* Basic constructor. */ VerifierData(Method* method, const DexFile* dex_file, const DexFile::CodeItem* code_item) : method_(method), dex_file_(dex_file), code_item_(code_item), @@ -461,9 +436,9 @@ class DexVerifier { } /* Get the class object at the specified index. */ - static inline Class* GetUninitInstance(const UninitInstanceMap* uninit_map, - int idx) { - assert(idx >= 0 && idx < uninit_map->num_entries_); + static inline Class* GetUninitInstance(const UninitInstanceMap* uninit_map, int idx) { + DCHECK_GE(idx, 0); + DCHECK_LT(idx, uninit_map->num_entries_); return uninit_map->map_[idx].klass_; } @@ -483,7 +458,7 @@ class DexVerifier { * (does not expect uninit ref types or "zero"). */ static Class* RegTypeInitializedReferenceToClass(RegType type) { - assert(RegTypeIsReference(type) && type != kRegTypeZero); + DCHECK(RegTypeIsReference(type) && type != kRegTypeZero); if ((type & 0x01) == 0) { return (Class*) type; } else { @@ -494,16 +469,16 @@ class DexVerifier { /* Extract the index into the uninitialized instance map table. */ static inline int RegTypeToUninitIndex(RegType type) { - assert(RegTypeIsUninitReference(type)); + DCHECK(RegTypeIsUninitReference(type)); return (type & ~kRegTypeUninitMask) >> kRegTypeUninitShift; } /* Convert the reference "type" to a Class pointer. */ static Class* RegTypeReferenceToClass(RegType type, const UninitInstanceMap* uninit_map) { - assert(RegTypeIsReference(type) && type != kRegTypeZero); + DCHECK(RegTypeIsReference(type) && type != kRegTypeZero); if (RegTypeIsUninitReference(type)) { - assert(uninit_map != NULL); + DCHECK(uninit_map != NULL); return GetUninitInstance(uninit_map, RegTypeToUninitIndex(type)); } else { return (Class*) type; @@ -755,15 +730,15 @@ class DexVerifier { /* Copy a register line. */ static inline void CopyRegisterLine(RegisterLine* dst, const RegisterLine* src, size_t num_regs) { - memcpy(dst->reg_types_, src->reg_types_, num_regs * sizeof(RegType)); + memcpy(dst->reg_types_.get(), src->reg_types_.get(), num_regs * sizeof(RegType)); - assert((src->monitor_entries_ == NULL && dst->monitor_entries_ == NULL) || - (src->monitor_entries_ != NULL && dst->monitor_entries_ != NULL)); - if (dst->monitor_entries_ != NULL) { - assert(dst->monitor_stack_ != NULL); - memcpy(dst->monitor_entries_, src->monitor_entries_, + DCHECK((src->monitor_entries_.get() == NULL && dst->monitor_entries_.get() == NULL) || + (src->monitor_entries_.get() != NULL && dst->monitor_entries_.get() != NULL)); + if (dst->monitor_entries_.get() != NULL) { + DCHECK(dst->monitor_stack_.get() != NULL); + memcpy(dst->monitor_entries_.get(), src->monitor_entries_.get(), num_regs * sizeof(MonitorEntries)); - memcpy(dst->monitor_stack_, src->monitor_stack_, + memcpy(dst->monitor_stack_.get(), src->monitor_stack_.get(), kMaxMonitorStackDepth * sizeof(uint32_t)); dst->monitor_stack_top_ = src->monitor_stack_top_; } @@ -773,7 +748,7 @@ class DexVerifier { static inline void CopyLineToTable(RegisterTable* reg_table, int insn_idx, const RegisterLine* src) { RegisterLine* dst = GetRegisterLine(reg_table, insn_idx); - assert(dst->reg_types_ != NULL); + DCHECK(dst->reg_types_.get() != NULL); CopyRegisterLine(dst, src, reg_table->insn_reg_count_plus_); } @@ -781,7 +756,7 @@ class DexVerifier { static inline void CopyLineFromTable(RegisterLine* dst, const RegisterTable* reg_table, int insn_idx) { RegisterLine* src = GetRegisterLine(reg_table, insn_idx); - assert(src->reg_types_ != NULL); + DCHECK(src->reg_types_.get() != NULL); CopyRegisterLine(dst, src, reg_table->insn_reg_count_plus_); } @@ -795,12 +770,12 @@ class DexVerifier { static inline int CompareLineToTable(const RegisterTable* reg_table, int insn_idx, const RegisterLine* line2) { const RegisterLine* line1 = GetRegisterLine(reg_table, insn_idx); - if (line1->monitor_entries_ != NULL) { + if (line1->monitor_entries_.get() != NULL) { int result; - if (line2->monitor_entries_ == NULL) + if (line2->monitor_entries_.get() == NULL) return 1; - result = memcmp(line1->monitor_entries_, line2->monitor_entries_, + result = memcmp(line1->monitor_entries_.get(), line2->monitor_entries_.get(), reg_table->insn_reg_count_plus_ * sizeof(MonitorEntries)); if (result != 0) { LOG(ERROR) << "monitor_entries_ mismatch"; @@ -811,14 +786,14 @@ class DexVerifier { LOG(ERROR) << "monitor_stack_top_ mismatch"; return result; } - result = memcmp(line1->monitor_stack_, line2->monitor_stack_, + result = memcmp(line1->monitor_stack_.get(), line2->monitor_stack_.get(), line1->monitor_stack_top_); if (result != 0) { LOG(ERROR) << "monitor_stack_ mismatch"; return result; } } - return memcmp(line1->reg_types_, line2->reg_types_, + return memcmp(line1->reg_types_.get(), line2->reg_types_.get(), reg_table->insn_reg_count_plus_ * sizeof(RegType)); } #endif diff --git a/src/jni_internal.cc b/src/jni_internal.cc index 8e24e47630..2ea6f76514 100644 --- a/src/jni_internal.cc +++ b/src/jni_internal.cc @@ -442,7 +442,8 @@ jint JII_AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args, bool as CHECK_GE(args.version, JNI_VERSION_1_2); Runtime* runtime = reinterpret_cast<JavaVMExt*>(vm)->runtime; - runtime->AttachCurrentThread(args.name, p_env, as_daemon); + runtime->AttachCurrentThread(args.name, as_daemon); + *p_env = Thread::Current()->GetJniEnv(); return JNI_OK; } @@ -618,11 +619,17 @@ class JNI { static jclass FindClass(JNIEnv* env, const char* name) { ScopedJniThreadState ts(env); - ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + Runtime* runtime = Runtime::Current(); + ClassLinker* class_linker = runtime->GetClassLinker(); std::string descriptor(NormalizeJniClassDescriptor(name)); - // TODO: need to get the appropriate ClassLoader. - const ClassLoader* cl = ts.Self()->GetClassLoaderOverride(); - Class* c = class_linker->FindClass(descriptor, cl); + Class* c = NULL; + if (runtime->IsStarted()) { + // TODO: need to get the appropriate ClassLoader. + const ClassLoader* cl = ts.Self()->GetClassLoaderOverride(); + c = class_linker->FindClass(descriptor, cl); + } else { + c = class_linker->FindSystemClass(descriptor); + } return AddLocalReference<jclass>(env, c); } diff --git a/src/logging.cc b/src/logging.cc index c59a099c52..03788c3b3e 100644 --- a/src/logging.cc +++ b/src/logging.cc @@ -17,26 +17,43 @@ #include "logging.h" #include "runtime.h" +#include "thread.h" #include "utils.h" +namespace { + +art::Mutex* GetLoggingLock() { + static art::Mutex* lock = art::Mutex::Create("LogMessage lock"); + return lock; +} + +} + LogMessage::~LogMessage() { + // Finish constructing the message. if (errno_ != -1) { buffer_ << ": " << strerror(errno_); } std::string msg(buffer_.str()); - if (msg.find('\n') == std::string::npos) { - LogLine(msg.c_str()); - } else { - msg += '\n'; - size_t i = 0; - while (i < msg.size()) { - size_t nl = msg.find('\n', i); - msg[nl] = '\0'; - LogLine(&msg[i]); - i = nl + 1; + + // Do the actual logging with the lock held. + { + art::MutexLock mu(GetLoggingLock()); + if (msg.find('\n') == std::string::npos) { + LogLine(msg.c_str()); + } else { + msg += '\n'; + size_t i = 0; + while (i < msg.size()) { + size_t nl = msg.find('\n', i); + msg[nl] = '\0'; + LogLine(&msg[i]); + i = nl + 1; + } } } + // Abort if necessary. if (severity_ == FATAL) { art::Runtime::Abort(file_, line_number_); } diff --git a/src/object.cc b/src/object.cc index d7b6024119..7c27ec798d 100644 --- a/src/object.cc +++ b/src/object.cc @@ -196,7 +196,7 @@ int32_t Field::GetInt(const Object* object) const { } void Field::SetInt(Object* object, int32_t i) const { - DCHECK(GetType()->IsPrimitiveInt()); + DCHECK(GetType()->IsPrimitiveInt()) << PrettyField(this); Set32(object, i); } @@ -273,7 +273,7 @@ void Method::SetReturnTypeIdx(uint32_t new_return_type_idx) { } Class* Method::GetReturnType() const { - DCHECK(GetDeclaringClass()->IsLinked()); + DCHECK(GetDeclaringClass()->IsResolved()); // Short-cut Class* result = GetDexCacheResolvedTypes()->Get(GetReturnTypeIdx()); if (result == NULL) { diff --git a/src/object.h b/src/object.h index c0e725c39f..23ce3c4cee 100644 --- a/src/object.h +++ b/src/object.h @@ -1275,7 +1275,7 @@ class Class : public StaticStorageBase { } // Returns true if the class has been linked. - bool IsLinked() const { + bool IsResolved() const { return GetStatus() >= kStatusResolved; } @@ -1630,7 +1630,7 @@ class Class : public StaticStorageBase { } Method* GetVirtualMethod(uint32_t i) const { - DCHECK(IsLinked()); + DCHECK(IsResolved()); return GetVirtualMethods()->Get(i); } @@ -1647,7 +1647,7 @@ class Class : public StaticStorageBase { } ObjectArray<Method>* GetVTable() const { - DCHECK(IsLinked()); + DCHECK(IsResolved()); return GetFieldObject<ObjectArray<Method>*>( OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false); } @@ -1745,7 +1745,7 @@ class Class : public StaticStorageBase { } size_t GetIFTableCount() const { - DCHECK(IsLinked()); + DCHECK(IsResolved()); DCHECK(sizeof(size_t) == sizeof(int32_t)); return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, iftable_count_), false); } @@ -1757,7 +1757,7 @@ class Class : public StaticStorageBase { } InterfaceEntry* GetIFTable() const { - DCHECK(IsLinked()); + DCHECK(IsResolved()); return GetFieldPtr<InterfaceEntry*>( OFFSET_OF_OBJECT_MEMBER(Class, iftable_), false); } @@ -1768,7 +1768,7 @@ class Class : public StaticStorageBase { } size_t GetIfviPoolCount() const { - DCHECK(IsLinked()); + DCHECK(IsResolved()); CHECK(sizeof(size_t) == sizeof(int32_t)); return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, ifvi_pool_count_), false); } @@ -1780,7 +1780,7 @@ class Class : public StaticStorageBase { } uint32_t* GetIfviPool() const { - DCHECK(IsLinked()); + DCHECK(IsResolved()); return GetFieldPtr<uint32_t*>( OFFSET_OF_OBJECT_MEMBER(Class, ifvi_pool_), false); } @@ -1820,7 +1820,7 @@ class Class : public StaticStorageBase { // Returns the number of instance fields containing reference types. size_t NumReferenceInstanceFields() const { - DCHECK(IsLinked()); + DCHECK(IsResolved()); DCHECK(sizeof(size_t) == sizeof(int32_t)); return GetField32( OFFSET_OF_OBJECT_MEMBER(Class, num_reference_instance_fields_), false); @@ -1840,7 +1840,7 @@ class Class : public StaticStorageBase { } uint32_t GetReferenceInstanceOffsets() const { - DCHECK(IsLinked()); + DCHECK(IsResolved()); return GetField32( OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_), false); } @@ -1854,7 +1854,7 @@ class Class : public StaticStorageBase { // Returns the number of static fields containing reference types. size_t NumReferenceStaticFields() const { - DCHECK(IsLinked()); + DCHECK(IsResolved()); DCHECK(sizeof(size_t) == sizeof(int32_t)); return GetField32( OFFSET_OF_OBJECT_MEMBER(Class, num_reference_static_fields_), false); @@ -2208,7 +2208,7 @@ inline void Method::SetDeclaringClass(Class *new_declaring_class) { } inline uint32_t Method::GetReturnTypeIdx() const { - DCHECK(GetDeclaringClass()->IsLinked()); + DCHECK(GetDeclaringClass()->IsResolved()); return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, java_return_type_idx_), false); } @@ -2527,7 +2527,7 @@ inline uint32_t Field::GetTypeIdx() const { } inline MemberOffset Field::GetOffset() const { - DCHECK(GetDeclaringClass()->IsLinked()); + DCHECK(GetDeclaringClass()->IsResolved()); return MemberOffset( GetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_), false)); } @@ -2595,7 +2595,7 @@ inline uint32_t Method::GetAccessFlags() const { } inline uint16_t Method::GetMethodIndex() const { - DCHECK(GetDeclaringClass()->IsLinked()); + DCHECK(GetDeclaringClass()->IsResolved()); return GetField16(OFFSET_OF_OBJECT_MEMBER(Method, method_index_), false); } diff --git a/src/runtime.cc b/src/runtime.cc index 2acf2ece17..c7ae9c1d7b 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -36,10 +36,11 @@ Runtime::Runtime() } Runtime::~Runtime() { - // TODO: use smart pointers instead. (we'll need the pimpl idiom.) + // Make sure our internal threads are dead before we start tearing down things they're using. + delete signal_catcher_; + delete class_linker_; Heap::Destroy(); - delete signal_catcher_; delete thread_list_; delete intern_table_; delete java_vm_; @@ -336,6 +337,11 @@ Runtime* Runtime::Create(const Options& options, bool ignore_unrecognized) { void Runtime::Start() { started_ = true; + + // Finish attaching the main thread. + Thread* main_thread = Thread::Current(); + main_thread->CreatePeer("main", false); + instance_->InitLibraries(); instance_->signal_catcher_ = new SignalCatcher; } @@ -378,7 +384,9 @@ bool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) { return false; } - thread_list_->Register(Thread::Attach(this, "main", false)); + // ClassLinker needs an attached thread, but we can't fully attach a thread + // without creating objects. + Thread::Attach(this, "main", false); class_linker_ = ClassLinker::Create(options->boot_class_path_, options->class_path_, @@ -466,9 +474,8 @@ void Runtime::BlockSignals() { CHECK_EQ(sigprocmask(SIG_BLOCK, &sigset, NULL), 0); } -void Runtime::AttachCurrentThread(const char* name, JNIEnv** penv, bool as_daemon) { - Thread* t = Thread::Attach(instance_, name, as_daemon); - thread_list_->Register(t); +void Runtime::AttachCurrentThread(const char* name, bool as_daemon) { + Thread::Attach(instance_, name, as_daemon); } void Runtime::DetachCurrentThread() { diff --git a/src/runtime.h b/src/runtime.h index db86a966a9..96513e68fb 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -85,7 +85,7 @@ class Runtime { static void Abort(const char* file, int line); // Attaches the current native thread to the runtime. - void AttachCurrentThread(const char* name, JNIEnv** jni_env, bool as_daemon); + void AttachCurrentThread(const char* name, bool as_daemon); void CallExitHook(jint status); diff --git a/src/signal_catcher.cc b/src/signal_catcher.cc index e2e23608d5..1552180173 100644 --- a/src/signal_catcher.cc +++ b/src/signal_catcher.cc @@ -29,11 +29,12 @@ namespace art { -bool SignalCatcher::halt_ = false; - SignalCatcher::SignalCatcher() { + lock_ = Mutex::Create("SignalCatcher lock"); + SetHaltFlag(false); + // Create a raw pthread; its start routine will attach to the runtime. - errno = pthread_create(&thread_, NULL, &Run, NULL); + errno = pthread_create(&thread_, NULL, &Run, this); if (errno != 0) { PLOG(FATAL) << "pthread_create failed for signal catcher thread"; } @@ -42,11 +43,21 @@ SignalCatcher::SignalCatcher() { SignalCatcher::~SignalCatcher() { // Since we know the thread is just sitting around waiting for signals // to arrive, send it one. - halt_ = true; + SetHaltFlag(true); pthread_kill(thread_, SIGQUIT); pthread_join(thread_, NULL); } +void SignalCatcher::SetHaltFlag(bool new_value) { + MutexLock mu(lock_); + halt_ = new_value; +} + +bool SignalCatcher::ShouldHalt() { + MutexLock mu(lock_); + return halt_; +} + void SignalCatcher::HandleSigQuit() { // TODO: suspend all threads @@ -100,8 +111,11 @@ int WaitForSignal(Thread* thread, sigset_t& mask) { return signal_number; } -void* SignalCatcher::Run(void*) { - Runtime::Current()->AttachCurrentThread("Signal Catcher", NULL, true); +void* SignalCatcher::Run(void* arg) { + SignalCatcher* signal_catcher = reinterpret_cast<SignalCatcher*>(arg); + CHECK(signal_catcher != NULL); + + Runtime::Current()->AttachCurrentThread("Signal Catcher", true); Thread* self = Thread::Current(); CHECK(self != NULL); @@ -113,7 +127,7 @@ void* SignalCatcher::Run(void*) { while (true) { int signal_number = WaitForSignal(self, mask); - if (halt_) { + if (signal_catcher->ShouldHalt()) { Runtime::Current()->DetachCurrentThread(); return NULL; } diff --git a/src/signal_catcher.h b/src/signal_catcher.h index a31b9f1990..8d91a94933 100644 --- a/src/signal_catcher.h +++ b/src/signal_catcher.h @@ -21,6 +21,7 @@ namespace art { +class Mutex; class Runtime; class Thread; @@ -40,7 +41,11 @@ class SignalCatcher { static void* Run(void* arg); static void HandleSigUsr1(); - static bool halt_; + void SetHaltFlag(bool new_value); + bool ShouldHalt(); + + Mutex* lock_; + bool halt_; pthread_t thread_; }; diff --git a/src/thread.cc b/src/thread.cc index 7d909c936f..3081d91c86 100644 --- a/src/thread.cc +++ b/src/thread.cc @@ -205,10 +205,26 @@ bool Mutex::TryLock() { } void Mutex::Unlock() { - DCHECK(HaveLock()); +#ifndef NDEBUG + Thread* self = Thread::Current(); + std::stringstream os; + os << "owner="; + if (owner_ != NULL) { + os << *owner_; + } else { + os << "NULL"; + } + os << " self="; + if (self != NULL) { + os << *self; + } else { + os << "NULL"; + } + DCHECK(HaveLock()) << os.str(); +#endif + SetOwner(NULL); int result = pthread_mutex_unlock(&lock_impl_); CHECK_EQ(result, 0); - SetOwner(NULL); } bool Mutex::HaveLock() { @@ -244,7 +260,6 @@ Thread* Thread::Create(const Runtime* runtime) { size_t stack_size = runtime->GetStackSize(); Thread* new_thread = new Thread; - new_thread->InitCpu(); pthread_attr_t attr; errno = pthread_attr_init(&attr); @@ -279,25 +294,52 @@ Thread* Thread::Create(const Runtime* runtime) { } Thread* Thread::Attach(const Runtime* runtime, const char* name, bool as_daemon) { - Thread* thread = new Thread; - thread->InitCpu(); + Thread* self = new Thread; - thread->tid_ = ::art::GetTid(); - thread->handle_ = pthread_self(); - thread->is_daemon_ = as_daemon; + self->tid_ = ::art::GetTid(); + self->handle_ = pthread_self(); + self->is_daemon_ = as_daemon; - thread->state_ = kRunnable; + self->state_ = kRunnable; SetThreadName(name); - errno = pthread_setspecific(Thread::pthread_key_self_, thread); + errno = pthread_setspecific(Thread::pthread_key_self_, self); if (errno != 0) { PLOG(FATAL) << "pthread_setspecific failed"; } - thread->jni_env_ = new JNIEnvExt(thread, runtime->GetJavaVM()); + self->jni_env_ = new JNIEnvExt(self, runtime->GetJavaVM()); + + runtime->GetThreadList()->Register(self); + + // If we're the main thread, ClassLinker won't be created until after we're attached, + // so that thread needs a two-stage attach. Regular threads don't need this hack. + if (self->thin_lock_id_ != ThreadList::kMainId) { + self->CreatePeer(name, as_daemon); + } + + return self; +} + +void Thread::CreatePeer(const char* name, bool as_daemon) { + ScopedThreadStateChange tsc(Thread::Current(), Thread::kNative); + + JNIEnv* env = jni_env_; + + jobject thread_group = NULL; + jobject thread_name = env->NewStringUTF(name); + jint thread_priority = 123; + jboolean thread_is_daemon = as_daemon; + + jclass c = env->FindClass("java/lang/Thread"); + LOG(INFO) << "java/lang/Thread=" << (void*)c; + jmethodID mid = env->GetMethodID(c, "<init>", "(Ljava/lang/ThreadGroup;Ljava/lang/String;IZ)V"); + LOG(INFO) << "java/lang/Thread.<init>=" << (void*)mid; + jobject o = env->NewObject(c, mid, thread_group, thread_name, thread_priority, thread_is_daemon); + LOG(INFO) << "Created new java.lang.Thread " << (void*) o << " decoded=" << (void*) DecodeJObject(o); - return thread; + peer_ = DecodeJObject(o); } void Thread::Dump(std::ostream& os) const { @@ -494,6 +536,7 @@ Thread::Thread() exception_(NULL), suspend_count_(0), class_loader_override_(NULL) { + InitCpu(); { ThreadListLock mu; thin_lock_id_ = Runtime::Current()->GetThreadList()->AllocThreadId(); diff --git a/src/thread.h b/src/thread.h index b255d6b2ec..df162b9631 100644 --- a/src/thread.h +++ b/src/thread.h @@ -448,6 +448,9 @@ class Thread { ~Thread(); friend class ThreadList; // For ~Thread. + void CreatePeer(const char* name, bool as_daemon); + friend class Runtime; // For CreatePeer. + void DumpState(std::ostream& os) const; void DumpStack(std::ostream& os) const; @@ -528,9 +531,9 @@ std::ostream& operator<<(std::ostream& os, const Thread::State& state); class ThreadList { public: - static const int kMaxThreadId = 0xFFFF; - static const int kInvalidId = 0; - static const int kMainId = 1; + static const uint32_t kMaxThreadId = 0xFFFF; + static const uint32_t kInvalidId = 0; + static const uint32_t kMainId = 1; static ThreadList* Create(); |