Merge "Add ISA directory to image and odex pathnames."
diff --git a/Android.mk b/Android.mk
index 3d65f6d..a7a1556 100644
--- a/Android.mk
+++ b/Android.mk
@@ -151,17 +151,16 @@
# host test targets
.PHONY: test-art-host-vixl
+VIXL_TEST_DEPENDENCY :=
+# We can only run the vixl tests on 64-bit hosts (vixl testing issue) when its a
+# top-level build (to declare the vixl test rule).
ifneq ($(HOST_IS_64_BIT),)
-test-art-host-vixl: $(ANDROID_HOST_OUT)/bin/cctest_vixl
- $(ANDROID_HOST_OUT)/bin/cctest_vixl --run_all
- @echo vixl PASSED
-
-else
-# vixl test needs 64b host.
-test-art-host-vixl:
- @echo vixl test only runnable with 64b host build.
-
+ifeq ($(ONE_SHOT_MAKEFILE),)
+VIXL_TEST_DEPENDENCY := run-vixl-tests
endif
+endif
+
+test-art-host-vixl: $(VIXL_TEST_DEPENDENCY)
# "mm test-art-host" to build and run all host tests
.PHONY: test-art-host
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index 219eec8..1cd528b 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -81,6 +81,7 @@
compiler/optimizing/find_loops_test.cc \
compiler/optimizing/linearize_test.cc \
compiler/optimizing/liveness_test.cc \
+ compiler/optimizing/live_ranges_test.cc \
compiler/optimizing/pretty_printer_test.cc \
compiler/optimizing/ssa_test.cc \
compiler/output_stream_test.cc \
diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h
index 586c442..7a91e47 100644
--- a/compiler/common_compiler_test.h
+++ b/compiler/common_compiler_test.h
@@ -130,6 +130,9 @@
return result;
}
+// Normally the ClassLinker supplies this.
+extern "C" void art_quick_generic_jni_trampoline(mirror::ArtMethod*);
+
class CommonCompilerTest : public CommonRuntimeTest {
public:
// Create an OatMethod based on pointers (for unit tests).
@@ -217,7 +220,7 @@
oat_method.LinkMethod(method);
method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterBridge);
} else {
- const void* method_code = GetQuickGenericJniTrampoline();
+ const void* method_code = reinterpret_cast<void*>(art_quick_generic_jni_trampoline);
OatFile::OatMethod oat_method = CreateOatMethod(method_code, nullptr);
oat_method.LinkMethod(method);
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index b48be58..93feb29 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -685,7 +685,7 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
CompilerDriver::DescriptorSet* image_classes =
reinterpret_cast<CompilerDriver::DescriptorSet*>(arg);
- image_classes->insert(ClassHelper(klass).GetDescriptor());
+ image_classes->insert(klass->GetDescriptor());
return true;
}
@@ -755,11 +755,15 @@
CHECK_NE(image_classes_->size(), 0U);
}
-static void MaybeAddToImageClasses(mirror::Class* klass, CompilerDriver::DescriptorSet* image_classes)
+static void MaybeAddToImageClasses(Handle<mirror::Class> c,
+ CompilerDriver::DescriptorSet* image_classes)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ Thread* self = Thread::Current();
+ StackHandleScope<1> hs(self);
+ // Make a copy of the handle so that we don't clobber it doing Assign.
+ Handle<mirror::Class> klass(hs.NewHandle(c.Get()));
while (!klass->IsObjectClass()) {
- ClassHelper kh(klass);
- const char* descriptor = kh.GetDescriptor();
+ std::string descriptor(klass->GetDescriptor());
std::pair<CompilerDriver::DescriptorSet::iterator, bool> result =
image_classes->insert(descriptor);
if (result.second) {
@@ -767,13 +771,16 @@
} else {
return;
}
- for (size_t i = 0; i < kh.NumDirectInterfaces(); ++i) {
- MaybeAddToImageClasses(kh.GetDirectInterface(i), image_classes);
+ for (size_t i = 0; i < klass->NumDirectInterfaces(); ++i) {
+ StackHandleScope<1> hs(self);
+ MaybeAddToImageClasses(hs.NewHandle(mirror::Class::GetDirectInterface(self, klass, i)),
+ image_classes);
}
if (klass->IsArrayClass()) {
- MaybeAddToImageClasses(klass->GetComponentType(), image_classes);
+ StackHandleScope<1> hs(self);
+ MaybeAddToImageClasses(hs.NewHandle(klass->GetComponentType()), image_classes);
}
- klass = klass->GetSuperClass();
+ klass.Assign(klass->GetSuperClass());
}
}
@@ -781,7 +788,8 @@
DCHECK(object != NULL);
DCHECK(arg != NULL);
CompilerDriver* compiler_driver = reinterpret_cast<CompilerDriver*>(arg);
- MaybeAddToImageClasses(object->GetClass(), compiler_driver->image_classes_.get());
+ StackHandleScope<1> hs(Thread::Current());
+ MaybeAddToImageClasses(hs.NewHandle(object->GetClass()), compiler_driver->image_classes_.get());
}
void CompilerDriver::UpdateImageClasses(TimingLogger* timings) {
@@ -1582,8 +1590,7 @@
CHECK(soa.Self()->IsExceptionPending());
mirror::Throwable* exception = soa.Self()->GetException(NULL);
VLOG(compiler) << "Exception during type resolution: " << exception->Dump();
- if (strcmp("Ljava/lang/OutOfMemoryError;",
- ClassHelper(exception->GetClass()).GetDescriptor()) == 0) {
+ if (exception->GetClass()->DescriptorEquals("Ljava/lang/OutOfMemoryError;")) {
// There's little point continuing compilation if the heap is exhausted.
LOG(FATAL) << "Out of memory during type resolution for compilation";
}
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 20a66d4..e261ee6 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -251,7 +251,9 @@
}
bool ImageWriter::ComputeLazyFieldsForClassesVisitor(Class* c, void* /*arg*/) {
- c->ComputeName();
+ Thread* self = Thread::Current();
+ StackHandleScope<1> hs(self);
+ mirror::Class::ComputeName(hs.NewHandle(c));
return true;
}
@@ -285,7 +287,7 @@
}
bool ImageWriter::IsImageClass(Class* klass) {
- return compiler_driver_.IsImageClass(ClassHelper(klass).GetDescriptor());
+ return compiler_driver_.IsImageClass(klass->GetDescriptor().c_str());
}
struct NonImageClasses {
@@ -339,7 +341,7 @@
bool ImageWriter::NonImageClassesVisitor(Class* klass, void* arg) {
NonImageClasses* context = reinterpret_cast<NonImageClasses*>(arg);
if (!context->image_writer->IsImageClass(klass)) {
- context->non_image_classes->insert(ClassHelper(klass).GetDescriptor());
+ context->non_image_classes->insert(klass->GetDescriptor());
}
return true;
}
@@ -359,7 +361,7 @@
Class* klass = obj->AsClass();
if (!image_writer->IsImageClass(klass)) {
image_writer->DumpImageClasses();
- CHECK(image_writer->IsImageClass(klass)) << ClassHelper(klass).GetDescriptor()
+ CHECK(image_writer->IsImageClass(klass)) << klass->GetDescriptor()
<< " " << PrettyDescriptor(klass);
}
}
@@ -757,7 +759,8 @@
uintptr_t value = quick_code - patch_location + patch->RelativeOffset();
SetPatchLocation(patch, value);
} else {
- if (quick_code == reinterpret_cast<uintptr_t>(GetQuickToInterpreterBridge())) {
+ if (quick_code == reinterpret_cast<uintptr_t>(GetQuickToInterpreterBridge()) ||
+ quick_code == reinterpret_cast<uintptr_t>(class_linker->GetQuickGenericJniTrampoline())) {
if (target->IsNative()) {
// generic JNI, not interpreter bridge from GetQuickOatCodeFor().
code_offset = quick_generic_jni_trampoline_offset_;
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 2c2564d..521992a 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -499,6 +499,7 @@
break;
}
+ case Instruction::MOVE_RESULT:
case Instruction::MOVE_RESULT_WIDE: {
UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
break;
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
index b9c1164..52e3e37 100644
--- a/compiler/optimizing/graph_visualizer.cc
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -18,6 +18,7 @@
#include "driver/dex_compilation_unit.h"
#include "nodes.h"
+#include "ssa_liveness_analysis.h"
namespace art {
@@ -102,6 +103,24 @@
}
output_ << "]";
}
+ if (instruction->GetLifetimePosition() != kNoLifetime) {
+ output_ << " (liveness: " << instruction->GetLifetimePosition();
+ if (instruction->HasLiveInterval()) {
+ output_ << " ";
+ const GrowableArray<LiveRange>& ranges = instruction->GetLiveInterval()->GetRanges();
+ size_t i = ranges.Size() - 1;
+ do {
+ output_ << "[" << ranges.Get(i).GetStart() << "," << ranges.Get(i).GetEnd() << "[";
+ if (i == 0) {
+ break;
+ } else {
+ --i;
+ output_ << ",";
+ }
+ } while (true);
+ }
+ output_ << ")";
+ }
}
void PrintInstructions(const HInstructionList& list) {
@@ -126,8 +145,14 @@
void VisitBasicBlock(HBasicBlock* block) {
StartTag("block");
PrintProperty("name", "B", block->GetBlockId());
- PrintInt("from_bci", -1);
- PrintInt("to_bci", -1);
+ if (block->GetLifetimeStart() != kNoLifetime) {
+ // Piggy back on these fields to show the lifetime of the block.
+ PrintInt("from_bci", block->GetLifetimeStart());
+ PrintInt("to_bci", block->GetLifetimeEnd());
+ } else {
+ PrintInt("from_bci", -1);
+ PrintInt("to_bci", -1);
+ }
PrintPredecessors(block);
PrintSuccessors(block);
PrintEmptyProperty("xhandlers");
diff --git a/compiler/optimizing/live_ranges_test.cc b/compiler/optimizing/live_ranges_test.cc
new file mode 100644
index 0000000..9849388
--- /dev/null
+++ b/compiler/optimizing/live_ranges_test.cc
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "builder.h"
+#include "dex_file.h"
+#include "dex_instruction.h"
+#include "nodes.h"
+#include "optimizing_unit_test.h"
+#include "ssa_liveness_analysis.h"
+#include "utils/arena_allocator.h"
+
+#include "gtest/gtest.h"
+
+namespace art {
+
+static HGraph* BuildGraph(const uint16_t* data, ArenaAllocator* allocator) {
+ HGraphBuilder builder(allocator);
+ const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
+ HGraph* graph = builder.BuildGraph(*item);
+ graph->BuildDominatorTree();
+ graph->TransformToSSA();
+ graph->FindNaturalLoops();
+ return graph;
+}
+
+TEST(LiveRangesTest, CFG1) {
+ /*
+ * Test the following snippet:
+ * return 0;
+ *
+ * Which becomes the following graph (numbered by lifetime position):
+ * 2: constant0
+ * 3: goto
+ * |
+ * 6: return
+ * |
+ * 9: exit
+ */
+ const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
+ Instruction::CONST_4 | 0 | 0,
+ Instruction::RETURN);
+
+ ArenaPool pool;
+ ArenaAllocator allocator(&pool);
+ HGraph* graph = BuildGraph(data, &allocator);
+ SsaLivenessAnalysis liveness(*graph);
+ liveness.Analyze();
+
+ LiveInterval* interval = liveness.GetInstructionFromSsaIndex(0)->GetLiveInterval();
+ ASSERT_EQ(1u, interval->GetRanges().Size());
+ LiveRange range = interval->GetRanges().Get(0);
+ ASSERT_EQ(2u, range.GetStart());
+ // Last use is the return instruction.
+ ASSERT_EQ(6u, range.GetEnd());
+ HBasicBlock* block = graph->GetBlocks().Get(1);
+ ASSERT_TRUE(block->GetLastInstruction()->AsReturn() != nullptr);
+ ASSERT_EQ(6u, block->GetLastInstruction()->GetLifetimePosition());
+}
+
+TEST(LiveRangesTest, CFG2) {
+ /*
+ * Test the following snippet:
+ * var a = 0;
+ * if (0 == 0) {
+ * } else {
+ * }
+ * return a;
+ *
+ * Which becomes the following graph (numbered by lifetime position):
+ * 2: constant0
+ * 3: goto
+ * |
+ * 6: equal
+ * 7: if
+ * / \
+ * 10: goto 13: goto
+ * \ /
+ * 16: return
+ * |
+ * 19: exit
+ */
+ const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
+ Instruction::CONST_4 | 0 | 0,
+ Instruction::IF_EQ, 3,
+ Instruction::GOTO | 0x100,
+ Instruction::RETURN | 0 << 8);
+
+ ArenaPool pool;
+ ArenaAllocator allocator(&pool);
+ HGraph* graph = BuildGraph(data, &allocator);
+ SsaLivenessAnalysis liveness(*graph);
+ liveness.Analyze();
+
+ LiveInterval* interval = liveness.GetInstructionFromSsaIndex(0)->GetLiveInterval();
+ ASSERT_EQ(1u, interval->GetRanges().Size());
+ LiveRange range = interval->GetRanges().Get(0);
+ ASSERT_EQ(2u, range.GetStart());
+ // Last use is the return instruction.
+ ASSERT_EQ(16u, range.GetEnd());
+ HBasicBlock* block = graph->GetBlocks().Get(3);
+ ASSERT_TRUE(block->GetLastInstruction()->AsReturn() != nullptr);
+ ASSERT_EQ(16u, block->GetLastInstruction()->GetLifetimePosition());
+}
+
+TEST(LiveRangesTest, CFG3) {
+ /*
+ * Test the following snippet:
+ * var a = 0;
+ * if (0 == 0) {
+ * } else {
+ * a = 4;
+ * }
+ * return a;
+ *
+ * Which becomes the following graph (numbered by lifetime position):
+ * 2: constant0
+ * 3: constant4
+ * 4: goto
+ * |
+ * 7: equal
+ * 8: if
+ * / \
+ * 11: goto 14: goto
+ * \ /
+ * 16: phi
+ * 17: return
+ * |
+ * 20: exit
+ */
+ const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
+ Instruction::CONST_4 | 0 | 0,
+ Instruction::IF_EQ, 3,
+ Instruction::CONST_4 | 4 << 12 | 0,
+ Instruction::RETURN | 0 << 8);
+
+ ArenaPool pool;
+ ArenaAllocator allocator(&pool);
+ HGraph* graph = BuildGraph(data, &allocator);
+ SsaLivenessAnalysis liveness(*graph);
+ liveness.Analyze();
+
+ // Test for the 0 constant.
+ LiveInterval* interval = liveness.GetInstructionFromSsaIndex(0)->GetLiveInterval();
+ ASSERT_EQ(1u, interval->GetRanges().Size());
+ LiveRange range = interval->GetRanges().Get(0);
+ ASSERT_EQ(2u, range.GetStart());
+ // Last use is the phi at the return block so instruction is live until
+ // the end of the then block.
+ ASSERT_EQ(12u, range.GetEnd());
+
+ // Test for the 4 constant.
+ interval = liveness.GetInstructionFromSsaIndex(1)->GetLiveInterval();
+ // The then branch is a hole for this constant, therefore its interval has 2 ranges.
+ ASSERT_EQ(2u, interval->GetRanges().Size());
+ // First range is the else block.
+ range = interval->GetRanges().Get(0);
+ ASSERT_EQ(13u, range.GetStart());
+ // Last use is the phi at the return block.
+ ASSERT_EQ(15u, range.GetEnd());
+ // Second range starts from the definition and ends at the if block.
+ range = interval->GetRanges().Get(1);
+ ASSERT_EQ(3u, range.GetStart());
+ // 9 is the end of the if block.
+ ASSERT_EQ(9u, range.GetEnd());
+
+ // Test for the phi.
+ interval = liveness.GetInstructionFromSsaIndex(3)->GetLiveInterval();
+ ASSERT_EQ(1u, interval->GetRanges().Size());
+ range = interval->GetRanges().Get(0);
+ ASSERT_EQ(16u, range.GetStart());
+ ASSERT_EQ(17u, range.GetEnd());
+}
+
+TEST(LiveRangesTest, Loop) {
+ /*
+ * Test the following snippet:
+ * var a = 0;
+ * while (a == a) {
+ * a = 4;
+ * }
+ * return 5;
+ *
+ * Which becomes the following graph (numbered by lifetime position):
+ * 2: constant0
+ * 3: constant4
+ * 4: constant5
+ * 5: goto
+ * |
+ * 8: goto
+ * |
+ * 10: phi
+ * 11: equal
+ * 12: if +++++
+ * | \ +
+ * | 15: goto
+ * |
+ * 18: return
+ * |
+ * 21: exit
+ */
+
+ const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
+ Instruction::CONST_4 | 0 | 0,
+ Instruction::IF_EQ, 4,
+ Instruction::CONST_4 | 4 << 12 | 0,
+ Instruction::GOTO | 0xFD00,
+ Instruction::CONST_4 | 5 << 12 | 1 << 8,
+ Instruction::RETURN | 1 << 8);
+
+ ArenaPool pool;
+ ArenaAllocator allocator(&pool);
+ HGraph* graph = BuildGraph(data, &allocator);
+ SsaLivenessAnalysis liveness(*graph);
+ liveness.Analyze();
+
+ // Test for the 0 constant.
+ LiveInterval* interval = liveness.GetInstructionFromSsaIndex(0)->GetLiveInterval();
+ ASSERT_EQ(1u, interval->GetRanges().Size());
+ LiveRange range = interval->GetRanges().Get(0);
+ ASSERT_EQ(2u, range.GetStart());
+ // Last use is the loop phi so instruction is live until
+ // the end of the pre loop header.
+ ASSERT_EQ(9u, range.GetEnd());
+
+ // Test for the 4 constant.
+ interval = liveness.GetInstructionFromSsaIndex(1)->GetLiveInterval();
+ // The instruction is live until the end of the loop.
+ ASSERT_EQ(1u, interval->GetRanges().Size());
+ range = interval->GetRanges().Get(0);
+ ASSERT_EQ(3u, range.GetStart());
+ ASSERT_EQ(16u, range.GetEnd());
+
+ // Test for the 5 constant.
+ interval = liveness.GetInstructionFromSsaIndex(2)->GetLiveInterval();
+ // The instruction is live until the return instruction of the loop.
+ ASSERT_EQ(1u, interval->GetRanges().Size());
+ range = interval->GetRanges().Get(0);
+ ASSERT_EQ(4u, range.GetStart());
+ ASSERT_EQ(18u, range.GetEnd());
+
+ // Test for the phi.
+ interval = liveness.GetInstructionFromSsaIndex(3)->GetLiveInterval();
+ ASSERT_EQ(1u, interval->GetRanges().Size());
+ range = interval->GetRanges().Get(0);
+ // Instruction is consumed by the if.
+ ASSERT_EQ(10u, range.GetStart());
+ ASSERT_EQ(11u, range.GetEnd());
+}
+
+} // namespace art
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 1085c10..a2cb1c4 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -29,6 +29,7 @@
class HIntConstant;
class HGraphVisitor;
class HPhi;
+class LiveInterval;
class LocationSummary;
static const int kDefaultNumberOfBlocks = 8;
@@ -223,6 +224,8 @@
DISALLOW_COPY_AND_ASSIGN(HLoopInformation);
};
+static constexpr size_t kNoLifetime = -1;
+
// A block in a method. Contains the list of instructions represented
// as a double linked list. Each block knows its predecessors and
// successors.
@@ -234,7 +237,9 @@
successors_(graph->GetArena(), kDefaultNumberOfSuccessors),
loop_information_(nullptr),
dominator_(nullptr),
- block_id_(-1) { }
+ block_id_(-1),
+ lifetime_start_(kNoLifetime),
+ lifetime_end_(kNoLifetime) {}
const GrowableArray<HBasicBlock*>& GetPredecessors() const {
return predecessors_;
@@ -299,6 +304,15 @@
block->successors_.Add(this);
}
+ size_t GetPredecessorIndexOf(HBasicBlock* predecessor) {
+ for (size_t i = 0, e = predecessors_.Size(); i < e; ++i) {
+ if (predecessors_.Get(i) == predecessor) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
void AddInstruction(HInstruction* instruction);
void RemoveInstruction(HInstruction* instruction);
void AddPhi(HPhi* phi);
@@ -334,6 +348,12 @@
// Returns wheter this block dominates the blocked passed as parameter.
bool Dominates(HBasicBlock* block) const;
+ size_t GetLifetimeStart() const { return lifetime_start_; }
+ size_t GetLifetimeEnd() const { return lifetime_end_; }
+
+ void SetLifetimeStart(size_t start) { lifetime_start_ = start; }
+ void SetLifetimeEnd(size_t end) { lifetime_end_ = end; }
+
private:
HGraph* const graph_;
GrowableArray<HBasicBlock*> predecessors_;
@@ -343,6 +363,8 @@
HLoopInformation* loop_information_;
HBasicBlock* dominator_;
int block_id_;
+ size_t lifetime_start_;
+ size_t lifetime_end_;
DISALLOW_COPY_AND_ASSIGN(HBasicBlock);
};
@@ -407,7 +429,9 @@
uses_(nullptr),
env_uses_(nullptr),
environment_(nullptr),
- locations_(nullptr) { }
+ locations_(nullptr),
+ live_interval_(nullptr),
+ lifetime_position_(kNoLifetime) {}
virtual ~HInstruction() { }
@@ -477,6 +501,12 @@
FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
#undef INSTRUCTION_TYPE_CHECK
+ size_t GetLifetimePosition() const { return lifetime_position_; }
+ void SetLifetimePosition(size_t position) { lifetime_position_ = position; }
+ LiveInterval* GetLiveInterval() const { return live_interval_; }
+ void SetLiveInterval(LiveInterval* interval) { live_interval_ = interval; }
+ bool HasLiveInterval() const { return live_interval_ != nullptr; }
+
private:
HInstruction* previous_;
HInstruction* next_;
@@ -501,6 +531,13 @@
// Set by the code generator.
LocationSummary* locations_;
+ // Set by the liveness analysis.
+ LiveInterval* live_interval_;
+
+ // Set by the liveness analysis, this is the position in a linear
+ // order of blocks where this instruction's live interval start.
+ size_t lifetime_position_;
+
friend class HBasicBlock;
friend class HInstructionList;
@@ -596,6 +633,8 @@
private:
HInstruction* instruction_;
HInstruction* next_;
+
+ DISALLOW_COPY_AND_ASSIGN(HInstructionIterator);
};
class HBackwardInstructionIterator : public ValueObject {
@@ -615,6 +654,8 @@
private:
HInstruction* instruction_;
HInstruction* next_;
+
+ DISALLOW_COPY_AND_ASSIGN(HBackwardInstructionIterator);
};
// An embedded container with N elements of type T. Used (with partial
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index f435cb0..286f48a 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -129,6 +129,7 @@
graph->FindNaturalLoops();
SsaLivenessAnalysis(*graph).Analyze();
+ visualizer.DumpGraph("liveness");
return new CompiledMethod(GetCompilerDriver(),
instruction_set,
diff --git a/compiler/optimizing/ssa_liveness_analysis.cc b/compiler/optimizing/ssa_liveness_analysis.cc
index 85171aa..0f16ad2 100644
--- a/compiler/optimizing/ssa_liveness_analysis.cc
+++ b/compiler/optimizing/ssa_liveness_analysis.cc
@@ -22,7 +22,7 @@
void SsaLivenessAnalysis::Analyze() {
LinearizeGraph();
NumberInstructions();
- ComputeSets();
+ ComputeLiveness();
}
static bool IsLoopExit(HLoopInformation* current, HLoopInformation* to) {
@@ -96,6 +96,22 @@
DISALLOW_COPY_AND_ASSIGN(HLinearOrderIterator);
};
+class HLinearPostOrderIterator : public ValueObject {
+ public:
+ explicit HLinearPostOrderIterator(const GrowableArray<HBasicBlock*>& post_order)
+ : post_order_(post_order), index_(0) {}
+
+ bool Done() const { return index_ == post_order_.Size(); }
+ HBasicBlock* Current() const { return post_order_.Get(index_); }
+ void Advance() { ++index_; }
+
+ private:
+ const GrowableArray<HBasicBlock*>& post_order_;
+ size_t index_;
+
+ DISALLOW_COPY_AND_ASSIGN(HLinearPostOrderIterator);
+};
+
void SsaLivenessAnalysis::LinearizeGraph() {
// For simplicity of the implementation, we create post linear order. The order for
// computing live ranges is the reverse of that order.
@@ -105,27 +121,41 @@
void SsaLivenessAnalysis::NumberInstructions() {
int ssa_index = 0;
+ size_t lifetime_position = 0;
+ // Each instruction gets an individual lifetime position, and a block gets a lifetime
+ // start and end position. Non-phi instructions have a distinct lifetime position than
+ // the block they are in. Phi instructions have the lifetime start of their block as
+ // lifetime position
for (HLinearOrderIterator it(linear_post_order_); !it.Done(); it.Advance()) {
HBasicBlock* block = it.Current();
+ block->SetLifetimeStart(++lifetime_position);
for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
HInstruction* current = it.Current();
if (current->HasUses()) {
+ instructions_from_ssa_index_.Add(current);
current->SetSsaIndex(ssa_index++);
+ current->SetLiveInterval(new (graph_.GetArena()) LiveInterval(graph_.GetArena()));
}
+ current->SetLifetimePosition(lifetime_position);
}
for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
HInstruction* current = it.Current();
if (current->HasUses()) {
+ instructions_from_ssa_index_.Add(current);
current->SetSsaIndex(ssa_index++);
+ current->SetLiveInterval(new (graph_.GetArena()) LiveInterval(graph_.GetArena()));
}
+ current->SetLifetimePosition(++lifetime_position);
}
+
+ block->SetLifetimeEnd(++lifetime_position);
}
number_of_ssa_values_ = ssa_index;
}
-void SsaLivenessAnalysis::ComputeSets() {
+void SsaLivenessAnalysis::ComputeLiveness() {
for (HLinearOrderIterator it(linear_post_order_); !it.Done(); it.Advance()) {
HBasicBlock* block = it.Current();
block_infos_.Put(
@@ -133,9 +163,10 @@
new (graph_.GetArena()) BlockInfo(graph_.GetArena(), *block, number_of_ssa_values_));
}
- // Compute the initial live_in, live_out, and kill sets. This method does not handle
- // backward branches, therefore live_in and live_out sets are not yet correct.
- ComputeInitialSets();
+ // Compute the live ranges, as well as the initial live_in, live_out, and kill sets.
+ // This method does not handle backward branches for the sets, therefore live_in
+ // and live_out sets are not yet correct.
+ ComputeLiveRanges();
// Do a fixed point calculation to take into account backward branches,
// that will update live_in of loop headers, and therefore live_out and live_in
@@ -143,26 +174,71 @@
ComputeLiveInAndLiveOutSets();
}
-void SsaLivenessAnalysis::ComputeInitialSets() {
- // Do a post orderr visit, adding inputs of instructions live in the block where
+class InstructionBitVectorIterator : public ValueObject {
+ public:
+ InstructionBitVectorIterator(const BitVector& vector,
+ const GrowableArray<HInstruction*>& instructions)
+ : instructions_(instructions),
+ iterator_(BitVector::Iterator(&vector)),
+ current_bit_index_(iterator_.Next()) {}
+
+ bool Done() const { return current_bit_index_ == -1; }
+ HInstruction* Current() const { return instructions_.Get(current_bit_index_); }
+ void Advance() {
+ current_bit_index_ = iterator_.Next();
+ }
+
+ private:
+ const GrowableArray<HInstruction*> instructions_;
+ BitVector::Iterator iterator_;
+ int32_t current_bit_index_;
+
+ DISALLOW_COPY_AND_ASSIGN(InstructionBitVectorIterator);
+};
+
+void SsaLivenessAnalysis::ComputeLiveRanges() {
+ // Do a post order visit, adding inputs of instructions live in the block where
// that instruction is defined, and killing instructions that are being visited.
- for (HPostOrderIterator it(graph_); !it.Done(); it.Advance()) {
+ for (HLinearPostOrderIterator it(linear_post_order_); !it.Done(); it.Advance()) {
HBasicBlock* block = it.Current();
BitVector* kill = GetKillSet(*block);
BitVector* live_in = GetLiveInSet(*block);
+ // Set phi inputs of successors of this block corresponding to this block
+ // as live_in.
+ for (size_t i = 0, e = block->GetSuccessors().Size(); i < e; ++i) {
+ HBasicBlock* successor = block->GetSuccessors().Get(i);
+ live_in->Union(GetLiveInSet(*successor));
+ size_t phi_input_index = successor->GetPredecessorIndexOf(block);
+ for (HInstructionIterator it(successor->GetPhis()); !it.Done(); it.Advance()) {
+ HInstruction* input = it.Current()->InputAt(phi_input_index);
+ live_in->SetBit(input->GetSsaIndex());
+ }
+ }
+
+ // Add a range that covers this block to all instructions live_in because of successors.
+ for (InstructionBitVectorIterator it(*live_in, instructions_from_ssa_index_);
+ !it.Done();
+ it.Advance()) {
+ it.Current()->GetLiveInterval()->AddRange(block->GetLifetimeStart(), block->GetLifetimeEnd());
+ }
+
for (HBackwardInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
HInstruction* current = it.Current();
if (current->HasSsaIndex()) {
+ // Kill the instruction and shorten its interval.
kill->SetBit(current->GetSsaIndex());
live_in->ClearBit(current->GetSsaIndex());
+ current->GetLiveInterval()->SetFrom(current->GetLifetimePosition());
}
// All inputs of an instruction must be live.
for (size_t i = 0, e = current->InputCount(); i < e; ++i) {
- DCHECK(current->InputAt(i)->HasSsaIndex());
- live_in->SetBit(current->InputAt(i)->GetSsaIndex());
+ HInstruction* input = current->InputAt(i);
+ DCHECK(input->HasSsaIndex());
+ live_in->SetBit(input->GetSsaIndex());
+ input->GetLiveInterval()->AddUse(current);
}
if (current->HasEnvironment()) {
@@ -173,32 +249,30 @@
if (instruction != nullptr) {
DCHECK(instruction->HasSsaIndex());
live_in->SetBit(instruction->GetSsaIndex());
+ instruction->GetLiveInterval()->AddUse(current);
}
}
}
}
+ // Kill phis defined in this block.
for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
HInstruction* current = it.Current();
if (current->HasSsaIndex()) {
kill->SetBit(current->GetSsaIndex());
live_in->ClearBit(current->GetSsaIndex());
}
+ }
- // Mark a phi input live_in for its corresponding predecessor.
- for (size_t i = 0, e = current->InputCount(); i < e; ++i) {
- HInstruction* input = current->InputAt(i);
-
- HBasicBlock* predecessor = block->GetPredecessors().Get(i);
- size_t ssa_index = input->GetSsaIndex();
- BitVector* predecessor_kill = GetKillSet(*predecessor);
- BitVector* predecessor_live_in = GetLiveInSet(*predecessor);
-
- // Phi inputs from a back edge have already been visited. If the back edge
- // block defines that input, we should not add it to its live_in.
- if (!predecessor_kill->IsBitSet(ssa_index)) {
- predecessor_live_in->SetBit(ssa_index);
- }
+ if (block->IsLoopHeader()) {
+ HBasicBlock* back_edge = block->GetLoopInformation()->GetBackEdges().Get(0);
+ // For all live_in instructions at the loop header, we need to create a range
+ // that covers the full loop.
+ for (InstructionBitVectorIterator it(*live_in, instructions_from_ssa_index_);
+ !it.Done();
+ it.Advance()) {
+ it.Current()->GetLiveInterval()->AddLoopRange(block->GetLifetimeStart(),
+ back_edge->GetLifetimeEnd());
}
}
}
diff --git a/compiler/optimizing/ssa_liveness_analysis.h b/compiler/optimizing/ssa_liveness_analysis.h
index b8695ba..2d91436 100644
--- a/compiler/optimizing/ssa_liveness_analysis.h
+++ b/compiler/optimizing/ssa_liveness_analysis.h
@@ -44,12 +44,104 @@
DISALLOW_COPY_AND_ASSIGN(BlockInfo);
};
+/**
+ * A live range contains the start and end of a range where an instruction
+ * is live.
+ */
+class LiveRange : public ValueObject {
+ public:
+ LiveRange(size_t start, size_t end) : start_(start), end_(end) {
+ DCHECK_LT(start, end);
+ }
+
+ size_t GetStart() const { return start_; }
+ size_t GetEnd() const { return end_; }
+
+ private:
+ size_t start_;
+ size_t end_;
+};
+
+static constexpr int kDefaultNumberOfRanges = 3;
+
+/**
+ * An interval is a list of disjoint live ranges where an instruction is live.
+ * Each instruction that has uses gets an interval.
+ */
+class LiveInterval : public ArenaObject {
+ public:
+ explicit LiveInterval(ArenaAllocator* allocator) : ranges_(allocator, kDefaultNumberOfRanges) {}
+
+ void AddUse(HInstruction* instruction) {
+ size_t position = instruction->GetLifetimePosition();
+ size_t start_block_position = instruction->GetBlock()->GetLifetimeStart();
+ size_t end_block_position = instruction->GetBlock()->GetLifetimeEnd();
+ if (ranges_.IsEmpty()) {
+ // First time we see a use of that interval.
+ ranges_.Add(LiveRange(start_block_position, position));
+ } else if (ranges_.Peek().GetStart() == start_block_position) {
+ // There is a use later in the same block.
+ DCHECK_LE(position, ranges_.Peek().GetEnd());
+ } else if (ranges_.Peek().GetStart() == end_block_position + 1) {
+ // Last use is in a following block.
+ LiveRange existing = ranges_.Pop();
+ ranges_.Add(LiveRange(start_block_position, existing.GetEnd()));
+ } else {
+ // There is a hole in the interval. Create a new range.
+ ranges_.Add(LiveRange(start_block_position, position));
+ }
+ }
+
+ void AddRange(size_t start, size_t end) {
+ if (ranges_.IsEmpty()) {
+ ranges_.Add(LiveRange(start, end));
+ } else if (ranges_.Peek().GetStart() == end + 1) {
+ // There is a use in the following block.
+ LiveRange existing = ranges_.Pop();
+ ranges_.Add(LiveRange(start, existing.GetEnd()));
+ } else {
+ // There is a hole in the interval. Create a new range.
+ ranges_.Add(LiveRange(start, end));
+ }
+ }
+
+ void AddLoopRange(size_t start, size_t end) {
+ DCHECK(!ranges_.IsEmpty());
+ while (!ranges_.IsEmpty() && ranges_.Peek().GetEnd() < end) {
+ DCHECK_LE(start, ranges_.Peek().GetStart());
+ ranges_.Pop();
+ }
+ if (ranges_.IsEmpty()) {
+ // Uses are only in the loop.
+ ranges_.Add(LiveRange(start, end));
+ } else {
+ // There are uses after the loop.
+ LiveRange range = ranges_.Pop();
+ ranges_.Add(LiveRange(start, range.GetEnd()));
+ }
+ }
+
+ void SetFrom(size_t from) {
+ DCHECK(!ranges_.IsEmpty());
+ LiveRange existing = ranges_.Pop();
+ ranges_.Add(LiveRange(from, existing.GetEnd()));
+ }
+
+ const GrowableArray<LiveRange>& GetRanges() const { return ranges_; }
+
+ private:
+ GrowableArray<LiveRange> ranges_;
+
+ DISALLOW_COPY_AND_ASSIGN(LiveInterval);
+};
+
class SsaLivenessAnalysis : public ValueObject {
public:
explicit SsaLivenessAnalysis(const HGraph& graph)
: graph_(graph),
linear_post_order_(graph.GetArena(), graph.GetBlocks().Size()),
block_infos_(graph.GetArena(), graph.GetBlocks().Size()),
+ instructions_from_ssa_index_(graph.GetArena(), 0),
number_of_ssa_values_(0) {
block_infos_.SetSize(graph.GetBlocks().Size());
}
@@ -72,6 +164,10 @@
return linear_post_order_;
}
+ HInstruction* GetInstructionFromSsaIndex(size_t index) {
+ return instructions_from_ssa_index_.Get(index);
+ }
+
private:
// Linearize the graph so that:
// (1): a block is always after its dominator,
@@ -79,15 +175,16 @@
// This creates a natural and efficient ordering when visualizing live ranges.
void LinearizeGraph();
- // Give an SSA number to each instruction that defines a value used by another instruction.
+ // Give an SSA number to each instruction that defines a value used by another instruction,
+ // and setup the lifetime information of each instruction and block.
void NumberInstructions();
- // Compute live_in, live_out and kill sets.
- void ComputeSets();
+ // Compute live ranges of instructions, as well as live_in, live_out and kill sets.
+ void ComputeLiveness();
- // Compute the initial live_in, live_out and kill sets, without analyzing
- // backward branches.
- void ComputeInitialSets();
+ // Compute the live ranges of instructions, as well as the initial live_in, live_out and
+ // kill sets, that do not take into account backward branches.
+ void ComputeLiveRanges();
// After computing the initial sets, this method does a fixed point
// calculation over the live_in and live_out set to take into account
@@ -103,6 +200,7 @@
const HGraph& graph_;
GrowableArray<HBasicBlock*> linear_post_order_;
GrowableArray<BlockInfo*> block_infos_;
+ GrowableArray<HInstruction*> instructions_from_ssa_index_;
size_t number_of_ssa_values_;
DISALLOW_COPY_AND_ASSIGN(SsaLivenessAnalysis);
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index fef25e0..aaf9ed5 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -1147,7 +1147,7 @@
state->stats_.ComputeOutliers(total_size, expansion, method);
}
}
- state->stats_.Update(ClassHelper(obj_class).GetDescriptor(), object_bytes);
+ state->stats_.Update(obj_class->GetDescriptor().c_str(), object_bytes);
}
std::set<const void*> already_seen_;
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index ce634e0..ac86014 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -49,7 +49,7 @@
}
DCHECK(!element_class->IsPrimitiveVoid());
std::string descriptor("[");
- descriptor += ClassHelper(element_class).GetDescriptor();
+ descriptor += element_class->GetDescriptor();
StackHandleScope<1> hs(Thread::Current());
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(element_class->GetClassLoader()));
mirror::Class* array_class = FindClass(self, descriptor.c_str(), class_loader);
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 54532b4..3c620de 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -96,8 +96,8 @@
ThrowLocation throw_location = self->GetCurrentLocationForThrow();
if (c->GetVerifyErrorClass() != NULL) {
// TODO: change the verifier to store an _instance_, with a useful detail message?
- ClassHelper ve_ch(c->GetVerifyErrorClass());
- self->ThrowNewException(throw_location, ve_ch.GetDescriptor(), PrettyDescriptor(c).c_str());
+ self->ThrowNewException(throw_location, c->GetVerifyErrorClass()->GetDescriptor().c_str(),
+ PrettyDescriptor(c).c_str());
} else {
self->ThrowNewException(throw_location, "Ljava/lang/NoClassDefFoundError;",
PrettyDescriptor(c).c_str());
@@ -191,6 +191,9 @@
memset(find_array_class_cache_, 0, kFindArrayCacheSize * sizeof(mirror::Class*));
}
+// To set a value for generic JNI. May be necessary in compiler tests.
+extern "C" void art_quick_generic_jni_trampoline(mirror::ArtMethod*);
+
void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class_path) {
VLOG(startup) << "ClassLinker::Init";
CHECK(Runtime::Current()->IsCompiler());
@@ -343,6 +346,10 @@
runtime->SetImtConflictMethod(runtime->CreateImtConflictMethod());
runtime->SetDefaultImt(runtime->CreateDefaultImt(this));
+ // Set up GenericJNI entrypoint. That is mainly a hack for common_compiler_test.h so that
+ // we do not need friend classes or a publicly exposed setter.
+ quick_generic_jni_trampoline_ = reinterpret_cast<void*>(art_quick_generic_jni_trampoline);
+
// Object, String and DexCache need to be rerun through FindSystemClass to finish init
java_lang_Object->SetStatus(mirror::Class::kStatusNotReady, self);
mirror::Class* Object_class = FindSystemClass(self, "Ljava/lang/Object;");
@@ -400,12 +407,10 @@
array_iftable_->SetInterface(1, java_io_Serializable);
// Sanity check Class[] and Object[]'s interfaces.
- ClassHelper kh(class_array_class.Get());
- CHECK_EQ(java_lang_Cloneable, kh.GetDirectInterface(0));
- CHECK_EQ(java_io_Serializable, kh.GetDirectInterface(1));
- kh.ChangeClass(object_array_class.Get());
- CHECK_EQ(java_lang_Cloneable, kh.GetDirectInterface(0));
- CHECK_EQ(java_io_Serializable, kh.GetDirectInterface(1));
+ CHECK_EQ(java_lang_Cloneable, mirror::Class::GetDirectInterface(self, class_array_class, 0));
+ CHECK_EQ(java_io_Serializable, mirror::Class::GetDirectInterface(self, class_array_class, 1));
+ CHECK_EQ(java_lang_Cloneable, mirror::Class::GetDirectInterface(self, object_array_class, 0));
+ CHECK_EQ(java_io_Serializable, mirror::Class::GetDirectInterface(self, object_array_class, 1));
// Run Class, ArtField, and ArtMethod through FindSystemClass. This initializes their
// dex_cache_ fields and register them in class_table_.
mirror::Class* Class_class = FindSystemClass(self, "Ljava/lang/Class;");
@@ -1724,9 +1729,8 @@
if (!runtime->IsStarted() || runtime->UseCompileTimeClassPath()) {
return; // OAT file unavailable.
}
- ClassHelper kh(klass);
- const DexFile& dex_file = kh.GetDexFile();
- const DexFile::ClassDef* dex_class_def = kh.GetClassDef();
+ const DexFile& dex_file = klass->GetDexFile();
+ const DexFile::ClassDef* dex_class_def = klass->GetClassDef();
CHECK(dex_class_def != nullptr);
const byte* class_data = dex_file.GetClassData(*dex_class_def);
// There should always be class data if there were direct methods.
@@ -1777,9 +1781,10 @@
// Ignore virtual methods on the iterator.
}
-static void LinkCode(const Handle<mirror::ArtMethod>& method, const OatFile::OatClass* oat_class,
- const DexFile& dex_file, uint32_t dex_method_index, uint32_t method_index)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+void ClassLinker::LinkCode(const Handle<mirror::ArtMethod>& method,
+ const OatFile::OatClass* oat_class,
+ const DexFile& dex_file, uint32_t dex_method_index,
+ uint32_t method_index) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Method shouldn't have already been linked.
DCHECK(method->GetEntryPointFromQuickCompiledCode() == nullptr);
DCHECK(method->GetEntryPointFromPortableCompiledCode() == nullptr);
@@ -1810,8 +1815,8 @@
// For static methods excluding the class initializer, install the trampoline.
// It will be replaced by the proper entry point by ClassLinker::FixupStaticTrampolines
// after initializing class (see ClassLinker::InitializeClass method).
- method->SetEntryPointFromQuickCompiledCode(GetQuickResolutionTrampoline(runtime->GetClassLinker()));
- method->SetEntryPointFromPortableCompiledCode(GetPortableResolutionTrampoline(runtime->GetClassLinker()));
+ method->SetEntryPointFromQuickCompiledCode(GetQuickResolutionTrampoline());
+ method->SetEntryPointFromPortableCompiledCode(GetPortableResolutionTrampoline());
} else if (enter_interpreter) {
if (!method->IsNative()) {
// Set entry point from compiled code if there's no code or in interpreter only mode.
@@ -1837,8 +1842,7 @@
if (enter_interpreter) {
// We have a native method here without code. Then it should have either the GenericJni
// trampoline as entrypoint (non-static), or the Resolution trampoline (static).
- DCHECK(method->GetEntryPointFromQuickCompiledCode() ==
- GetQuickResolutionTrampoline(runtime->GetClassLinker())
+ DCHECK(method->GetEntryPointFromQuickCompiledCode() == GetQuickResolutionTrampoline()
|| method->GetEntryPointFromQuickCompiledCode() == GetQuickGenericJniTrampoline());
}
}
@@ -2028,15 +2032,14 @@
if (klass->GetClassLoader() != NULL) { // All non-boot finalizer methods are flagged
klass->SetFinalizable();
} else {
- ClassHelper kh(klass.Get());
- const char* klass_descriptor = kh.GetDescriptor();
+ std::string klass_descriptor = klass->GetDescriptor();
// The Enum class declares a "final" finalize() method to prevent subclasses from
// introducing a finalizer. We don't want to set the finalizable flag for Enum or its
// subclasses, so we exclude it here.
// We also want to avoid setting the flag on Object, where we know that finalize() is
// empty.
- if ((strcmp("Ljava/lang/Object;", klass_descriptor) != 0) &&
- (strcmp("Ljava/lang/Enum;", klass_descriptor) != 0)) {
+ if (klass_descriptor.compare("Ljava/lang/Object;") != 0 &&
+ klass_descriptor.compare("Ljava/lang/Enum;") != 0) {
klass->SetFinalizable();
}
}
@@ -2397,9 +2400,7 @@
for (auto it = class_table_.lower_bound(hash), end = class_table_.end(); it != end && it->first == hash;
++it) {
mirror::Class* klass = it->second;
- ClassHelper kh(klass);
- if ((klass->GetClassLoader() == class_loader) &&
- (strcmp(descriptor, kh.GetDescriptor()) == 0)) {
+ if (klass->GetClassLoader() == class_loader && descriptor == klass->GetDescriptor()) {
class_table_.erase(it);
return true;
}
@@ -2443,16 +2444,13 @@
auto end = class_table_.end();
for (auto it = class_table_.lower_bound(hash); it != end && it->first == hash; ++it) {
mirror::Class* klass = it->second;
- ClassHelper kh(klass);
- if ((klass->GetClassLoader() == class_loader) &&
- (strcmp(descriptor, kh.GetDescriptor()) == 0)) {
+ if (klass->GetClassLoader() == class_loader && descriptor == klass->GetDescriptor()) {
if (kIsDebugBuild) {
// Check for duplicates in the table.
for (++it; it != end && it->first == hash; ++it) {
mirror::Class* klass2 = it->second;
- ClassHelper kh(klass2);
CHECK(!((klass2->GetClassLoader() == class_loader) &&
- (strcmp(descriptor, kh.GetDescriptor()) == 0)))
+ descriptor == klass2->GetDescriptor()))
<< PrettyClass(klass) << " " << klass << " " << klass->GetClassLoader() << " "
<< PrettyClass(klass2) << " " << klass2 << " " << klass2->GetClassLoader();
}
@@ -2486,11 +2484,10 @@
for (int32_t j = 0; j < types->GetLength(); j++) {
mirror::Class* klass = types->Get(j);
if (klass != NULL) {
- ClassHelper kh(klass);
DCHECK(klass->GetClassLoader() == NULL);
- const char* descriptor = kh.GetDescriptor();
- size_t hash = Hash(descriptor);
- mirror::Class* existing = LookupClassFromTableLocked(descriptor, NULL, hash);
+ std::string descriptor = klass->GetDescriptor();
+ size_t hash = Hash(descriptor.c_str());
+ mirror::Class* existing = LookupClassFromTableLocked(descriptor.c_str(), NULL, hash);
if (existing != NULL) {
CHECK(existing == klass) << PrettyClassAndClassLoader(existing) << " != "
<< PrettyClassAndClassLoader(klass);
@@ -2544,8 +2541,7 @@
for (auto it = class_table_.lower_bound(hash), end = class_table_.end();
it != end && it->first == hash; ++it) {
mirror::Class* klass = it->second;
- ClassHelper kh(klass);
- if (strcmp(descriptor, kh.GetDescriptor()) == 0) {
+ if (descriptor == klass->GetDescriptor()) {
result.push_back(klass);
}
}
@@ -2757,7 +2753,7 @@
}
LOG(FATAL) << "Unexpected class status: " << oat_file_class_status
<< " " << dex_file.GetLocation() << " " << PrettyClass(klass) << " "
- << ClassHelper(klass).GetDescriptor();
+ << klass->GetDescriptor();
return false;
}
@@ -3077,8 +3073,7 @@
}
// Check if there are encoded static values needing initialization.
if (klass->NumStaticFields() != 0) {
- ClassHelper kh(klass);
- const DexFile::ClassDef* dex_class_def = kh.GetClassDef();
+ const DexFile::ClassDef* dex_class_def = klass->GetClassDef();
DCHECK(dex_class_def != NULL);
if (dex_class_def->static_values_off_ != 0) {
return false;
@@ -3207,13 +3202,12 @@
}
if (klass->NumStaticFields() > 0) {
- ClassHelper kh(klass.Get());
- const DexFile::ClassDef* dex_class_def = kh.GetClassDef();
+ const DexFile::ClassDef* dex_class_def = klass->GetClassDef();
CHECK(dex_class_def != NULL);
- const DexFile& dex_file = kh.GetDexFile();
+ const DexFile& dex_file = klass->GetDexFile();
StackHandleScope<2> hs(self);
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(kh.GetDexCache()));
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
EncodedStaticFieldValueIterator it(dex_file, &dex_cache, &class_loader,
this, *dex_class_def);
if (it.HasNext()) {
@@ -3258,8 +3252,8 @@
// Set the class as initialized except if failed to initialize static fields.
klass->SetStatus(mirror::Class::kStatusInitialized, self);
if (VLOG_IS_ON(class_linker)) {
- ClassHelper kh(klass.Get());
- LOG(INFO) << "Initialized class " << kh.GetDescriptor() << " from " << kh.GetLocation();
+ LOG(INFO) << "Initialized class " << klass->GetDescriptor() << " from " <<
+ klass->GetLocation();
}
// Opportunistically set static method trampolines to their destination.
FixupStaticTrampolines(klass.Get());
@@ -3613,6 +3607,7 @@
bool ClassLinker::LinkInterfaceMethods(const Handle<mirror::Class>& klass,
const Handle<mirror::ObjectArray<mirror::Class> >& interfaces) {
+ Thread* const self = Thread::Current();
// Set the imt table to be all conflicts by default.
klass->SetImTable(Runtime::Current()->GetDefaultImt());
size_t super_ifcount;
@@ -3621,18 +3616,14 @@
} else {
super_ifcount = 0;
}
- size_t ifcount = super_ifcount;
- uint32_t num_interfaces;
- {
- ClassHelper kh(klass.Get());
- num_interfaces =
- interfaces.Get() == nullptr ? kh.NumDirectInterfaces() : interfaces->GetLength();
- ifcount += num_interfaces;
- for (size_t i = 0; i < num_interfaces; i++) {
- mirror::Class* interface =
- interfaces.Get() == nullptr ? kh.GetDirectInterface(i) : interfaces->Get(i);
- ifcount += interface->GetIfTableCount();
- }
+ uint32_t num_interfaces =
+ interfaces.Get() == nullptr ? klass->NumDirectInterfaces() : interfaces->GetLength();
+ size_t ifcount = super_ifcount + num_interfaces;
+ for (size_t i = 0; i < num_interfaces; i++) {
+ mirror::Class* interface =
+ interfaces.Get() == nullptr ? mirror::Class::GetDirectInterface(self, klass, i) :
+ interfaces->Get(i);
+ ifcount += interface->GetIfTableCount();
}
if (ifcount == 0) {
// Class implements no interfaces.
@@ -3656,7 +3647,6 @@
return true;
}
}
- Thread* self = Thread::Current();
StackHandleScope<2> hs(self);
Handle<mirror::IfTable> iftable(hs.NewHandle(AllocIfTable(self, ifcount)));
if (UNLIKELY(iftable.Get() == NULL)) {
@@ -3673,15 +3663,14 @@
// Flatten the interface inheritance hierarchy.
size_t idx = super_ifcount;
for (size_t i = 0; i < num_interfaces; i++) {
- ClassHelper kh(klass.Get());
mirror::Class* interface =
- interfaces.Get() == nullptr ? kh.GetDirectInterface(i) : interfaces->Get(i);
+ interfaces.Get() == nullptr ? mirror::Class::GetDirectInterface(self, klass, i) :
+ interfaces->Get(i);
DCHECK(interface != NULL);
if (!interface->IsInterface()) {
- ClassHelper ih(interface);
ThrowIncompatibleClassChangeError(klass.Get(), "Class %s implements non-interface class %s",
PrettyDescriptor(klass.Get()).c_str(),
- PrettyDescriptor(ih.GetDescriptor()).c_str());
+ PrettyDescriptor(interface->GetDescriptor()).c_str());
return false;
}
// Check if interface is already in iftable
@@ -4007,8 +3996,7 @@
}
// We lie to the GC about the java.lang.ref.Reference.referent field, so it doesn't scan it.
- if (!is_static &&
- (strcmp("Ljava/lang/ref/Reference;", ClassHelper(klass.Get()).GetDescriptor()) == 0)) {
+ if (!is_static && "Ljava/lang/ref/Reference;" == klass->GetDescriptor()) {
// We know there are no non-reference fields in the Reference classes, and we know
// that 'referent' is alphabetically last, so this is easy...
CHECK_EQ(num_reference_fields, num_fields);
@@ -4033,8 +4021,8 @@
FieldHelper fh(field);
Primitive::Type type = fh.GetTypeAsPrimitiveType();
bool is_primitive = type != Primitive::kPrimNot;
- if ((strcmp("Ljava/lang/ref/Reference;", ClassHelper(klass.Get()).GetDescriptor()) == 0)
- && (strcmp("referent", fh.GetName()) == 0)) {
+ if ("Ljava/lang/ref/Reference;" == klass->GetDescriptor() &&
+ strcmp("referent", fh.GetName()) == 0) {
is_primitive = true; // We lied above, so we have to expect a lie here.
}
if (is_primitive) {
@@ -4058,7 +4046,7 @@
} else {
klass->SetNumReferenceInstanceFields(num_reference_fields);
if (!klass->IsVariableSize()) {
- DCHECK_GE(size, sizeof(mirror::Object)) << ClassHelper(klass.Get()).GetDescriptor();
+ DCHECK_GE(size, sizeof(mirror::Object)) << klass->GetDescriptor();
size_t previous_size = klass->GetObjectSize();
if (previous_size != 0) {
// Make sure that we didn't originally have an incorrect size.
@@ -4334,14 +4322,17 @@
return resolved;
}
const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
- mirror::Class* klass = ResolveType(dex_file, field_id.class_idx_, dex_cache, class_loader);
- if (klass == NULL) {
+ Thread* const self = Thread::Current();
+ StackHandleScope<1> hs(self);
+ Handle<mirror::Class> klass(
+ hs.NewHandle(ResolveType(dex_file, field_id.class_idx_, dex_cache, class_loader)));
+ if (klass.Get() == NULL) {
DCHECK(Thread::Current()->IsExceptionPending());
return NULL;
}
if (is_static) {
- resolved = klass->FindStaticField(dex_cache.Get(), field_idx);
+ resolved = mirror::Class::FindStaticField(self, klass, dex_cache.Get(), field_idx);
} else {
resolved = klass->FindInstanceField(dex_cache.Get(), field_idx);
}
@@ -4350,12 +4341,12 @@
const char* name = dex_file.GetFieldName(field_id);
const char* type = dex_file.GetFieldTypeDescriptor(field_id);
if (is_static) {
- resolved = klass->FindStaticField(name, type);
+ resolved = mirror::Class::FindStaticField(self, klass, name, type);
} else {
resolved = klass->FindInstanceField(name, type);
}
if (resolved == NULL) {
- ThrowNoSuchFieldError(is_static ? "static " : "instance ", klass, type, name);
+ ThrowNoSuchFieldError(is_static ? "static " : "instance ", klass.Get(), type, name);
return NULL;
}
}
@@ -4373,8 +4364,11 @@
return resolved;
}
const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
- mirror::Class* klass = ResolveType(dex_file, field_id.class_idx_, dex_cache, class_loader);
- if (klass == NULL) {
+ Thread* self = Thread::Current();
+ StackHandleScope<1> hs(self);
+ Handle<mirror::Class> klass(
+ hs.NewHandle(ResolveType(dex_file, field_id.class_idx_, dex_cache, class_loader)));
+ if (klass.Get() == NULL) {
DCHECK(Thread::Current()->IsExceptionPending());
return NULL;
}
@@ -4382,11 +4376,11 @@
StringPiece name(dex_file.StringDataByIdx(field_id.name_idx_));
StringPiece type(dex_file.StringDataByIdx(
dex_file.GetTypeId(field_id.type_idx_).descriptor_idx_));
- resolved = klass->FindField(name, type);
+ resolved = mirror::Class::FindField(self, klass, name, type);
if (resolved != NULL) {
dex_cache->SetResolvedField(field_idx, resolved);
} else {
- ThrowNoSuchFieldError("", klass, type, name);
+ ThrowNoSuchFieldError("", klass.Get(), type, name);
}
return resolved;
}
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 8037b91..22fd668 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -356,8 +356,8 @@
}
const void* GetQuickGenericJniTrampoline() const {
- return quick_generic_jni_trampoline_;
- }
+ return quick_generic_jni_trampoline_;
+ }
const void* GetQuickResolutionTrampoline() const {
return quick_resolution_trampoline_;
@@ -512,6 +512,9 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool LinkFields(const Handle<mirror::Class>& klass, bool is_static)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void LinkCode(const Handle<mirror::ArtMethod>& method, const OatFile::OatClass* oat_class,
+ const DexFile& dex_file, uint32_t dex_method_index, uint32_t method_index)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void CreateReferenceInstanceOffsets(const Handle<mirror::Class>& klass)
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 9970dd5..ff90f41 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -60,12 +60,11 @@
void AssertPrimitiveClass(const std::string& descriptor, mirror::Class* primitive)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- ClassHelper primitive_ch(primitive);
ASSERT_TRUE(primitive != NULL);
ASSERT_TRUE(primitive->GetClass() != NULL);
ASSERT_EQ(primitive->GetClass(), primitive->GetClass()->GetClass());
EXPECT_TRUE(primitive->GetClass()->GetSuperClass() != NULL);
- ASSERT_STREQ(descriptor.c_str(), primitive_ch.GetDescriptor());
+ ASSERT_STREQ(descriptor.c_str(), primitive->GetDescriptor().c_str());
EXPECT_TRUE(primitive->GetSuperClass() == NULL);
EXPECT_FALSE(primitive->HasSuperClass());
EXPECT_TRUE(primitive->GetClassLoader() == NULL);
@@ -87,7 +86,7 @@
EXPECT_EQ(0U, primitive->NumVirtualMethods());
EXPECT_EQ(0U, primitive->NumInstanceFields());
EXPECT_EQ(0U, primitive->NumStaticFields());
- EXPECT_EQ(0U, primitive_ch.NumDirectInterfaces());
+ EXPECT_EQ(0U, primitive->NumDirectInterfaces());
EXPECT_TRUE(primitive->GetVTable() == NULL);
EXPECT_EQ(0, primitive->GetIfTableCount());
EXPECT_TRUE(primitive->GetIfTable() == NULL);
@@ -103,8 +102,7 @@
Handle<mirror::ClassLoader> loader(hs.NewHandle(class_loader));
Handle<mirror::Class> array(
hs.NewHandle(class_linker_->FindClass(self, array_descriptor.c_str(), loader)));
- ClassHelper array_component_ch(array->GetComponentType());
- EXPECT_STREQ(component_type.c_str(), array_component_ch.GetDescriptor());
+ EXPECT_STREQ(component_type.c_str(), array->GetComponentType()->GetDescriptor().c_str());
EXPECT_EQ(class_loader, array->GetClassLoader());
EXPECT_EQ(kAccFinal | kAccAbstract, (array->GetAccessFlags() & (kAccFinal | kAccAbstract)));
AssertArrayClass(array_descriptor, array);
@@ -112,19 +110,17 @@
void AssertArrayClass(const std::string& array_descriptor, const Handle<mirror::Class>& array)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- ClassHelper kh(array.Get());
ASSERT_TRUE(array.Get() != NULL);
ASSERT_TRUE(array->GetClass() != NULL);
ASSERT_EQ(array->GetClass(), array->GetClass()->GetClass());
EXPECT_TRUE(array->GetClass()->GetSuperClass() != NULL);
- ASSERT_STREQ(array_descriptor.c_str(), kh.GetDescriptor());
+ ASSERT_STREQ(array_descriptor.c_str(), array->GetDescriptor().c_str());
EXPECT_TRUE(array->GetSuperClass() != NULL);
Thread* self = Thread::Current();
EXPECT_EQ(class_linker_->FindSystemClass(self, "Ljava/lang/Object;"), array->GetSuperClass());
EXPECT_TRUE(array->HasSuperClass());
ASSERT_TRUE(array->GetComponentType() != NULL);
- kh.ChangeClass(array->GetComponentType());
- ASSERT_TRUE(kh.GetDescriptor() != NULL);
+ ASSERT_TRUE(!array->GetComponentType()->GetDescriptor().empty());
EXPECT_EQ(mirror::Class::kStatusInitialized, array->GetStatus());
EXPECT_FALSE(array->IsErroneous());
EXPECT_TRUE(array->IsLoaded());
@@ -142,16 +138,15 @@
EXPECT_EQ(0U, array->NumVirtualMethods());
EXPECT_EQ(0U, array->NumInstanceFields());
EXPECT_EQ(0U, array->NumStaticFields());
- kh.ChangeClass(array.Get());
- EXPECT_EQ(2U, kh.NumDirectInterfaces());
+ EXPECT_EQ(2U, array->NumDirectInterfaces());
EXPECT_TRUE(array->GetVTable() != NULL);
EXPECT_EQ(2, array->GetIfTableCount());
ASSERT_TRUE(array->GetIfTable() != NULL);
- kh.ChangeClass(kh.GetDirectInterface(0));
- EXPECT_STREQ(kh.GetDescriptor(), "Ljava/lang/Cloneable;");
- kh.ChangeClass(array.Get());
- kh.ChangeClass(kh.GetDirectInterface(1));
- EXPECT_STREQ(kh.GetDescriptor(), "Ljava/io/Serializable;");
+ mirror::Class* direct_interface0 = mirror::Class::GetDirectInterface(self, array, 0);
+ EXPECT_TRUE(direct_interface0 != nullptr);
+ EXPECT_STREQ(direct_interface0->GetDescriptor().c_str(), "Ljava/lang/Cloneable;");
+ mirror::Class* direct_interface1 = mirror::Class::GetDirectInterface(self, array, 1);
+ EXPECT_STREQ(direct_interface1->GetDescriptor().c_str(), "Ljava/io/Serializable;");
EXPECT_EQ(class_linker_->FindArrayClass(self, array->GetComponentType()), array.Get());
}
@@ -185,8 +180,7 @@
void AssertClass(const std::string& descriptor, const Handle<mirror::Class>& klass)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- ClassHelper kh(klass.Get());
- EXPECT_STREQ(descriptor.c_str(), kh.GetDescriptor());
+ EXPECT_STREQ(descriptor.c_str(), klass->GetDescriptor().c_str());
if (descriptor == "Ljava/lang/Object;") {
EXPECT_FALSE(klass->HasSuperClass());
} else {
@@ -202,7 +196,8 @@
EXPECT_FALSE(klass->IsArrayClass());
EXPECT_TRUE(klass->GetComponentType() == NULL);
EXPECT_TRUE(klass->IsInSamePackage(klass.Get()));
- EXPECT_TRUE(mirror::Class::IsInSamePackage(kh.GetDescriptor(), kh.GetDescriptor()));
+ EXPECT_TRUE(mirror::Class::IsInSamePackage(klass->GetDescriptor().c_str(),
+ klass->GetDescriptor().c_str()));
if (klass->IsInterface()) {
EXPECT_TRUE(klass->IsAbstract());
if (klass->NumDirectMethods() == 1) {
@@ -311,7 +306,7 @@
Handle<mirror::Class> klass(
hs.NewHandle(class_linker_->FindSystemClass(self, descriptor.c_str())));
ASSERT_TRUE(klass.Get() != nullptr);
- EXPECT_STREQ(descriptor.c_str(), ClassHelper(klass.Get()).GetDescriptor());
+ EXPECT_STREQ(descriptor.c_str(), klass.Get()->GetDescriptor().c_str());
EXPECT_EQ(class_loader, klass->GetClassLoader());
if (klass->IsPrimitive()) {
AssertPrimitiveClass(descriptor, klass.Get());
@@ -706,12 +701,11 @@
TEST_F(ClassLinkerTest, FindClass) {
ScopedObjectAccess soa(Thread::Current());
mirror::Class* JavaLangObject = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;");
- ClassHelper kh(JavaLangObject);
ASSERT_TRUE(JavaLangObject != NULL);
ASSERT_TRUE(JavaLangObject->GetClass() != NULL);
ASSERT_EQ(JavaLangObject->GetClass(), JavaLangObject->GetClass()->GetClass());
EXPECT_EQ(JavaLangObject, JavaLangObject->GetClass()->GetSuperClass());
- ASSERT_STREQ(kh.GetDescriptor(), "Ljava/lang/Object;");
+ ASSERT_STREQ(JavaLangObject->GetDescriptor().c_str(), "Ljava/lang/Object;");
EXPECT_TRUE(JavaLangObject->GetSuperClass() == NULL);
EXPECT_FALSE(JavaLangObject->HasSuperClass());
EXPECT_TRUE(JavaLangObject->GetClassLoader() == NULL);
@@ -748,19 +742,18 @@
}
EXPECT_EQ(0U, JavaLangObject->NumStaticFields());
- EXPECT_EQ(0U, kh.NumDirectInterfaces());
+ EXPECT_EQ(0U, JavaLangObject->NumDirectInterfaces());
StackHandleScope<1> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("MyClass"))));
AssertNonExistentClass("LMyClass;");
mirror::Class* MyClass = class_linker_->FindClass(soa.Self(), "LMyClass;", class_loader);
- kh.ChangeClass(MyClass);
ASSERT_TRUE(MyClass != NULL);
ASSERT_TRUE(MyClass->GetClass() != NULL);
ASSERT_EQ(MyClass->GetClass(), MyClass->GetClass()->GetClass());
EXPECT_EQ(JavaLangObject, MyClass->GetClass()->GetSuperClass());
- ASSERT_STREQ(kh.GetDescriptor(), "LMyClass;");
+ ASSERT_STREQ(MyClass->GetDescriptor().c_str(), "LMyClass;");
EXPECT_TRUE(MyClass->GetSuperClass() == JavaLangObject);
EXPECT_TRUE(MyClass->HasSuperClass());
EXPECT_EQ(class_loader.Get(), MyClass->GetClassLoader());
@@ -782,7 +775,7 @@
EXPECT_EQ(0U, MyClass->NumVirtualMethods());
EXPECT_EQ(0U, MyClass->NumInstanceFields());
EXPECT_EQ(0U, MyClass->NumStaticFields());
- EXPECT_EQ(0U, kh.NumDirectInterfaces());
+ EXPECT_EQ(0U, MyClass->NumDirectInterfaces());
EXPECT_EQ(JavaLangObject->GetClass()->GetClass(), MyClass->GetClass()->GetClass());
@@ -913,56 +906,57 @@
EXPECT_EQ(9U, statics->NumStaticFields());
- mirror::ArtField* s0 = statics->FindStaticField("s0", "Z");
+ mirror::ArtField* s0 = mirror::Class::FindStaticField(soa.Self(), statics, "s0", "Z");
FieldHelper fh(s0);
- EXPECT_STREQ(ClassHelper(s0->GetClass()).GetDescriptor(), "Ljava/lang/reflect/ArtField;");
+ EXPECT_STREQ(s0->GetClass()->GetDescriptor().c_str(), "Ljava/lang/reflect/ArtField;");
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimBoolean);
EXPECT_EQ(true, s0->GetBoolean(statics.Get()));
s0->SetBoolean<false>(statics.Get(), false);
- mirror::ArtField* s1 = statics->FindStaticField("s1", "B");
+ mirror::ArtField* s1 = mirror::Class::FindStaticField(soa.Self(), statics, "s1", "B");
fh.ChangeField(s1);
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimByte);
EXPECT_EQ(5, s1->GetByte(statics.Get()));
s1->SetByte<false>(statics.Get(), 6);
- mirror::ArtField* s2 = statics->FindStaticField("s2", "C");
+ mirror::ArtField* s2 = mirror::Class::FindStaticField(soa.Self(), statics, "s2", "C");
fh.ChangeField(s2);
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimChar);
EXPECT_EQ('a', s2->GetChar(statics.Get()));
s2->SetChar<false>(statics.Get(), 'b');
- mirror::ArtField* s3 = statics->FindStaticField("s3", "S");
+ mirror::ArtField* s3 = mirror::Class::FindStaticField(soa.Self(), statics, "s3", "S");
fh.ChangeField(s3);
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimShort);
EXPECT_EQ(-536, s3->GetShort(statics.Get()));
s3->SetShort<false>(statics.Get(), -535);
- mirror::ArtField* s4 = statics->FindStaticField("s4", "I");
+ mirror::ArtField* s4 = mirror::Class::FindStaticField(soa.Self(), statics, "s4", "I");
fh.ChangeField(s4);
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimInt);
EXPECT_EQ(2000000000, s4->GetInt(statics.Get()));
s4->SetInt<false>(statics.Get(), 2000000001);
- mirror::ArtField* s5 = statics->FindStaticField("s5", "J");
+ mirror::ArtField* s5 = mirror::Class::FindStaticField(soa.Self(), statics, "s5", "J");
fh.ChangeField(s5);
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimLong);
EXPECT_EQ(0x1234567890abcdefLL, s5->GetLong(statics.Get()));
s5->SetLong<false>(statics.Get(), INT64_C(0x34567890abcdef12));
- mirror::ArtField* s6 = statics->FindStaticField("s6", "F");
+ mirror::ArtField* s6 = mirror::Class::FindStaticField(soa.Self(), statics, "s6", "F");
fh.ChangeField(s6);
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimFloat);
EXPECT_EQ(0.5, s6->GetFloat(statics.Get()));
s6->SetFloat<false>(statics.Get(), 0.75);
- mirror::ArtField* s7 = statics->FindStaticField("s7", "D");
+ mirror::ArtField* s7 = mirror::Class::FindStaticField(soa.Self(), statics, "s7", "D");
fh.ChangeField(s7);
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimDouble);
EXPECT_EQ(16777217, s7->GetDouble(statics.Get()));
s7->SetDouble<false>(statics.Get(), 16777219);
- mirror::ArtField* s8 = statics->FindStaticField("s8", "Ljava/lang/String;");
+ mirror::ArtField* s8 = mirror::Class::FindStaticField(soa.Self(), statics, "s8",
+ "Ljava/lang/String;");
fh.ChangeField(s8);
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimNot);
EXPECT_TRUE(s8->GetObject(statics.Get())->AsString()->Equals("android"));
@@ -984,19 +978,24 @@
TEST_F(ClassLinkerTest, Interfaces) {
ScopedObjectAccess soa(Thread::Current());
- StackHandleScope<1> hs(soa.Self());
+ StackHandleScope<6> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("Interfaces"))));
- mirror::Class* I = class_linker_->FindClass(soa.Self(), "LInterfaces$I;", class_loader);
- mirror::Class* J = class_linker_->FindClass(soa.Self(), "LInterfaces$J;", class_loader);
- mirror::Class* K = class_linker_->FindClass(soa.Self(), "LInterfaces$K;", class_loader);
- mirror::Class* A = class_linker_->FindClass(soa.Self(), "LInterfaces$A;", class_loader);
- mirror::Class* B = class_linker_->FindClass(soa.Self(), "LInterfaces$B;", class_loader);
- EXPECT_TRUE(I->IsAssignableFrom(A));
- EXPECT_TRUE(J->IsAssignableFrom(A));
- EXPECT_TRUE(J->IsAssignableFrom(K));
- EXPECT_TRUE(K->IsAssignableFrom(B));
- EXPECT_TRUE(J->IsAssignableFrom(B));
+ Handle<mirror::Class> I(
+ hs.NewHandle(class_linker_->FindClass(soa.Self(), "LInterfaces$I;", class_loader)));
+ Handle<mirror::Class> J(
+ hs.NewHandle(class_linker_->FindClass(soa.Self(), "LInterfaces$J;", class_loader)));
+ Handle<mirror::Class> K(
+ hs.NewHandle(class_linker_->FindClass(soa.Self(), "LInterfaces$K;", class_loader)));
+ Handle<mirror::Class> A(
+ hs.NewHandle(class_linker_->FindClass(soa.Self(), "LInterfaces$A;", class_loader)));
+ Handle<mirror::Class> B(
+ hs.NewHandle(class_linker_->FindClass(soa.Self(), "LInterfaces$B;", class_loader)));
+ EXPECT_TRUE(I->IsAssignableFrom(A.Get()));
+ EXPECT_TRUE(J->IsAssignableFrom(A.Get()));
+ EXPECT_TRUE(J->IsAssignableFrom(K.Get()));
+ EXPECT_TRUE(K->IsAssignableFrom(B.Get()));
+ EXPECT_TRUE(J->IsAssignableFrom(B.Get()));
const Signature void_sig = I->GetDexCache()->GetDexFile()->CreateSignature("()V");
mirror::ArtMethod* Ii = I->FindVirtualMethod("i", void_sig);
@@ -1029,10 +1028,14 @@
EXPECT_EQ(Aj1, A->FindVirtualMethodForVirtualOrInterface(Jj1));
EXPECT_EQ(Aj2, A->FindVirtualMethodForVirtualOrInterface(Jj2));
- mirror::ArtField* Afoo = A->FindStaticField("foo", "Ljava/lang/String;");
- mirror::ArtField* Bfoo = B->FindStaticField("foo", "Ljava/lang/String;");
- mirror::ArtField* Jfoo = J->FindStaticField("foo", "Ljava/lang/String;");
- mirror::ArtField* Kfoo = K->FindStaticField("foo", "Ljava/lang/String;");
+ mirror::ArtField* Afoo = mirror::Class::FindStaticField(soa.Self(), A, "foo",
+ "Ljava/lang/String;");
+ mirror::ArtField* Bfoo = mirror::Class::FindStaticField(soa.Self(), B, "foo",
+ "Ljava/lang/String;");
+ mirror::ArtField* Jfoo = mirror::Class::FindStaticField(soa.Self(), J, "foo",
+ "Ljava/lang/String;");
+ mirror::ArtField* Kfoo = mirror::Class::FindStaticField(soa.Self(), K, "foo",
+ "Ljava/lang/String;");
ASSERT_TRUE(Afoo != NULL);
EXPECT_EQ(Afoo, Bfoo);
EXPECT_EQ(Afoo, Jfoo);
@@ -1106,9 +1109,8 @@
ScopedObjectAccess soa(Thread::Current());
for (int i = 0; i < ClassLinker::kClassRootsMax; i++) {
mirror::Class* klass = class_linker_->GetClassRoot(ClassLinker::ClassRoot(i));
- ClassHelper kh(klass);
- EXPECT_TRUE(kh.GetDescriptor() != NULL);
- EXPECT_STREQ(kh.GetDescriptor(),
+ EXPECT_TRUE(!klass->GetDescriptor().empty());
+ EXPECT_STREQ(klass->GetDescriptor().c_str(),
class_linker_->GetClassRootDescriptor(ClassLinker::ClassRoot(i))) << " i = " << i;
}
}
diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc
index 315f274..a3e3cfa 100644
--- a/runtime/common_throws.cc
+++ b/runtime/common_throws.cc
@@ -36,8 +36,7 @@
static void AddReferrerLocation(std::ostream& os, mirror::Class* referrer)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (referrer != NULL) {
- ClassHelper kh(referrer);
- std::string location(kh.GetLocation());
+ std::string location(referrer->GetLocation());
if (!location.empty()) {
os << " (declaration of '" << PrettyDescriptor(referrer)
<< "' appears in " << location << ")";
@@ -297,10 +296,9 @@
void ThrowNoSuchFieldError(const StringPiece& scope, mirror::Class* c,
const StringPiece& type, const StringPiece& name)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- ClassHelper kh(c);
std::ostringstream msg;
msg << "No " << scope << "field " << name << " of type " << type
- << " in class " << kh.GetDescriptor() << " or its superclasses";
+ << " in class " << c->GetDescriptor() << " or its superclasses";
ThrowException(NULL, "Ljava/lang/NoSuchFieldError;", c, msg.str().c_str());
}
@@ -309,9 +307,8 @@
void ThrowNoSuchMethodError(InvokeType type, mirror::Class* c, const StringPiece& name,
const Signature& signature) {
std::ostringstream msg;
- ClassHelper kh(c);
msg << "No " << type << " method " << name << signature
- << " in class " << kh.GetDescriptor() << " or its super classes";
+ << " in class " << c->GetDescriptor() << " or its super classes";
ThrowException(NULL, "Ljava/lang/NoSuchMethodError;", c, msg.str().c_str());
}
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index f6b4891..2cbff79 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -756,7 +756,7 @@
if (!o->IsClass()) {
return StringPrintf("non-class %p", o); // This is only used for debugging output anyway.
}
- return DescriptorToName(ClassHelper(o->AsClass()).GetDescriptor());
+ return DescriptorToName(o->AsClass()->GetDescriptor().c_str());
}
JDWP::JdwpError Dbg::GetClassObject(JDWP::RefTypeId id, JDWP::ObjectId& class_object_id) {
@@ -1088,7 +1088,7 @@
}
if (pDescriptor != NULL) {
- *pDescriptor = ClassHelper(c).GetDescriptor();
+ *pDescriptor = c->GetDescriptor();
}
return JDWP::ERR_NONE;
}
@@ -1124,7 +1124,7 @@
if (c == NULL) {
return status;
}
- *signature = ClassHelper(c).GetDescriptor();
+ *signature = c->GetDescriptor();
return JDWP::ERR_NONE;
}
@@ -1137,7 +1137,7 @@
if (c->IsProxyClass()) {
return JDWP::ERR_ABSENT_INFORMATION;
}
- result = ClassHelper(c).GetSourceFile();
+ result = c->GetSourceFile();
return JDWP::ERR_NONE;
}
@@ -1202,7 +1202,7 @@
LOG(WARNING) << __FUNCTION__ << " access out of bounds: offset=" << offset << "; count=" << count;
return JDWP::ERR_INVALID_LENGTH;
}
- std::string descriptor(ClassHelper(a->GetClass()).GetDescriptor());
+ std::string descriptor(a->GetClass()->GetDescriptor());
JDWP::JdwpTag tag = BasicTagFromDescriptor(descriptor.c_str() + 1);
expandBufAdd1(pReply, tag);
@@ -1264,9 +1264,8 @@
LOG(WARNING) << __FUNCTION__ << " access out of bounds: offset=" << offset << "; count=" << count;
return JDWP::ERR_INVALID_LENGTH;
}
- ClassHelper ch(dst->GetClass());
- const char* descriptor = ch.GetDescriptor();
- JDWP::JdwpTag tag = BasicTagFromDescriptor(descriptor + 1);
+ std::string descriptor = dst->GetClass()->GetDescriptor();
+ JDWP::JdwpTag tag = BasicTagFromDescriptor(descriptor.c_str() + 1);
if (IsPrimitiveTag(tag)) {
size_t width = GetTagWidth(tag);
@@ -1497,16 +1496,17 @@
JDWP::JdwpError Dbg::OutputDeclaredInterfaces(JDWP::RefTypeId class_id, JDWP::ExpandBuf* pReply) {
JDWP::JdwpError status;
- mirror::Class* c = DecodeClass(class_id, status);
- if (c == NULL) {
+ Thread* self = Thread::Current();
+ StackHandleScope<1> hs(self);
+ Handle<mirror::Class> c(hs.NewHandle(DecodeClass(class_id, status)));
+ if (c.Get() == nullptr) {
return status;
}
-
- ClassHelper kh(c);
- size_t interface_count = kh.NumDirectInterfaces();
+ size_t interface_count = c->NumDirectInterfaces();
expandBufAdd4BE(pReply, interface_count);
for (size_t i = 0; i < interface_count; ++i) {
- expandBufAddRefTypeId(pReply, gRegistry->AddRefType(kh.GetDirectInterface(i)));
+ expandBufAddRefTypeId(pReply,
+ gRegistry->AddRefType(mirror::Class::GetDirectInterface(self, c, i)));
}
return JDWP::ERR_NONE;
}
@@ -2592,8 +2592,7 @@
// since the class may not yet be verified.
int state = JDWP::CS_VERIFIED | JDWP::CS_PREPARED;
JDWP::JdwpTypeTag tag = GetTypeTag(c);
- gJdwpState->PostClassPrepare(tag, gRegistry->Add(c),
- ClassHelper(c).GetDescriptor(), state);
+ gJdwpState->PostClassPrepare(tag, gRegistry->Add(c), c->GetDescriptor(), state);
}
void Dbg::UpdateDebugger(Thread* thread, mirror::Object* this_object,
@@ -4357,7 +4356,7 @@
while (count--) {
AllocRecord* record = &recent_allocation_records_[idx];
- class_names.Add(ClassHelper(record->type).GetDescriptor());
+ class_names.Add(record->type->GetDescriptor().c_str());
MethodHelper mh;
for (size_t i = 0; i < kMaxAllocRecordStackDepth; i++) {
@@ -4411,8 +4410,8 @@
// (1b) stack depth
AllocRecord* record = &recent_allocation_records_[idx];
size_t stack_depth = record->GetDepth();
- ClassHelper kh(record->type);
- size_t allocated_object_class_name_index = class_names.IndexOf(kh.GetDescriptor());
+ size_t allocated_object_class_name_index =
+ class_names.IndexOf(record->type->GetDescriptor().c_str());
JDWP::Append4BE(bytes, record->byte_count);
JDWP::Append2BE(bytes, record->thin_lock_id);
JDWP::Append2BE(bytes, allocated_object_class_name_index);
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index 6998e21..bfcb58f 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -737,11 +737,6 @@
return reinterpret_cast<void*>(art_quick_to_interpreter_bridge);
}
-extern "C" void art_quick_generic_jni_trampoline(mirror::ArtMethod*);
-static inline const void* GetQuickGenericJniTrampoline() {
- return reinterpret_cast<void*>(art_quick_generic_jni_trampoline);
-}
-
static inline const void* GetQuickToPortableBridge() {
// TODO: quick to portable bridge. Bug: 8196384
return GetQuickToInterpreterBridge();
@@ -763,10 +758,6 @@
return class_linker->GetQuickImtConflictTrampoline();
}
-static inline const void* GetQuickGenericJniTrampoline(ClassLinker* class_linker) {
- return class_linker->GetQuickGenericJniTrampoline();
-}
-
static inline const void* GetQuickToInterpreterBridgeTrampoline(ClassLinker* class_linker) {
return class_linker->GetQuickToInterpreterBridgeTrampoline();
}
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index b4c2d14..ef31be3 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -2765,7 +2765,7 @@
void Heap::CheckPreconditionsForAllocObject(mirror::Class* c, size_t byte_count) {
CHECK(c == NULL || (c->IsClassClass() && byte_count >= sizeof(mirror::Class)) ||
(c->IsVariableSize() || c->GetObjectSize() == byte_count) ||
- strlen(ClassHelper(c).GetDescriptor()) == 0);
+ c->GetDescriptor().empty());
CHECK_GE(byte_count, sizeof(mirror::Object));
}
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index 20e2b8d..478c74c 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -49,7 +49,8 @@
value.SetJ((static_cast<uint64_t>(args[1]) << 32) | args[0]);
result->SetD(log(value.GetD()));
} else if (name == "java.lang.String java.lang.Class.getNameNative()") {
- result->SetL(receiver->AsClass()->ComputeName());
+ StackHandleScope<1> hs(self);
+ result->SetL(mirror::Class::ComputeName(hs.NewHandle(receiver->AsClass())));
} else if (name == "int java.lang.Float.floatToRawIntBits(float)") {
result->SetI(args[0]);
} else if (name == "float java.lang.Float.intBitsToFloat(int)") {
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index c5fb0d8..418aff5 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -117,8 +117,8 @@
"Ljava/lang/VirtualMachineError;",
"Invoking %s with bad arg %d, type '%s' not instance of '%s'",
mh.GetName(), shorty_pos,
- ClassHelper(o->GetClass()).GetDescriptor(),
- ClassHelper(arg_type).GetDescriptor());
+ o->GetClass()->GetDescriptor().c_str(),
+ arg_type->GetDescriptor().c_str());
return false;
}
}
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index 9b03334..0c7c8a9 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -345,9 +345,9 @@
self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
"Ljava/lang/VirtualMachineError;",
"Put '%s' that is not instance of field '%s' in '%s'",
- ClassHelper(reg->GetClass()).GetDescriptor(),
- ClassHelper(field_class).GetDescriptor(),
- ClassHelper(f->GetDeclaringClass()).GetDescriptor());
+ reg->GetClass()->GetDescriptor().c_str(),
+ field_class->GetDescriptor().c_str(),
+ f->GetDeclaringClass()->GetDescriptor().c_str());
return false;
}
}
diff --git a/runtime/interpreter/interpreter_goto_table_impl.cc b/runtime/interpreter/interpreter_goto_table_impl.cc
index 5b7dee1d..e0f9e5f 100644
--- a/runtime/interpreter/interpreter_goto_table_impl.cc
+++ b/runtime/interpreter/interpreter_goto_table_impl.cc
@@ -342,8 +342,8 @@
self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
"Ljava/lang/VirtualMachineError;",
"Returning '%s' that is not instance of return type '%s'",
- ClassHelper(obj_result->GetClass()).GetDescriptor(),
- ClassHelper(return_type).GetDescriptor());
+ obj_result->GetClass()->GetDescriptor().c_str(),
+ return_type->GetDescriptor().c_str());
HANDLE_PENDING_EXCEPTION();
}
}
@@ -614,7 +614,7 @@
self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
"Ljava/lang/VirtualMachineError;",
"Throwing '%s' that is not instance of Throwable",
- ClassHelper(exception->GetClass()).GetDescriptor());
+ exception->GetClass()->GetDescriptor().c_str());
} else {
self->SetException(shadow_frame.GetCurrentLocationForThrow(), exception->AsThrowable());
}
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc
index 859cfc4..c1d24f5 100644
--- a/runtime/interpreter/interpreter_switch_impl.cc
+++ b/runtime/interpreter/interpreter_switch_impl.cc
@@ -258,8 +258,8 @@
self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
"Ljava/lang/VirtualMachineError;",
"Returning '%s' that is not instance of return type '%s'",
- ClassHelper(obj_result->GetClass()).GetDescriptor(),
- ClassHelper(return_type).GetDescriptor());
+ obj_result->GetClass()->GetDescriptor().c_str(),
+ return_type->GetDescriptor().c_str());
HANDLE_PENDING_EXCEPTION();
}
}
@@ -528,7 +528,7 @@
self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
"Ljava/lang/VirtualMachineError;",
"Throwing '%s' that is not instance of Throwable",
- ClassHelper(exception->GetClass()).GetDescriptor());
+ exception->GetClass()->GetDescriptor().c_str());
} else {
self->SetException(shadow_frame.GetCurrentLocationForThrow(), exception->AsThrowable());
}
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 3afb149..17a3de4 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -109,7 +109,7 @@
ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/NoSuchMethodError;",
"no %s method \"%s.%s%s\"",
- kind, ClassHelper(c).GetDescriptor(), name, sig);
+ kind, c->GetDescriptor().c_str(), name, sig);
}
static mirror::Class* EnsureInitialized(Thread* self, mirror::Class* klass)
@@ -206,20 +206,21 @@
soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/NoSuchFieldError;",
"no type \"%s\" found and so no field \"%s\" "
"could be found in class \"%s\" or its superclasses", sig, name,
- ClassHelper(c.Get()).GetDescriptor());
+ c->GetDescriptor().c_str());
soa.Self()->GetException(nullptr)->SetCause(cause.Get());
return nullptr;
}
if (is_static) {
- field = c->FindStaticField(name, ClassHelper(field_type).GetDescriptor());
+ field = mirror::Class::FindStaticField(soa.Self(), c, name,
+ field_type->GetDescriptor().c_str());
} else {
- field = c->FindInstanceField(name, ClassHelper(field_type).GetDescriptor());
+ field = c->FindInstanceField(name, field_type->GetDescriptor().c_str());
}
if (field == nullptr) {
ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/NoSuchFieldError;",
"no \"%s\" field \"%s\" in class \"%s\" or its superclasses",
- sig, name, ClassHelper(c.Get()).GetDescriptor());
+ sig, name, c->GetDescriptor().c_str());
return nullptr;
}
return soa.EncodeField(field);
diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc
index 5225919..ffafc85 100644
--- a/runtime/mem_map.cc
+++ b/runtime/mem_map.cc
@@ -47,8 +47,8 @@
}
#if defined(__LP64__) && !defined(__x86_64__)
-// Where to start with low memory allocation.
-static constexpr uintptr_t LOW_MEM_START = kPageSize * 2;
+// Where to start with low memory allocation. The first 64KB is protected by SELinux.
+static constexpr uintptr_t LOW_MEM_START = 64 * KB;
uintptr_t MemMap::next_mem_pos_ = LOW_MEM_START; // first page to check for low-mem extent
#endif
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index c3e2d22..cde977b 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/mirror/art_method-inl.h
@@ -222,7 +222,7 @@
DCHECK(entry_point != GetQuickToInterpreterBridgeTrampoline(runtime->GetClassLinker()));
CHECK(entry_point != GetQuickToInterpreterBridge());
- if (UNLIKELY(entry_point == GetQuickGenericJniTrampoline())) {
+ if (UNLIKELY(entry_point == runtime->GetClassLinker()->GetQuickGenericJniTrampoline())) {
// Generic JNI frame.
DCHECK(IsNative());
uint32_t handle_refs = MethodHelper(this).GetNumberOfReferenceArgsWithoutReceiver() + 1;
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index d454ae8..b2d8288 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -21,9 +21,11 @@
#include "art_field.h"
#include "art_method.h"
+#include "class_linker-inl.h"
#include "class_loader.h"
#include "common_throws.h"
#include "dex_cache.h"
+#include "dex_file.h"
#include "gc/heap-inl.h"
#include "iftable.h"
#include "object_array-inl.h"
@@ -508,7 +510,7 @@
}
template<ReadBarrierOption kReadBarrierOption>
-bool Class::IsArtFieldClass() {
+inline bool Class::IsArtFieldClass() {
Class* java_lang_Class = GetClass<kVerifyNone, kReadBarrierOption>();
Class* java_lang_reflect_ArtField =
java_lang_Class->GetInstanceField(0)->GetClass<kVerifyNone, kReadBarrierOption>();
@@ -516,7 +518,7 @@
}
template<ReadBarrierOption kReadBarrierOption>
-bool Class::IsArtMethodClass() {
+inline bool Class::IsArtMethodClass() {
return this == ArtMethod::GetJavaLangReflectArtMethod<kReadBarrierOption>();
}
@@ -527,6 +529,24 @@
return this == java_lang_Class;
}
+inline const DexFile& Class::GetDexFile() {
+ return *GetDexCache()->GetDexFile();
+}
+
+inline bool Class::DescriptorEquals(const char* match) {
+ if (UNLIKELY(IsArrayClass())) {
+ return match[0] == '[' && GetComponentType()->DescriptorEquals(match + 1);
+ } else if (UNLIKELY(IsPrimitive())) {
+ return strcmp(Primitive::Descriptor(GetPrimitiveType()), match) == 0;
+ } else if (UNLIKELY(IsProxyClass())) {
+ return Runtime::Current()->GetClassLinker()->GetDescriptorForProxy(this) == match;
+ } else {
+ const DexFile& dex_file = GetDexFile();
+ const DexFile::TypeId& type_id = dex_file.GetTypeId(GetClassDef()->class_idx_);
+ return strcmp(dex_file.GetTypeDescriptor(type_id), match) == 0;
+ }
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 15b69f3..4869b45 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -136,15 +136,13 @@
// Class.getName: keywords for primitive types, regular "[I" form for primitive arrays (so "int"
// but "[I"), and arrays of reference types written between "L" and ";" but with dots rather than
// slashes (so "java.lang.String" but "[Ljava.lang.String;"). Madness.
-String* Class::ComputeName() {
- String* name = GetName();
+String* Class::ComputeName(Handle<Class> h_this) {
+ String* name = h_this->GetName();
if (name != nullptr) {
return name;
}
+ std::string descriptor(h_this->GetDescriptor());
Thread* self = Thread::Current();
- StackHandleScope<1> hs(self);
- Handle<mirror::Class> handle_c(hs.NewHandle(this));
- std::string descriptor(ClassHelper(this).GetDescriptor());
if ((descriptor[0] != 'L') && (descriptor[0] != '[')) {
// The descriptor indicates that this is the class for
// a primitive type; special-case the return value.
@@ -173,7 +171,7 @@
std::replace(descriptor.begin(), descriptor.end(), '/', '.');
name = String::AllocFromModifiedUtf8(self, descriptor.c_str());
}
- handle_c->SetName(name);
+ h_this->SetName(name);
return name;
}
@@ -190,52 +188,59 @@
return;
}
- Class* super = GetSuperClass();
- ClassHelper kh(this);
+ Thread* self = Thread::Current();
+ StackHandleScope<2> hs(self);
+ Handle<mirror::Class> h_this(hs.NewHandle(this));
+ Handle<mirror::Class> h_super(hs.NewHandle(GetSuperClass()));
+
os << "----- " << (IsInterface() ? "interface" : "class") << " "
- << "'" << kh.GetDescriptor() << "' cl=" << GetClassLoader() << " -----\n",
+ << "'" << GetDescriptor() << "' cl=" << GetClassLoader() << " -----\n",
os << " objectSize=" << SizeOf() << " "
- << "(" << (super != NULL ? super->SizeOf() : -1) << " from super)\n",
+ << "(" << (h_super.Get() != NULL ? h_super->SizeOf() : -1) << " from super)\n",
os << StringPrintf(" access=0x%04x.%04x\n",
GetAccessFlags() >> 16, GetAccessFlags() & kAccJavaFlagsMask);
- if (super != NULL) {
- os << " super='" << PrettyClass(super) << "' (cl=" << super->GetClassLoader() << ")\n";
+ if (h_super.Get() != NULL) {
+ os << " super='" << PrettyClass(h_super.Get()) << "' (cl=" << h_super->GetClassLoader()
+ << ")\n";
}
if (IsArrayClass()) {
os << " componentType=" << PrettyClass(GetComponentType()) << "\n";
}
- if (kh.NumDirectInterfaces() > 0) {
- os << " interfaces (" << kh.NumDirectInterfaces() << "):\n";
- for (size_t i = 0; i < kh.NumDirectInterfaces(); ++i) {
- Class* interface = kh.GetDirectInterface(i);
+ const size_t num_direct_interfaces = NumDirectInterfaces();
+ if (num_direct_interfaces > 0) {
+ os << " interfaces (" << num_direct_interfaces << "):\n";
+ for (size_t i = 0; i < num_direct_interfaces; ++i) {
+ Class* interface = GetDirectInterface(self, h_this, i);
const ClassLoader* cl = interface->GetClassLoader();
os << StringPrintf(" %2zd: %s (cl=%p)\n", i, PrettyClass(interface).c_str(), cl);
}
}
- os << " vtable (" << NumVirtualMethods() << " entries, "
- << (super != NULL ? super->NumVirtualMethods() : 0) << " in super):\n";
+ // After this point, this may have moved due to GetDirectInterface.
+ os << " vtable (" << h_this->NumVirtualMethods() << " entries, "
+ << (h_super.Get() != NULL ? h_super->NumVirtualMethods() : 0) << " in super):\n";
for (size_t i = 0; i < NumVirtualMethods(); ++i) {
- os << StringPrintf(" %2zd: %s\n", i, PrettyMethod(GetVirtualMethodDuringLinking(i)).c_str());
+ os << StringPrintf(" %2zd: %s\n", i,
+ PrettyMethod(h_this->GetVirtualMethodDuringLinking(i)).c_str());
}
- os << " direct methods (" << NumDirectMethods() << " entries):\n";
- for (size_t i = 0; i < NumDirectMethods(); ++i) {
- os << StringPrintf(" %2zd: %s\n", i, PrettyMethod(GetDirectMethod(i)).c_str());
+ os << " direct methods (" << h_this->NumDirectMethods() << " entries):\n";
+ for (size_t i = 0; i < h_this->NumDirectMethods(); ++i) {
+ os << StringPrintf(" %2zd: %s\n", i, PrettyMethod(h_this->GetDirectMethod(i)).c_str());
}
- if (NumStaticFields() > 0) {
- os << " static fields (" << NumStaticFields() << " entries):\n";
- if (IsResolved() || IsErroneous()) {
- for (size_t i = 0; i < NumStaticFields(); ++i) {
- os << StringPrintf(" %2zd: %s\n", i, PrettyField(GetStaticField(i)).c_str());
+ if (h_this->NumStaticFields() > 0) {
+ os << " static fields (" << h_this->NumStaticFields() << " entries):\n";
+ if (h_this->IsResolved() || h_this->IsErroneous()) {
+ for (size_t i = 0; i < h_this->NumStaticFields(); ++i) {
+ os << StringPrintf(" %2zd: %s\n", i, PrettyField(h_this->GetStaticField(i)).c_str());
}
} else {
os << " <not yet available>";
}
}
- if (NumInstanceFields() > 0) {
- os << " instance fields (" << NumInstanceFields() << " entries):\n";
- if (IsResolved() || IsErroneous()) {
- for (size_t i = 0; i < NumInstanceFields(); ++i) {
- os << StringPrintf(" %2zd: %s\n", i, PrettyField(GetInstanceField(i)).c_str());
+ if (h_this->NumInstanceFields() > 0) {
+ os << " instance fields (" << h_this->NumInstanceFields() << " entries):\n";
+ if (h_this->IsResolved() || h_this->IsErroneous()) {
+ for (size_t i = 0; i < h_this->NumInstanceFields(); ++i) {
+ os << StringPrintf(" %2zd: %s\n", i, PrettyField(h_this->GetInstanceField(i)).c_str());
}
} else {
os << " <not yet available>";
@@ -305,8 +310,7 @@
return true;
}
// Compare the package part of the descriptor string.
- return IsInSamePackage(ClassHelper(klass1).GetDescriptor(),
- ClassHelper(klass2).GetDescriptor());
+ return IsInSamePackage(klass1->GetDescriptor().c_str(), klass2->GetDescriptor().c_str());
}
bool Class::IsStringClass() const {
@@ -585,71 +589,82 @@
return NULL;
}
-ArtField* Class::FindStaticField(const StringPiece& name, const StringPiece& type) {
+ArtField* Class::FindStaticField(Thread* self, Handle<Class> klass, const StringPiece& name,
+ const StringPiece& type) {
// Is the field in this class (or its interfaces), or any of its
// superclasses (or their interfaces)?
- for (Class* k = this; k != NULL; k = k->GetSuperClass()) {
+ for (Class* k = klass.Get(); k != nullptr; k = k->GetSuperClass()) {
// Is the field in this class?
ArtField* f = k->FindDeclaredStaticField(name, type);
- if (f != NULL) {
+ if (f != nullptr) {
return f;
}
+ // Wrap k incase it moves during GetDirectInterface.
+ StackHandleScope<1> hs(self);
+ HandleWrapper<mirror::Class> h_k(hs.NewHandleWrapper(&k));
// Is this field in any of this class' interfaces?
- ClassHelper kh(k);
- for (uint32_t i = 0; i < kh.NumDirectInterfaces(); ++i) {
- Class* interface = kh.GetDirectInterface(i);
- f = interface->FindStaticField(name, type);
- if (f != NULL) {
+ for (uint32_t i = 0; i < h_k->NumDirectInterfaces(); ++i) {
+ StackHandleScope<1> hs(self);
+ Handle<mirror::Class> interface(hs.NewHandle(GetDirectInterface(self, h_k, i)));
+ f = FindStaticField(self, interface, name, type);
+ if (f != nullptr) {
return f;
}
}
}
- return NULL;
+ return nullptr;
}
-ArtField* Class::FindStaticField(const DexCache* dex_cache, uint32_t dex_field_idx) {
- for (Class* k = this; k != NULL; k = k->GetSuperClass()) {
+ArtField* Class::FindStaticField(Thread* self, Handle<Class> klass, const DexCache* dex_cache,
+ uint32_t dex_field_idx) {
+ for (Class* k = klass.Get(); k != nullptr; k = k->GetSuperClass()) {
// Is the field in this class?
ArtField* f = k->FindDeclaredStaticField(dex_cache, dex_field_idx);
if (f != NULL) {
return f;
}
+ // Wrap k incase it moves during GetDirectInterface.
+ StackHandleScope<1> hs(self);
+ HandleWrapper<mirror::Class> h_k(hs.NewHandleWrapper(&k));
// Is this field in any of this class' interfaces?
- ClassHelper kh(k);
- for (uint32_t i = 0; i < kh.NumDirectInterfaces(); ++i) {
- Class* interface = kh.GetDirectInterface(i);
- f = interface->FindStaticField(dex_cache, dex_field_idx);
- if (f != NULL) {
+ for (uint32_t i = 0; i < h_k->NumDirectInterfaces(); ++i) {
+ StackHandleScope<1> hs(self);
+ Handle<mirror::Class> interface(hs.NewHandle(GetDirectInterface(self, h_k, i)));
+ f = FindStaticField(self, interface, dex_cache, dex_field_idx);
+ if (f != nullptr) {
return f;
}
}
}
- return NULL;
+ return nullptr;
}
-ArtField* Class::FindField(const StringPiece& name, const StringPiece& type) {
+ArtField* Class::FindField(Thread* self, Handle<Class> klass, const StringPiece& name,
+ const StringPiece& type) {
// Find a field using the JLS field resolution order
- for (Class* k = this; k != NULL; k = k->GetSuperClass()) {
+ for (Class* k = klass.Get(); k != NULL; k = k->GetSuperClass()) {
// Is the field in this class?
ArtField* f = k->FindDeclaredInstanceField(name, type);
- if (f != NULL) {
+ if (f != nullptr) {
return f;
}
f = k->FindDeclaredStaticField(name, type);
- if (f != NULL) {
+ if (f != nullptr) {
return f;
}
// Is this field in any of this class' interfaces?
- ClassHelper kh(k);
- for (uint32_t i = 0; i < kh.NumDirectInterfaces(); ++i) {
- Class* interface = kh.GetDirectInterface(i);
- f = interface->FindStaticField(name, type);
- if (f != NULL) {
+ StackHandleScope<1> hs(self);
+ HandleWrapper<mirror::Class> h_k(hs.NewHandleWrapper(&k));
+ for (uint32_t i = 0; i < h_k->NumDirectInterfaces(); ++i) {
+ StackHandleScope<1> hs(self);
+ Handle<mirror::Class> interface(hs.NewHandle(GetDirectInterface(self, h_k, i)));
+ f = interface->FindStaticField(self, interface, name, type);
+ if (f != nullptr) {
return f;
}
}
}
- return NULL;
+ return nullptr;
}
static void SetPreverifiedFlagOnMethods(mirror::ObjectArray<mirror::ArtMethod>* methods)
@@ -671,5 +686,111 @@
SetPreverifiedFlagOnMethods(GetVirtualMethods());
}
+std::string Class::GetDescriptor() {
+ if (UNLIKELY(IsArrayClass())) {
+ return GetArrayDescriptor();
+ } else if (UNLIKELY(IsPrimitive())) {
+ return Primitive::Descriptor(GetPrimitiveType());
+ } else if (UNLIKELY(IsProxyClass())) {
+ return Runtime::Current()->GetClassLinker()->GetDescriptorForProxy(this);
+ } else {
+ const DexFile& dex_file = GetDexFile();
+ const DexFile::TypeId& type_id = dex_file.GetTypeId(GetClassDef()->class_idx_);
+ return dex_file.GetTypeDescriptor(type_id);
+ }
+}
+
+std::string Class::GetArrayDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return "[" + GetComponentType()->GetDescriptor();
+}
+
+const DexFile::ClassDef* Class::GetClassDef() {
+ uint16_t class_def_idx = GetDexClassDefIndex();
+ if (class_def_idx == DexFile::kDexNoIndex16) {
+ return nullptr;
+ }
+ return &GetDexFile().GetClassDef(class_def_idx);
+}
+
+uint32_t Class::NumDirectInterfaces() {
+ if (IsPrimitive()) {
+ return 0;
+ } else if (IsArrayClass()) {
+ return 2;
+ } else if (IsProxyClass()) {
+ mirror::SynthesizedProxyClass* proxy_class=
+ reinterpret_cast<mirror::SynthesizedProxyClass*>(this);
+ mirror::ObjectArray<mirror::Class>* interfaces = proxy_class->GetInterfaces();
+ return interfaces != nullptr ? interfaces->GetLength() : 0;
+ } else {
+ const DexFile::TypeList* interfaces = GetInterfaceTypeList();
+ if (interfaces == nullptr) {
+ return 0;
+ } else {
+ return interfaces->Size();
+ }
+ }
+}
+
+uint16_t Class::GetDirectInterfaceTypeIdx(uint32_t idx) {
+ DCHECK(!IsPrimitive());
+ DCHECK(!IsArrayClass());
+ return GetInterfaceTypeList()->GetTypeItem(idx).type_idx_;
+}
+
+mirror::Class* Class::GetDirectInterface(Thread* self, Handle<mirror::Class> klass, uint32_t idx) {
+ DCHECK(klass.Get() != nullptr);
+ DCHECK(!klass->IsPrimitive());
+ if (klass->IsArrayClass()) {
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ if (idx == 0) {
+ return class_linker->FindSystemClass(self, "Ljava/lang/Cloneable;");
+ } else {
+ DCHECK_EQ(1U, idx);
+ return class_linker->FindSystemClass(self, "Ljava/io/Serializable;");
+ }
+ } else if (klass->IsProxyClass()) {
+ mirror::SynthesizedProxyClass* proxy_class =
+ reinterpret_cast<mirror::SynthesizedProxyClass*>(klass.Get());
+ mirror::ObjectArray<mirror::Class>* interfaces = proxy_class->GetInterfaces();
+ DCHECK(interfaces != nullptr);
+ return interfaces->Get(idx);
+ } else {
+ uint16_t type_idx = klass->GetDirectInterfaceTypeIdx(idx);
+ mirror::Class* interface = klass->GetDexCache()->GetResolvedType(type_idx);
+ if (interface == nullptr) {
+ interface = Runtime::Current()->GetClassLinker()->ResolveType(klass->GetDexFile(), type_idx,
+ klass.Get());
+ CHECK(interface != nullptr || self->IsExceptionPending());
+ }
+ return interface;
+ }
+}
+
+const char* Class::GetSourceFile() {
+ std::string descriptor(GetDescriptor());
+ const DexFile& dex_file = GetDexFile();
+ const DexFile::ClassDef* dex_class_def = GetClassDef();
+ CHECK(dex_class_def != nullptr) << "No class def for class " << PrettyClass(this);
+ return dex_file.GetSourceFile(*dex_class_def);
+}
+
+std::string Class::GetLocation() {
+ mirror::DexCache* dex_cache = GetDexCache();
+ if (dex_cache != nullptr && !IsProxyClass()) {
+ return dex_cache->GetLocation()->ToModifiedUtf8();
+ }
+ // Arrays and proxies are generated and have no corresponding dex file location.
+ return "generated class";
+}
+
+const DexFile::TypeList* Class::GetInterfaceTypeList() {
+ const DexFile::ClassDef* class_def = GetClassDef();
+ if (class_def == nullptr) {
+ return nullptr;
+ }
+ return GetDexFile().GetInterfacesList(*class_def);
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 92b999e..a283f60 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -17,6 +17,7 @@
#ifndef ART_RUNTIME_MIRROR_CLASS_H_
#define ART_RUNTIME_MIRROR_CLASS_H_
+#include "dex_file.h"
#include "gc/allocator_type.h"
#include "invoke_type.h"
#include "modifiers.h"
@@ -274,7 +275,7 @@
String* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Returns the cached name.
void SetName(String* name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Sets the cached name.
// Computes the name, then sets the cached value.
- String* ComputeName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ static String* ComputeName(Handle<Class> h_this) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsProxyClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -776,7 +777,8 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Find a static or instance field using the JLS resolution order
- ArtField* FindField(const StringPiece& name, const StringPiece& type)
+ static ArtField* FindField(Thread* self, Handle<Class> klass, const StringPiece& name,
+ const StringPiece& type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Finds the given instance field in this class or a superclass.
@@ -795,12 +797,14 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Finds the given static field in this class or a superclass.
- ArtField* FindStaticField(const StringPiece& name, const StringPiece& type)
+ static ArtField* FindStaticField(Thread* self, Handle<Class> klass, const StringPiece& name,
+ const StringPiece& type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Finds the given static field in this class or superclass, only searches classes that
// have the same dex cache.
- ArtField* FindStaticField(const DexCache* dex_cache, uint32_t dex_field_idx)
+ static ArtField* FindStaticField(Thread* self, Handle<Class> klass, const DexCache* dex_cache,
+ uint32_t dex_field_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
ArtField* FindDeclaredStaticField(const StringPiece& name, const StringPiece& type)
@@ -857,6 +861,19 @@
void VisitReferences(mirror::Class* klass, const Visitor& visitor)
NO_THREAD_SAFETY_ANALYSIS;
+ std::string GetDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool DescriptorEquals(const char* match) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ std::string GetArrayDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ const DexFile::ClassDef* GetClassDef() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ uint32_t NumDirectInterfaces() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ uint16_t GetDirectInterfaceTypeIdx(uint32_t idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ static mirror::Class* GetDirectInterface(Thread* self, Handle<mirror::Class> klass, uint32_t idx)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ const char* GetSourceFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ std::string GetLocation() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ const DexFile& GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ const DexFile::TypeList* GetInterfaceTypeList() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
private:
void SetVerifyErrorClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index e0fd6a2..e24602a 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -104,7 +104,7 @@
TEST_F(ObjectTest, Clone) {
ScopedObjectAccess soa(Thread::Current());
- StackHandleScope<1> hs(soa.Self());
+ StackHandleScope<2> hs(soa.Self());
Handle<ObjectArray<Object>> a1(
hs.NewHandle(class_linker_->AllocObjectArray<Object>(soa.Self(), 256)));
size_t s1 = a1->SizeOf();
@@ -115,7 +115,7 @@
TEST_F(ObjectTest, AllocObjectArray) {
ScopedObjectAccess soa(Thread::Current());
- StackHandleScope<1> hs(soa.Self());
+ StackHandleScope<2> hs(soa.Self());
Handle<ObjectArray<Object> > oa(
hs.NewHandle(class_linker_->AllocObjectArray<Object>(soa.Self(), 2)));
EXPECT_EQ(2, oa->GetLength());
@@ -142,12 +142,12 @@
soa.Self()->ClearException();
ASSERT_TRUE(oa->GetClass() != NULL);
- ClassHelper oa_ch(oa->GetClass());
- ASSERT_EQ(2U, oa_ch.NumDirectInterfaces());
+ Handle<mirror::Class> klass(hs.NewHandle(oa->GetClass()));
+ ASSERT_EQ(2U, klass->NumDirectInterfaces());
EXPECT_EQ(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Cloneable;"),
- oa_ch.GetDirectInterface(0));
+ mirror::Class::GetDirectInterface(soa.Self(), klass, 0));
EXPECT_EQ(class_linker_->FindSystemClass(soa.Self(), "Ljava/io/Serializable;"),
- oa_ch.GetDirectInterface(1));
+ mirror::Class::GetDirectInterface(soa.Self(), klass, 1));
}
TEST_F(ObjectTest, AllocArray) {
@@ -682,26 +682,31 @@
TEST_F(ObjectTest, FindStaticField) {
ScopedObjectAccess soa(Thread::Current());
- StackHandleScope<1> hs(soa.Self());
+ StackHandleScope<4> hs(soa.Self());
Handle<String> s(hs.NewHandle(String::AllocFromModifiedUtf8(soa.Self(), "ABC")));
ASSERT_TRUE(s.Get() != NULL);
- Class* c = s->GetClass();
- ASSERT_TRUE(c != NULL);
+ Handle<Class> c(hs.NewHandle(s->GetClass()));
+ ASSERT_TRUE(c.Get() != NULL);
// Wrong type.
EXPECT_TRUE(c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", "I") == NULL);
- EXPECT_TRUE(c->FindStaticField("CASE_INSENSITIVE_ORDER", "I") == NULL);
+ EXPECT_TRUE(mirror::Class::FindStaticField(soa.Self(), c, "CASE_INSENSITIVE_ORDER", "I") == NULL);
// Wrong name.
EXPECT_TRUE(c->FindDeclaredStaticField("cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;") == NULL);
- EXPECT_TRUE(c->FindStaticField("cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;") == NULL);
+ EXPECT_TRUE(
+ mirror::Class::FindStaticField(soa.Self(), c, "cASE_INSENSITIVE_ORDER",
+ "Ljava/util/Comparator;") == NULL);
// Right name and type.
- ArtField* f1 = c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
- ArtField* f2 = c->FindStaticField("CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
- EXPECT_TRUE(f1 != NULL);
- EXPECT_TRUE(f2 != NULL);
- EXPECT_EQ(f1, f2);
+ Handle<ArtField> f1(hs.NewHandle(
+ c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;")));
+ Handle<ArtField> f2(hs.NewHandle(
+ mirror::Class::FindStaticField(soa.Self(), c, "CASE_INSENSITIVE_ORDER",
+ "Ljava/util/Comparator;")));
+ EXPECT_TRUE(f1.Get() != NULL);
+ EXPECT_TRUE(f2.Get() != NULL);
+ EXPECT_EQ(f1.Get(), f2.Get());
// TODO: test static fields via superclasses.
// TODO: test static fields via interfaces.
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index 8d183da..69b05f4 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -262,12 +262,14 @@
}
const DexFile* dex_file = dex_cache->GetDexFile();
const DexFile::FieldId& field_id = dex_file->GetFieldId(field_idx);
- mirror::Class* klass = dex_cache->GetResolvedType(field_id.class_idx_);
- if (klass == NULL) {
+ Thread* const self = Thread::Current();
+ StackHandleScope<1> hs(self);
+ Handle<mirror::Class> klass(hs.NewHandle(dex_cache->GetResolvedType(field_id.class_idx_)));
+ if (klass.Get() == NULL) {
return;
}
if (is_static) {
- field = klass->FindStaticField(dex_cache.Get(), field_idx);
+ field = mirror::Class::FindStaticField(self, klass, dex_cache.Get(), field_idx);
} else {
field = klass->FindInstanceField(dex_cache.Get(), field_idx);
}
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index b6cf7d8..e619dda 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -84,8 +84,9 @@
static jstring Class_getNameNative(JNIEnv* env, jobject javaThis) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Class* c = DecodeClass(soa, javaThis);
- return soa.AddLocalReference<jstring>(c->ComputeName());
+ StackHandleScope<1> hs(soa.Self());
+ mirror::Class* const c = DecodeClass(soa, javaThis);
+ return soa.AddLocalReference<jstring>(mirror::Class::ComputeName(hs.NewHandle(c)));
}
static jobjectArray Class_getProxyInterfaces(JNIEnv* env, jobject javaThis) {
diff --git a/runtime/native/java_lang_reflect_Array.cc b/runtime/native/java_lang_reflect_Array.cc
index 7c6f2f3..db77437 100644
--- a/runtime/native/java_lang_reflect_Array.cc
+++ b/runtime/native/java_lang_reflect_Array.cc
@@ -35,7 +35,7 @@
DCHECK(javaDimArray != NULL);
mirror::Object* dimensions_obj = soa.Decode<mirror::Object*>(javaDimArray);
DCHECK(dimensions_obj->IsArrayInstance());
- DCHECK_STREQ(ClassHelper(dimensions_obj->GetClass()).GetDescriptor(), "[I");
+ DCHECK_STREQ(dimensions_obj->GetClass()->GetDescriptor().c_str(), "[I");
Handle<mirror::IntArray> dimensions_array(
hs.NewHandle(down_cast<mirror::IntArray*>(dimensions_obj)));
mirror::Array* new_array = mirror::Array::CreateMultiArray(soa.Self(), element_class,
diff --git a/runtime/object_utils.h b/runtime/object_utils.h
index b1e8c09..664ac89 100644
--- a/runtime/object_utils.h
+++ b/runtime/object_utils.h
@@ -66,171 +66,6 @@
DISALLOW_COPY_AND_ASSIGN(ObjectLock);
};
-class ClassHelper {
- public:
- explicit ClassHelper(mirror::Class* c )
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- : interface_type_list_(nullptr), klass_(nullptr) {
- if (c != nullptr) {
- ChangeClass(c);
- }
- }
-
- void ChangeClass(mirror::Class* new_c)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- CHECK(new_c != nullptr) << "klass_=" << klass_; // Log what we were changing from if any
- if (!new_c->IsClass()) {
- LOG(FATAL) << "new_c=" << new_c << " cc " << new_c->GetClass() << " ccc "
- << ((new_c->GetClass() != nullptr) ? new_c->GetClass()->GetClass() : nullptr);
- }
- klass_ = new_c;
- interface_type_list_ = nullptr;
- }
-
- // The returned const char* is only guaranteed to be valid for the lifetime of the ClassHelper.
- // If you need it longer, copy it into a std::string.
- const char* GetDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- CHECK(klass_ != nullptr);
- if (UNLIKELY(klass_->IsArrayClass())) {
- return GetArrayDescriptor();
- } else if (UNLIKELY(klass_->IsPrimitive())) {
- return Primitive::Descriptor(klass_->GetPrimitiveType());
- } else if (UNLIKELY(klass_->IsProxyClass())) {
- descriptor_ = GetClassLinker()->GetDescriptorForProxy(klass_);
- return descriptor_.c_str();
- } else {
- const DexFile& dex_file = GetDexFile();
- const DexFile::TypeId& type_id = dex_file.GetTypeId(GetClassDef()->class_idx_);
- return dex_file.GetTypeDescriptor(type_id);
- }
- }
-
- const char* GetArrayDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- std::string result("[");
- mirror::Class* saved_klass = klass_;
- CHECK(saved_klass != nullptr);
- ChangeClass(klass_->GetComponentType());
- result += GetDescriptor();
- ChangeClass(saved_klass);
- descriptor_ = result;
- return descriptor_.c_str();
- }
-
- const DexFile::ClassDef* GetClassDef() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(klass_ != nullptr);
- uint16_t class_def_idx = klass_->GetDexClassDefIndex();
- if (class_def_idx == DexFile::kDexNoIndex16) {
- return nullptr;
- }
- return &GetDexFile().GetClassDef(class_def_idx);
- }
-
- uint32_t NumDirectInterfaces() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(klass_ != nullptr);
- if (klass_->IsPrimitive()) {
- return 0;
- } else if (klass_->IsArrayClass()) {
- return 2;
- } else if (klass_->IsProxyClass()) {
- mirror::SynthesizedProxyClass* proxyClass = reinterpret_cast<mirror::SynthesizedProxyClass*>(klass_);
- mirror::ObjectArray<mirror::Class>* interfaces = proxyClass->GetInterfaces();
- return interfaces != nullptr ? interfaces->GetLength() : 0;
- } else {
- const DexFile::TypeList* interfaces = GetInterfaceTypeList();
- if (interfaces == nullptr) {
- return 0;
- } else {
- return interfaces->Size();
- }
- }
- }
-
- uint16_t GetDirectInterfaceTypeIdx(uint32_t idx)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(klass_ != nullptr);
- DCHECK(!klass_->IsPrimitive());
- DCHECK(!klass_->IsArrayClass());
- return GetInterfaceTypeList()->GetTypeItem(idx).type_idx_;
- }
-
- mirror::Class* GetDirectInterface(uint32_t idx)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(klass_ != nullptr);
- DCHECK(!klass_->IsPrimitive());
- if (klass_->IsArrayClass()) {
- if (idx == 0) {
- return GetClassLinker()->FindSystemClass(Thread::Current(), "Ljava/lang/Cloneable;");
- } else {
- DCHECK_EQ(1U, idx);
- return GetClassLinker()->FindSystemClass(Thread::Current(), "Ljava/io/Serializable;");
- }
- } else if (klass_->IsProxyClass()) {
- mirror::SynthesizedProxyClass* proxyClass = reinterpret_cast<mirror::SynthesizedProxyClass*>(klass_);
- mirror::ObjectArray<mirror::Class>* interfaces = proxyClass->GetInterfaces();
- DCHECK(interfaces != nullptr);
- return interfaces->Get(idx);
- } else {
- uint16_t type_idx = GetDirectInterfaceTypeIdx(idx);
- mirror::Class* interface = GetDexCache()->GetResolvedType(type_idx);
- if (interface == nullptr) {
- interface = GetClassLinker()->ResolveType(GetDexFile(), type_idx, klass_);
- CHECK(interface != nullptr || Thread::Current()->IsExceptionPending());
- }
- return interface;
- }
- }
-
- const char* GetSourceFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- std::string descriptor(GetDescriptor());
- const DexFile& dex_file = GetDexFile();
- const DexFile::ClassDef* dex_class_def = GetClassDef();
- CHECK(dex_class_def != nullptr) << "No class def for class " << PrettyClass(klass_);
- return dex_file.GetSourceFile(*dex_class_def);
- }
-
- std::string GetLocation() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- mirror::DexCache* dex_cache = GetDexCache();
- if (dex_cache != nullptr && !klass_->IsProxyClass()) {
- return dex_cache->GetLocation()->ToModifiedUtf8();
- } else {
- // Arrays and proxies are generated and have no corresponding dex file location.
- return "generated class";
- }
- }
-
- const DexFile& GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return *GetDexCache()->GetDexFile();
- }
-
- mirror::DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return klass_->GetDexCache();
- }
-
- private:
- const DexFile::TypeList* GetInterfaceTypeList()
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- const DexFile::TypeList* result = interface_type_list_;
- if (result == nullptr) {
- const DexFile::ClassDef* class_def = GetClassDef();
- if (class_def != nullptr) {
- result = GetDexFile().GetInterfacesList(*class_def);
- interface_type_list_ = result;
- }
- }
- return result;
- }
-
- ClassLinker* GetClassLinker() ALWAYS_INLINE {
- return Runtime::Current()->GetClassLinker();
- }
-
- const DexFile::TypeList* interface_type_list_;
- mirror::Class* klass_;
- std::string descriptor_;
-
- DISALLOW_COPY_AND_ASSIGN(ClassHelper);
-};
-
class FieldHelper {
public:
FieldHelper() : field_(nullptr) {}
@@ -304,8 +139,7 @@
DCHECK(field_->IsStatic());
DCHECK_LT(field_index, 2U);
// 0 == Class[] interfaces; 1 == Class[][] throws;
- ClassHelper kh(field_->GetDeclaringClass());
- declaring_class_descriptor_ = kh.GetDescriptor();
+ declaring_class_descriptor_ = field_->GetDeclaringClass()->GetDescriptor();
return declaring_class_descriptor_.c_str();
}
const DexFile& dex_file = GetDexFile();
@@ -468,7 +302,7 @@
}
const char* GetDeclaringClassSourceFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return ClassHelper(method_->GetDeclaringClass()).GetSourceFile();
+ return method_->GetDeclaringClass()->GetSourceFile();
}
uint16_t GetClassDefIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc
index 8517e34..f38fb21 100644
--- a/runtime/proxy_test.cc
+++ b/runtime/proxy_test.cc
@@ -107,30 +107,33 @@
TEST_F(ProxyTest, ProxyClassHelper) {
ScopedObjectAccess soa(Thread::Current());
jobject jclass_loader = LoadDex("Interfaces");
- StackHandleScope<1> hs(soa.Self());
+ StackHandleScope<4> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
- mirror::Class* I = class_linker_->FindClass(soa.Self(), "LInterfaces$I;", class_loader);
- mirror::Class* J = class_linker_->FindClass(soa.Self(), "LInterfaces$J;", class_loader);
- ASSERT_TRUE(I != nullptr);
- ASSERT_TRUE(J != nullptr);
- std::vector<mirror::Class*> interfaces;
- interfaces.push_back(I);
- interfaces.push_back(J);
+ Handle<mirror::Class> I(hs.NewHandle(
+ class_linker_->FindClass(soa.Self(), "LInterfaces$I;", class_loader)));
+ Handle<mirror::Class> J(hs.NewHandle(
+ class_linker_->FindClass(soa.Self(), "LInterfaces$J;", class_loader)));
+ ASSERT_TRUE(I.Get() != nullptr);
+ ASSERT_TRUE(J.Get() != nullptr);
- mirror::Class* proxyClass = GenerateProxyClass(soa, jclass_loader, "$Proxy1234", interfaces);
- ASSERT_TRUE(proxyClass != nullptr);
- ASSERT_TRUE(proxyClass->IsProxyClass());
- ASSERT_TRUE(proxyClass->IsInitialized());
+ std::vector<mirror::Class*> interfaces;
+ interfaces.push_back(I.Get());
+ interfaces.push_back(J.Get());
+ Handle<mirror::Class> proxy_class(hs.NewHandle(
+ GenerateProxyClass(soa, jclass_loader, "$Proxy1234", interfaces)));
+ interfaces.clear(); // Don't least possibly stale objects in the array as good practice.
+ ASSERT_TRUE(proxy_class.Get() != nullptr);
+ ASSERT_TRUE(proxy_class->IsProxyClass());
+ ASSERT_TRUE(proxy_class->IsInitialized());
// Check ClassHelper for proxy.
- ClassHelper kh(proxyClass);
- EXPECT_EQ(kh.NumDirectInterfaces(), 2U); // Interfaces$I and Interfaces$J.
- EXPECT_EQ(I, kh.GetDirectInterface(0));
- EXPECT_EQ(J, kh.GetDirectInterface(1));
- std::string proxyClassDescriptor(kh.GetDescriptor());
- EXPECT_EQ("L$Proxy1234;", proxyClassDescriptor);
+ EXPECT_EQ(proxy_class->NumDirectInterfaces(), 2U); // Interfaces$I and Interfaces$J.
+ EXPECT_EQ(I.Get(), mirror::Class::GetDirectInterface(soa.Self(), proxy_class, 0));
+ EXPECT_EQ(J.Get(), mirror::Class::GetDirectInterface(soa.Self(), proxy_class, 1));
+ std::string proxy_class_descriptor(proxy_class->GetDescriptor());
+ EXPECT_STREQ("L$Proxy1234;", proxy_class_descriptor.c_str());
}
// Creates a proxy class and check FieldHelper works correctly.
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 98310e6..cbd66a6 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -242,22 +242,21 @@
}
#define DO_FIRST_ARG(match_descriptor, get_fn, append) { \
- const StringPiece src_descriptor(arg != nullptr \
- ? ClassHelper(arg->GetClass<>()).GetDescriptor() \
- : "null"); \
- if (LIKELY(src_descriptor == match_descriptor)) { \
+ if (LIKELY(arg != nullptr && arg->GetClass<>()->DescriptorEquals(match_descriptor))) { \
mirror::ArtField* primitive_field = arg->GetClass()->GetIFields()->Get(0); \
append(primitive_field-> get_fn(arg));
#define DO_ARG(match_descriptor, get_fn, append) \
- } else if (LIKELY(src_descriptor == match_descriptor)) { \
+ } else if (LIKELY(arg != nullptr && \
+ arg->GetClass<>()->DescriptorEquals(match_descriptor))) { \
mirror::ArtField* primitive_field = arg->GetClass()->GetIFields()->Get(0); \
append(primitive_field-> get_fn(arg));
#define DO_FAIL(expected) \
} else { \
if (arg->GetClass<>()->IsPrimitive()) { \
- ThrowIllegalPrimitiveArgumentException(expected, src_descriptor); \
+ ThrowIllegalPrimitiveArgumentException(expected, \
+ arg->GetClass<>()->GetDescriptor().c_str()); \
} else { \
ThrowIllegalArgumentException(nullptr, \
StringPrintf("method %s argument %zd has type %s, got %s", \
@@ -742,32 +741,32 @@
}
JValue boxed_value;
- const StringPiece src_descriptor(ClassHelper(o->GetClass()).GetDescriptor());
+ mirror::Class* klass = o->GetClass();
mirror::Class* src_class = nullptr;
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
mirror::ArtField* primitive_field = o->GetClass()->GetIFields()->Get(0);
- if (src_descriptor == "Ljava/lang/Boolean;") {
+ if (klass->DescriptorEquals("Ljava/lang/Boolean;")) {
src_class = class_linker->FindPrimitiveClass('Z');
boxed_value.SetZ(primitive_field->GetBoolean(o));
- } else if (src_descriptor == "Ljava/lang/Byte;") {
+ } else if (klass->DescriptorEquals("Ljava/lang/Byte;")) {
src_class = class_linker->FindPrimitiveClass('B');
boxed_value.SetB(primitive_field->GetByte(o));
- } else if (src_descriptor == "Ljava/lang/Character;") {
+ } else if (klass->DescriptorEquals("Ljava/lang/Character;")) {
src_class = class_linker->FindPrimitiveClass('C');
boxed_value.SetC(primitive_field->GetChar(o));
- } else if (src_descriptor == "Ljava/lang/Float;") {
+ } else if (klass->DescriptorEquals("Ljava/lang/Float;")) {
src_class = class_linker->FindPrimitiveClass('F');
boxed_value.SetF(primitive_field->GetFloat(o));
- } else if (src_descriptor == "Ljava/lang/Double;") {
+ } else if (klass->DescriptorEquals("Ljava/lang/Double;")) {
src_class = class_linker->FindPrimitiveClass('D');
boxed_value.SetD(primitive_field->GetDouble(o));
- } else if (src_descriptor == "Ljava/lang/Integer;") {
+ } else if (klass->DescriptorEquals("Ljava/lang/Integer;")) {
src_class = class_linker->FindPrimitiveClass('I');
boxed_value.SetI(primitive_field->GetInt(o));
- } else if (src_descriptor == "Ljava/lang/Long;") {
+ } else if (klass->DescriptorEquals("Ljava/lang/Long;")) {
src_class = class_linker->FindPrimitiveClass('J');
boxed_value.SetJ(primitive_field->GetLong(o));
- } else if (src_descriptor == "Ljava/lang/Short;") {
+ } else if (klass->DescriptorEquals("Ljava/lang/Short;")) {
src_class = class_linker->FindPrimitiveClass('S');
boxed_value.SetS(primitive_field->GetShort(o));
} else {
@@ -775,7 +774,7 @@
StringPrintf("%s has type %s, got %s",
UnboxingFailureKind(f).c_str(),
PrettyDescriptor(dst_class).c_str(),
- PrettyDescriptor(src_descriptor.data()).c_str()).c_str());
+ PrettyDescriptor(o->GetClass()->GetDescriptor()).c_str()).c_str());
return false;
}
diff --git a/runtime/stack.h b/runtime/stack.h
index 963983a..2e32f51 100644
--- a/runtime/stack.h
+++ b/runtime/stack.h
@@ -306,6 +306,11 @@
return method_;
}
+ mirror::ArtMethod** GetMethodAddress() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(method_ != nullptr);
+ return &method_;
+ }
+
mirror::Object* GetThisObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
mirror::Object* GetThisObject(uint16_t num_ins) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -389,12 +394,7 @@
#endif
// Link to previous shadow frame or NULL.
ShadowFrame* link_;
-#if defined(ART_USE_PORTABLE_COMPILER)
- // TODO: make const in the portable case.
mirror::ArtMethod* method_;
-#else
- mirror::ArtMethod* const method_;
-#endif
uint32_t dex_pc_;
uint32_t vregs_[0];
@@ -518,6 +518,16 @@
}
}
+ mirror::ArtMethod** GetMethodAddress() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ if (cur_shadow_frame_ != nullptr) {
+ return cur_shadow_frame_->GetMethodAddress();
+ } else if (cur_quick_frame_ != nullptr) {
+ return cur_quick_frame_;
+ } else {
+ return nullptr;
+ }
+ }
+
bool IsShadowFrame() const {
return cur_shadow_frame_ != nullptr;
}
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 415cc0b..488961e 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -1962,7 +1962,10 @@
}
void VisitShadowFrame(ShadowFrame* shadow_frame) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- mirror::ArtMethod* m = shadow_frame->GetMethod();
+ mirror::ArtMethod** method_addr = shadow_frame->GetMethodAddress();
+ visitor_(reinterpret_cast<mirror::Object**>(method_addr), 0 /*ignored*/, this);
+ mirror::ArtMethod* m = *method_addr;
+ DCHECK(m != nullptr);
size_t num_regs = shadow_frame->NumberOfVRegs();
if (m->IsNative() || shadow_frame->HasReferenceArray()) {
// handle scope for JNI or References for interpreter.
@@ -2003,7 +2006,9 @@
private:
void VisitQuickFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- mirror::ArtMethod* m = GetMethod();
+ mirror::ArtMethod** method_addr = GetMethodAddress();
+ visitor_(reinterpret_cast<mirror::Object**>(method_addr), 0 /*ignored*/, this);
+ mirror::ArtMethod* m = *method_addr;
// Process register map (which native and runtime methods don't have)
if (!m->IsNative() && !m->IsRuntimeMethod() && !m->IsProxyMethod()) {
const uint8_t* native_gc_map = m->GetNativeGcMap();
diff --git a/runtime/thread.h b/runtime/thread.h
index be7634f..f7aef42 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -98,7 +98,7 @@
// Space to throw a StackOverflowError in.
// TODO: shrink reserved space, in particular for 64bit.
#if defined(__x86_64__)
- static constexpr size_t kStackOverflowReservedBytes = 24 * KB;
+ static constexpr size_t kStackOverflowReservedBytes = 32 * KB;
#elif defined(__aarch64__)
// Worst-case, we would need about 2.6x the amount of x86_64 for many more registers.
// But this one works rather well.
diff --git a/runtime/utils.cc b/runtime/utils.cc
index e4af8e4..02b955a 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -230,7 +230,7 @@
if (klass == NULL) {
return "null";
}
- return PrettyDescriptor(ClassHelper(klass).GetDescriptor());
+ return PrettyDescriptor(klass->GetDescriptor());
}
std::string PrettyDescriptor(const std::string& descriptor) {
@@ -412,11 +412,9 @@
if (obj->GetClass() == NULL) {
return "(raw)";
}
- ClassHelper kh(obj->GetClass());
- std::string result(PrettyDescriptor(kh.GetDescriptor()));
+ std::string result(PrettyDescriptor(obj->GetClass()->GetDescriptor()));
if (obj->IsClass()) {
- kh.ChangeClass(obj->AsClass());
- result += "<" + PrettyDescriptor(kh.GetDescriptor()) + ">";
+ result += "<" + PrettyDescriptor(obj->AsClass()->GetDescriptor()) + ">";
}
return result;
}
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 9dd366d..0a31f63 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -93,11 +93,10 @@
}
bool early_failure = false;
std::string failure_message;
- ClassHelper kh(klass);
- const DexFile& dex_file = kh.GetDexFile();
- const DexFile::ClassDef* class_def = kh.GetClassDef();
+ const DexFile& dex_file = klass->GetDexFile();
+ const DexFile::ClassDef* class_def = klass->GetClassDef();
mirror::Class* super = klass->GetSuperClass();
- if (super == NULL && strcmp("Ljava/lang/Object;", kh.GetDescriptor()) != 0) {
+ if (super == NULL && "Ljava/lang/Object;" != klass->GetDescriptor()) {
early_failure = true;
failure_message = " that has no super class";
} else if (super != NULL && super->IsFinal()) {
@@ -116,7 +115,7 @@
return kHardFailure;
}
StackHandleScope<2> hs(Thread::Current());
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(kh.GetDexCache()));
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
return VerifyClass(&dex_file, dex_cache, class_loader, class_def, allow_soft_failures, error);
}
@@ -3057,7 +3056,7 @@
if (method_type != METHOD_INTERFACE && !actual_arg_type.IsZero()) {
mirror::Class* klass = res_method->GetDeclaringClass();
const RegType& res_method_class =
- reg_types_.FromClass(ClassHelper(klass).GetDescriptor(), klass,
+ reg_types_.FromClass(klass->GetDescriptor().c_str(), klass,
klass->CannotBeAssignedFromOtherTypes());
if (!res_method_class.IsAssignableFrom(actual_arg_type)) {
Fail(actual_arg_type.IsUnresolvedTypes() ? VERIFY_ERROR_NO_CLASS:
@@ -3182,7 +3181,7 @@
if (!actual_arg_type.IsZero()) {
mirror::Class* klass = res_method->GetDeclaringClass();
const RegType& res_method_class =
- reg_types_.FromClass(ClassHelper(klass).GetDescriptor(), klass,
+ reg_types_.FromClass(klass->GetDescriptor().c_str(), klass,
klass->CannotBeAssignedFromOtherTypes());
if (!res_method_class.IsAssignableFrom(actual_arg_type)) {
Fail(actual_arg_type.IsUnresolvedTypes() ? VERIFY_ERROR_NO_CLASS :
diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc
index c6f3e5c..8df1e5d 100644
--- a/runtime/verifier/reg_type.cc
+++ b/runtime/verifier/reg_type.cc
@@ -621,7 +621,7 @@
if (super_klass != NULL) {
// A super class of a precise type isn't precise as a precise type indicates the register
// holds exactly that type.
- return cache->FromClass(ClassHelper(super_klass).GetDescriptor(), super_klass, false);
+ return cache->FromClass(super_klass->GetDescriptor().c_str(), super_klass, false);
} else {
return cache->Zero();
}
@@ -899,7 +899,7 @@
} else if (c2 == join_class && !incoming_type.IsPreciseReference()) {
return incoming_type;
} else {
- return reg_types->FromClass(ClassHelper(join_class).GetDescriptor(), join_class, false);
+ return reg_types->FromClass(join_class->GetDescriptor().c_str(), join_class, false);
}
}
} else {
diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc
index 689a33e..ff9edbb 100644
--- a/runtime/verifier/reg_type_cache.cc
+++ b/runtime/verifier/reg_type_cache.cc
@@ -567,7 +567,7 @@
return FromDescriptor(loader, component.c_str(), false);
} else {
mirror::Class* klass = array.GetClass()->GetComponentType();
- return FromClass(ClassHelper(klass).GetDescriptor(), klass,
+ return FromClass(klass->GetDescriptor().c_str(), klass,
klass->CannotBeAssignedFromOtherTypes());
}
}