summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/art.go5
-rw-r--r--compiler/optimizing/code_generator_mips.cc2
-rw-r--r--compiler/optimizing/emit_swap_mips_test.cc32
-rw-r--r--compiler/optimizing/optimizing_cfi_test_expected.inc12
-rw-r--r--compiler/utils/mips/assembler_mips.cc10
-rw-r--r--compiler/utils/mips/assembler_mips_test.cc8
-rw-r--r--dex2oat/dex2oat_test.cc1
-rw-r--r--dexlayout/dexlayout.cc25
-rw-r--r--runtime/arch/mips/asm_support_mips.S26
-rw-r--r--runtime/arch/mips/asm_support_mips.h2
-rw-r--r--runtime/arch/mips/context_mips.cc15
-rw-r--r--runtime/arch/mips/jni_entrypoints_mips.S10
-rw-r--r--runtime/arch/mips/quick_entrypoints_mips.S214
-rw-r--r--runtime/arch/mips/quick_method_frame_info_mips.h18
-rw-r--r--runtime/common_dex_operations.h26
-rw-r--r--runtime/dex_file_annotations.cc17
-rw-r--r--runtime/interpreter/interpreter.cc6
-rw-r--r--runtime/runtime.cc4
-rw-r--r--test/1929-exception-catch-exception/build20
-rw-r--r--test/992-source-data/expected.txt12
-rw-r--r--test/992-source-data/source_file.cc13
-rw-r--r--test/992-source-data/src/art/Test992.java21
22 files changed, 326 insertions, 173 deletions
diff --git a/build/art.go b/build/art.go
index 1bcaf51a1d..452b3485a3 100644
--- a/build/art.go
+++ b/build/art.go
@@ -97,6 +97,11 @@ func globalFlags(ctx android.BaseContext) ([]string, []string) {
asflags = append(asflags, "-DART_ENABLE_ADDRESS_SANITIZER=1")
}
+ if envTrue(ctx, "ART_MIPS32_CHECK_ALIGNMENT") {
+ // Enable the use of MIPS32 CHECK_ALIGNMENT macro for debugging purposes
+ asflags = append(asflags, "-DART_MIPS32_CHECK_ALIGNMENT")
+ }
+
return cflags, asflags
}
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index 3ba107a283..2f65e8c958 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -1300,7 +1300,7 @@ void ParallelMoveResolverMIPS::Exchange(int index1, int index2, bool double_slot
// automatically unspilled when the scratch scope object is destroyed).
ScratchRegisterScope ensure_scratch(this, TMP, V0, codegen_->GetNumberOfCoreRegisters());
// If V0 spills onto the stack, SP-relative offsets need to be adjusted.
- int stack_offset = ensure_scratch.IsSpilled() ? kMipsWordSize : 0;
+ int stack_offset = ensure_scratch.IsSpilled() ? kStackAlignment : 0;
for (int i = 0; i <= (double_slot ? 1 : 0); i++, stack_offset += kMipsWordSize) {
__ LoadFromOffset(kLoadWord,
Register(ensure_scratch.GetRegister()),
diff --git a/compiler/optimizing/emit_swap_mips_test.cc b/compiler/optimizing/emit_swap_mips_test.cc
index 36e932c67a..b63914faf7 100644
--- a/compiler/optimizing/emit_swap_mips_test.cc
+++ b/compiler/optimizing/emit_swap_mips_test.cc
@@ -238,14 +238,14 @@ TEST_F(EmitSwapMipsTest, TwoStackSlots) {
DataType::Type::kInt32,
nullptr);
const char* expected =
- "addiu $sp, $sp, -4\n"
+ "addiu $sp, $sp, -16\n"
"sw $v0, 0($sp)\n"
- "lw $v0, 56($sp)\n"
- "lw $t8, 52($sp)\n"
- "sw $v0, 52($sp)\n"
- "sw $t8, 56($sp)\n"
+ "lw $v0, 68($sp)\n"
+ "lw $t8, 64($sp)\n"
+ "sw $v0, 64($sp)\n"
+ "sw $t8, 68($sp)\n"
"lw $v0, 0($sp)\n"
- "addiu $sp, $sp, 4\n";
+ "addiu $sp, $sp, 16\n";
DriverWrapper(moves_, expected, "TwoStackSlots");
}
@@ -261,18 +261,18 @@ TEST_F(EmitSwapMipsTest, TwoDoubleStackSlots) {
DataType::Type::kInt64,
nullptr);
const char* expected =
- "addiu $sp, $sp, -4\n"
+ "addiu $sp, $sp, -16\n"
"sw $v0, 0($sp)\n"
- "lw $v0, 60($sp)\n"
- "lw $t8, 52($sp)\n"
- "sw $v0, 52($sp)\n"
- "sw $t8, 60($sp)\n"
- "lw $v0, 64($sp)\n"
- "lw $t8, 56($sp)\n"
- "sw $v0, 56($sp)\n"
- "sw $t8, 64($sp)\n"
+ "lw $v0, 72($sp)\n"
+ "lw $t8, 64($sp)\n"
+ "sw $v0, 64($sp)\n"
+ "sw $t8, 72($sp)\n"
+ "lw $v0, 76($sp)\n"
+ "lw $t8, 68($sp)\n"
+ "sw $v0, 68($sp)\n"
+ "sw $t8, 76($sp)\n"
"lw $v0, 0($sp)\n"
- "addiu $sp, $sp, 4\n";
+ "addiu $sp, $sp, 16\n";
DriverWrapper(moves_, expected, "TwoDoubleStackSlots");
}
diff --git a/compiler/optimizing/optimizing_cfi_test_expected.inc b/compiler/optimizing/optimizing_cfi_test_expected.inc
index fde55cb92f..1e82c4b0f7 100644
--- a/compiler/optimizing/optimizing_cfi_test_expected.inc
+++ b/compiler/optimizing/optimizing_cfi_test_expected.inc
@@ -330,10 +330,10 @@ static constexpr uint8_t expected_cfi_kThumb2_adjust[] = {
static constexpr uint8_t expected_asm_kMips_adjust_head[] = {
0xC0, 0xFF, 0xBD, 0x27, 0x3C, 0x00, 0xBF, 0xAF, 0x38, 0x00, 0xB1, 0xAF,
0x34, 0x00, 0xB0, 0xAF, 0x28, 0x00, 0xB6, 0xF7, 0x20, 0x00, 0xB4, 0xF7,
- 0x08, 0x00, 0x80, 0x14, 0xFC, 0xFF, 0xBD, 0x27,
+ 0x08, 0x00, 0x80, 0x14, 0xF0, 0xFF, 0xBD, 0x27,
0x00, 0x00, 0xBF, 0xAF, 0x00, 0x00, 0x10, 0x04, 0x02, 0x00, 0x01, 0x3C,
0x18, 0x00, 0x21, 0x34, 0x21, 0x08, 0x3F, 0x00, 0x00, 0x00, 0xBF, 0x8F,
- 0x09, 0x00, 0x20, 0x00, 0x04, 0x00, 0xBD, 0x27,
+ 0x09, 0x00, 0x20, 0x00, 0x10, 0x00, 0xBD, 0x27,
};
static constexpr uint8_t expected_asm_kMips_adjust_tail[] = {
0x3C, 0x00, 0xBF, 0x8F, 0x38, 0x00, 0xB1, 0x8F, 0x34, 0x00, 0xB0, 0x8F,
@@ -342,7 +342,7 @@ static constexpr uint8_t expected_asm_kMips_adjust_tail[] = {
};
static constexpr uint8_t expected_cfi_kMips_adjust[] = {
0x44, 0x0E, 0x40, 0x44, 0x9F, 0x01, 0x44, 0x91, 0x02, 0x44, 0x90, 0x03,
- 0x50, 0x0E, 0x44, 0x60, 0x0E, 0x40, 0x04, 0x04, 0x00, 0x02, 0x00, 0x0A,
+ 0x50, 0x0E, 0x50, 0x60, 0x0E, 0x40, 0x04, 0x04, 0x00, 0x02, 0x00, 0x0A,
0x44, 0xDF, 0x44, 0xD1, 0x44, 0xD0, 0x50, 0x0E, 0x00, 0x0B, 0x0E, 0x40,
};
// 0x00000000: addiu sp, sp, -64
@@ -356,8 +356,8 @@ static constexpr uint8_t expected_cfi_kMips_adjust[] = {
// 0x00000010: sdc1 f22, +40(sp)
// 0x00000014: sdc1 f20, +32(sp)
// 0x00000018: bnez a0, 0x0000003c ; +36
-// 0x0000001c: addiu sp, sp, -4
-// 0x00000020: .cfi_def_cfa_offset: 68
+// 0x0000001c: addiu sp, sp, -16
+// 0x00000020: .cfi_def_cfa_offset: 80
// 0x00000020: sw ra, +0(sp)
// 0x00000024: nal
// 0x00000028: lui at, 2
@@ -365,7 +365,7 @@ static constexpr uint8_t expected_cfi_kMips_adjust[] = {
// 0x00000030: addu at, at, ra
// 0x00000034: lw ra, +0(sp)
// 0x00000038: jr at
-// 0x0000003c: addiu sp, sp, 4
+// 0x0000003c: addiu sp, sp, 16
// 0x00000040: .cfi_def_cfa_offset: 64
// 0x00000040: nop
// ...
diff --git a/compiler/utils/mips/assembler_mips.cc b/compiler/utils/mips/assembler_mips.cc
index cbb2c0ea47..9545ca6869 100644
--- a/compiler/utils/mips/assembler_mips.cc
+++ b/compiler/utils/mips/assembler_mips.cc
@@ -1863,20 +1863,20 @@ void MipsAssembler::Not(Register rd, Register rs) {
}
void MipsAssembler::Push(Register rs) {
- IncreaseFrameSize(kMipsWordSize);
+ IncreaseFrameSize(kStackAlignment);
Sw(rs, SP, 0);
}
void MipsAssembler::Pop(Register rd) {
Lw(rd, SP, 0);
- DecreaseFrameSize(kMipsWordSize);
+ DecreaseFrameSize(kStackAlignment);
}
void MipsAssembler::PopAndReturn(Register rd, Register rt) {
bool reordering = SetReorder(false);
Lw(rd, SP, 0);
Jr(rt);
- DecreaseFrameSize(kMipsWordSize); // Single instruction in delay slot.
+ DecreaseFrameSize(kStackAlignment); // Single instruction in delay slot.
SetReorder(reordering);
}
@@ -4588,7 +4588,7 @@ void MipsAssembler::EmitBranch(uint32_t branch_id) {
Addu(AT, AT, RA);
Lw(RA, SP, 0);
Jr(AT);
- DecreaseFrameSize(kMipsWordSize);
+ DecreaseFrameSize(kStackAlignment);
break;
case Branch::kLongCondBranch:
// The comment on case 'Branch::kLongUncondBranch' applies here as well.
@@ -4608,7 +4608,7 @@ void MipsAssembler::EmitBranch(uint32_t branch_id) {
Addu(AT, AT, RA);
Lw(RA, SP, 0);
Jr(AT);
- DecreaseFrameSize(kMipsWordSize);
+ DecreaseFrameSize(kStackAlignment);
break;
case Branch::kLongCall:
DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot);
diff --git a/compiler/utils/mips/assembler_mips_test.cc b/compiler/utils/mips/assembler_mips_test.cc
index 9397be4c09..b027d3a549 100644
--- a/compiler/utils/mips/assembler_mips_test.cc
+++ b/compiler/utils/mips/assembler_mips_test.cc
@@ -2803,7 +2803,7 @@ TEST_F(AssemblerMIPSTest, LongBranchReorder) {
oss <<
".set noreorder\n"
"addiu $t0, $t1, 0x5678\n"
- "addiu $sp, $sp, -4\n"
+ "addiu $sp, $sp, -16\n"
"sw $ra, 0($sp)\n"
"bltzal $zero, .+4\n"
"lui $at, 0x" << std::hex << High16Bits(offset_forward) << "\n"
@@ -2811,11 +2811,11 @@ TEST_F(AssemblerMIPSTest, LongBranchReorder) {
"addu $at, $at, $ra\n"
"lw $ra, 0($sp)\n"
"jalr $zero, $at\n"
- "addiu $sp, $sp, 4\n" <<
+ "addiu $sp, $sp, 16\n" <<
RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") <<
RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") <<
"addiu $t0, $t1, 0x5678\n"
- "addiu $sp, $sp, -4\n"
+ "addiu $sp, $sp, -16\n"
"sw $ra, 0($sp)\n"
"bltzal $zero, .+4\n"
"lui $at, 0x" << std::hex << High16Bits(offset_back) << "\n"
@@ -2823,7 +2823,7 @@ TEST_F(AssemblerMIPSTest, LongBranchReorder) {
"addu $at, $at, $ra\n"
"lw $ra, 0($sp)\n"
"jalr $zero, $at\n"
- "addiu $sp, $sp, 4\n";
+ "addiu $sp, $sp, 16\n";
std::string expected = oss.str();
DriverStr(expected, "LongBranchReorder");
EXPECT_EQ(__ GetLabelLocation(&patcher_label1), 0 * 4u);
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index 75859ca77f..21768d3126 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -968,6 +968,7 @@ class Dex2oatWatchdogTest : public Dex2oatTest {
std::string swap_location = GetOdexDir() + "/Dex2OatSwapTest.odex.swap";
copy.push_back("--swap-file=" + swap_location);
+ copy.push_back("-j512"); // Excessive idle threads just slow down dex2oat.
GenerateOdexForTest(dex_location,
odex_location,
CompilerFilter::kSpeed,
diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc
index 957fb4944d..731040bc50 100644
--- a/dexlayout/dexlayout.cc
+++ b/dexlayout/dexlayout.cc
@@ -1794,6 +1794,10 @@ int32_t DexLayout::LayoutCodeItems(const DexFile* dex_file,
}
}
+ // Removing duplicate CodeItems may expose other issues with downstream
+ // optimizations such as quickening. But we need to ensure at least the weak
+ // forms of it currently in use do not break layout optimizations.
+ std::map<dex_ir::CodeItem*, uint32_t> original_code_item_offset;
// Total_diff includes diffs generated by clinits, executed, and non-executed methods.
int32_t total_diff = 0;
// The relative placement has no effect on correctness; it is used to ensure
@@ -1812,11 +1816,22 @@ int32_t DexLayout::LayoutCodeItems(const DexFile* dex_file,
dex_ir::CodeItem* code_item = method->GetCodeItem();
if (code_item != nullptr &&
code_items_set.find(code_item) != code_items_set.end()) {
- diff += UnsignedLeb128Size(code_item_offset)
- - UnsignedLeb128Size(code_item->GetOffset());
- code_item->SetOffset(code_item_offset);
- code_item_offset +=
- RoundUp(code_item->GetSize(), kDexCodeItemAlignment);
+ // Compute where the CodeItem was originally laid out.
+ uint32_t original_offset = code_item->GetOffset();
+ auto it = original_code_item_offset.find(code_item);
+ if (it != original_code_item_offset.end()) {
+ original_offset = it->second;
+ } else {
+ original_code_item_offset[code_item] = code_item->GetOffset();
+ // Assign the new offset and move the pointer to allocate space.
+ code_item->SetOffset(code_item_offset);
+ code_item_offset +=
+ RoundUp(code_item->GetSize(), kDexCodeItemAlignment);
+ }
+ // Update the size of the encoded methods to reflect that the offset difference
+ // may have changed the ULEB128 length.
+ diff +=
+ UnsignedLeb128Size(code_item->GetOffset()) - UnsignedLeb128Size(original_offset);
}
}
}
diff --git a/runtime/arch/mips/asm_support_mips.S b/runtime/arch/mips/asm_support_mips.S
index 50095ae77e..fa51059d3a 100644
--- a/runtime/arch/mips/asm_support_mips.S
+++ b/runtime/arch/mips/asm_support_mips.S
@@ -173,4 +173,30 @@
.set pop
.endm
+// This utility macro is used to check whether the address contained in
+// a register is suitably aligned. Default usage is confirm that the
+// address stored in $sp is a multiple of 16. It can be used for other
+// alignments, and for other base address registers, if needed.
+//
+// Enable this macro by running the shell command:
+//
+// export ART_MIPS32_CHECK_ALIGNMENT=true
+//
+// NOTE: The value of alignment must be a power of 2, and must fit in an
+// unsigned 15-bit integer. The macro won't behave as expected if these
+// conditions aren't met.
+//
+.macro CHECK_ALIGNMENT ba=$sp, tmp=$at, alignment=16
+#ifdef ART_MIPS32_CHECK_ALIGNMENT
+ .set push
+ .set noat
+ .set noreorder
+ andi \tmp, \ba, \alignment-1
+ beqz \tmp, .+12 # Skip break instruction if base address register (ba) is aligned
+ nop
+ break
+ .set pop
+#endif
+.endm
+
#endif // ART_RUNTIME_ARCH_MIPS_ASM_SUPPORT_MIPS_S_
diff --git a/runtime/arch/mips/asm_support_mips.h b/runtime/arch/mips/asm_support_mips.h
index 2edd63f58a..bec52384ac 100644
--- a/runtime/arch/mips/asm_support_mips.h
+++ b/runtime/arch/mips/asm_support_mips.h
@@ -19,7 +19,7 @@
#include "asm_support.h"
-#define FRAME_SIZE_SAVE_ALL_CALLEE_SAVES 96
+#define FRAME_SIZE_SAVE_ALL_CALLEE_SAVES 112
#define FRAME_SIZE_SAVE_REFS_ONLY 48
#define FRAME_SIZE_SAVE_REFS_AND_ARGS 112
#define FRAME_SIZE_SAVE_EVERYTHING 256
diff --git a/runtime/arch/mips/context_mips.cc b/runtime/arch/mips/context_mips.cc
index ca1de0ae2a..3f362de7ce 100644
--- a/runtime/arch/mips/context_mips.cc
+++ b/runtime/arch/mips/context_mips.cc
@@ -42,7 +42,16 @@ void MipsContext::FillCalleeSaves(uint8_t* frame, const QuickMethodFrameInfo& fr
// Core registers come first, from the highest down to the lowest.
for (uint32_t core_reg : HighToLowBits(frame_info.CoreSpillMask())) {
- gprs_[core_reg] = CalleeSaveAddress(frame, spill_pos, frame_info.FrameSizeInBytes());
+ // If the $ZERO register shows up in the list of registers to
+ // be saved this was only done to properly align the floating
+ // point register save locations to addresses which are
+ // multiples of 8. We only store the address of a register in
+ // gprs_ if the register is not the $ZERO register. The $ZERO
+ // register is read-only so there's never a reason to save it
+ // on the stack.
+ if (core_reg != 0u) {
+ gprs_[core_reg] = CalleeSaveAddress(frame, spill_pos, frame_info.FrameSizeInBytes());
+ }
++spill_pos;
}
DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()));
@@ -97,7 +106,9 @@ extern "C" NO_RETURN void art_quick_do_long_jump(uint32_t*, uint32_t*);
void MipsContext::DoLongJump() {
uintptr_t gprs[kNumberOfCoreRegisters];
- uint32_t fprs[kNumberOfFRegisters];
+ // Align fprs[] so that art_quick_do_long_jump() can load FPU
+ // registers from it using the ldc1 instruction.
+ uint32_t fprs[kNumberOfFRegisters] __attribute__((aligned(8)));
for (size_t i = 0; i < kNumberOfCoreRegisters; ++i) {
gprs[i] = gprs_[i] != nullptr ? *gprs_[i] : MipsContext::kBadGprBase + i;
}
diff --git a/runtime/arch/mips/jni_entrypoints_mips.S b/runtime/arch/mips/jni_entrypoints_mips.S
index 5c950717c4..2c0e75090d 100644
--- a/runtime/arch/mips/jni_entrypoints_mips.S
+++ b/runtime/arch/mips/jni_entrypoints_mips.S
@@ -28,8 +28,9 @@ ENTRY art_jni_dlsym_lookup_stub
.cfi_adjust_cfa_offset 48
sw $ra, 32($sp)
.cfi_rel_offset 31, 32
- SDu $f14, $f15, 24, $sp, $t0
- SDu $f12, $f13, 16, $sp, $t0
+ CHECK_ALIGNMENT $sp, $t0
+ sdc1 $f14, 24($sp)
+ sdc1 $f12, 16($sp)
sw $a3, 12($sp)
.cfi_rel_offset 7, 12
sw $a2, 8($sp)
@@ -45,8 +46,9 @@ ENTRY art_jni_dlsym_lookup_stub
lw $a1, 4($sp)
lw $a2, 8($sp)
lw $a3, 12($sp)
- LDu $f12, $f13, 16, $sp, $t0
- LDu $f14, $f15, 24, $sp, $t0
+ CHECK_ALIGNMENT $sp, $t0
+ ldc1 $f12, 16($sp)
+ ldc1 $f14, 24($sp)
lw $ra, 32($sp)
beq $v0, $zero, .Lno_native_code_found
addiu $sp, $sp, 48 # restore the stack
diff --git a/runtime/arch/mips/quick_entrypoints_mips.S b/runtime/arch/mips/quick_entrypoints_mips.S
index f6204bd8b6..ee3f17d06a 100644
--- a/runtime/arch/mips/quick_entrypoints_mips.S
+++ b/runtime/arch/mips/quick_entrypoints_mips.S
@@ -37,45 +37,49 @@
* Reserves FRAME_SIZE_SAVE_ALL_CALLEE_SAVES + ARG_SLOT_SIZE bytes on the stack
*/
.macro SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
- addiu $sp, $sp, -96
- .cfi_adjust_cfa_offset 96
+ addiu $sp, $sp, -112
+ .cfi_adjust_cfa_offset 112
// Ugly compile-time check, but we only have the preprocessor.
-#if (FRAME_SIZE_SAVE_ALL_CALLEE_SAVES != 96)
+#if (FRAME_SIZE_SAVE_ALL_CALLEE_SAVES != 112)
#error "FRAME_SIZE_SAVE_ALL_CALLEE_SAVES(MIPS) size not as expected."
#endif
- sw $ra, 92($sp)
- .cfi_rel_offset 31, 92
- sw $s8, 88($sp)
- .cfi_rel_offset 30, 88
- sw $gp, 84($sp)
- .cfi_rel_offset 28, 84
- sw $s7, 80($sp)
- .cfi_rel_offset 23, 80
- sw $s6, 76($sp)
- .cfi_rel_offset 22, 76
- sw $s5, 72($sp)
- .cfi_rel_offset 21, 72
- sw $s4, 68($sp)
- .cfi_rel_offset 20, 68
- sw $s3, 64($sp)
- .cfi_rel_offset 19, 64
- sw $s2, 60($sp)
- .cfi_rel_offset 18, 60
- sw $s1, 56($sp)
- .cfi_rel_offset 17, 56
- sw $s0, 52($sp)
- .cfi_rel_offset 16, 52
-
- SDu $f30, $f31, 44, $sp, $t1
- SDu $f28, $f29, 36, $sp, $t1
- SDu $f26, $f27, 28, $sp, $t1
- SDu $f24, $f25, 20, $sp, $t1
- SDu $f22, $f23, 12, $sp, $t1
- SDu $f20, $f21, 4, $sp, $t1
-
- # 1 word for holding Method*
+ sw $ra, 108($sp)
+ .cfi_rel_offset 31, 108
+ sw $s8, 104($sp)
+ .cfi_rel_offset 30, 104
+ sw $gp, 100($sp)
+ .cfi_rel_offset 28, 100
+ sw $s7, 96($sp)
+ .cfi_rel_offset 23, 96
+ sw $s6, 92($sp)
+ .cfi_rel_offset 22, 92
+ sw $s5, 88($sp)
+ .cfi_rel_offset 21, 88
+ sw $s4, 84($sp)
+ .cfi_rel_offset 20, 84
+ sw $s3, 80($sp)
+ .cfi_rel_offset 19, 80
+ sw $s2, 76($sp)
+ .cfi_rel_offset 18, 76
+ sw $s1, 72($sp)
+ .cfi_rel_offset 17, 72
+ sw $s0, 68($sp)
+ .cfi_rel_offset 16, 68
+ // 4-byte placeholder for register $zero, serving for alignment
+ // of the following double precision floating point registers.
+
+ CHECK_ALIGNMENT $sp, $t1
+ sdc1 $f30, 56($sp)
+ sdc1 $f28, 48($sp)
+ sdc1 $f26, 40($sp)
+ sdc1 $f24, 32($sp)
+ sdc1 $f22, 24($sp)
+ sdc1 $f20, 16($sp)
+
+ # 1 word for holding Method* plus 12 bytes padding to keep contents of SP
+ # a multiple of 16.
lw $t0, %got(_ZN3art7Runtime9instance_E)($gp)
lw $t0, 0($t0)
@@ -216,12 +220,13 @@
.cfi_rel_offset 6, 60
sw $a1, 56($sp)
.cfi_rel_offset 5, 56
- SDu $f18, $f19, 48, $sp, $t8
- SDu $f16, $f17, 40, $sp, $t8
- SDu $f14, $f15, 32, $sp, $t8
- SDu $f12, $f13, 24, $sp, $t8
- SDu $f10, $f11, 16, $sp, $t8
- SDu $f8, $f9, 8, $sp, $t8
+ CHECK_ALIGNMENT $sp, $t8
+ sdc1 $f18, 48($sp)
+ sdc1 $f16, 40($sp)
+ sdc1 $f14, 32($sp)
+ sdc1 $f12, 24($sp)
+ sdc1 $f10, 16($sp)
+ sdc1 $f8, 8($sp)
# bottom will hold Method*
.endm
@@ -320,12 +325,13 @@
lw $a2, 60($sp)
.cfi_restore 6
RESTORE_SAVE_REFS_AND_ARGS_FRAME_A1
- LDu $f18, $f19, 48, $sp, $t8
- LDu $f16, $f17, 40, $sp, $t8
- LDu $f14, $f15, 32, $sp, $t8
- LDu $f12, $f13, 24, $sp, $t8
- LDu $f10, $f11, 16, $sp, $t8
- LDu $f8, $f9, 8, $sp, $t8
+ CHECK_ALIGNMENT $sp, $t8
+ ldc1 $f18, 48($sp)
+ ldc1 $f16, 40($sp)
+ ldc1 $f14, 32($sp)
+ ldc1 $f12, 24($sp)
+ ldc1 $f10, 16($sp)
+ ldc1 $f8, 8($sp)
addiu $sp, $sp, 112 # Pop frame.
.cfi_adjust_cfa_offset -112
.endm
@@ -412,22 +418,23 @@
1:
.cpload $ra
- SDu $f30, $f31, 136, $sp, $t1
- SDu $f28, $f29, 128, $sp, $t1
- SDu $f26, $f27, 120, $sp, $t1
- SDu $f24, $f25, 112, $sp, $t1
- SDu $f22, $f23, 104, $sp, $t1
- SDu $f20, $f21, 96, $sp, $t1
- SDu $f18, $f19, 88, $sp, $t1
- SDu $f16, $f17, 80, $sp, $t1
- SDu $f14, $f15, 72, $sp, $t1
- SDu $f12, $f13, 64, $sp, $t1
- SDu $f10, $f11, 56, $sp, $t1
- SDu $f8, $f9, 48, $sp, $t1
- SDu $f6, $f7, 40, $sp, $t1
- SDu $f4, $f5, 32, $sp, $t1
- SDu $f2, $f3, 24, $sp, $t1
- SDu $f0, $f1, 16, $sp, $t1
+ CHECK_ALIGNMENT $sp, $t1
+ sdc1 $f30, 136($sp)
+ sdc1 $f28, 128($sp)
+ sdc1 $f26, 120($sp)
+ sdc1 $f24, 112($sp)
+ sdc1 $f22, 104($sp)
+ sdc1 $f20, 96($sp)
+ sdc1 $f18, 88($sp)
+ sdc1 $f16, 80($sp)
+ sdc1 $f14, 72($sp)
+ sdc1 $f12, 64($sp)
+ sdc1 $f10, 56($sp)
+ sdc1 $f8, 48($sp)
+ sdc1 $f6, 40($sp)
+ sdc1 $f4, 32($sp)
+ sdc1 $f2, 24($sp)
+ sdc1 $f0, 16($sp)
# 3 words padding and 1 word for holding Method*
@@ -460,22 +467,23 @@
addiu $sp, $sp, ARG_SLOT_SIZE # remove argument slots on the stack
.cfi_adjust_cfa_offset -ARG_SLOT_SIZE
- LDu $f30, $f31, 136, $sp, $t1
- LDu $f28, $f29, 128, $sp, $t1
- LDu $f26, $f27, 120, $sp, $t1
- LDu $f24, $f25, 112, $sp, $t1
- LDu $f22, $f23, 104, $sp, $t1
- LDu $f20, $f21, 96, $sp, $t1
- LDu $f18, $f19, 88, $sp, $t1
- LDu $f16, $f17, 80, $sp, $t1
- LDu $f14, $f15, 72, $sp, $t1
- LDu $f12, $f13, 64, $sp, $t1
- LDu $f10, $f11, 56, $sp, $t1
- LDu $f8, $f9, 48, $sp, $t1
- LDu $f6, $f7, 40, $sp, $t1
- LDu $f4, $f5, 32, $sp, $t1
- LDu $f2, $f3, 24, $sp, $t1
- LDu $f0, $f1, 16, $sp, $t1
+ CHECK_ALIGNMENT $sp, $t1
+ ldc1 $f30, 136($sp)
+ ldc1 $f28, 128($sp)
+ ldc1 $f26, 120($sp)
+ ldc1 $f24, 112($sp)
+ ldc1 $f22, 104($sp)
+ ldc1 $f20, 96($sp)
+ ldc1 $f18, 88($sp)
+ ldc1 $f16, 80($sp)
+ ldc1 $f14, 72($sp)
+ ldc1 $f12, 64($sp)
+ ldc1 $f10, 56($sp)
+ ldc1 $f8, 48($sp)
+ ldc1 $f6, 40($sp)
+ ldc1 $f4, 32($sp)
+ ldc1 $f2, 24($sp)
+ ldc1 $f0, 16($sp)
lw $ra, 252($sp)
.cfi_restore 31
@@ -665,7 +673,8 @@ ENTRY art_quick_osr_stub
b .Losr_exit
sw $v1, 4($a2) # store v0/v1 into result
.Losr_fp_result:
- SDu $f0, $f1, 0, $a2, $t0 # store f0/f1 into result
+ CHECK_ALIGNMENT $a2, $t0, 8
+ sdc1 $f0, 0($a2) # store f0/f1 into result
.Losr_exit:
lw $ra, 44($sp)
.cfi_restore 31
@@ -701,26 +710,28 @@ ENTRY art_quick_osr_stub
END art_quick_osr_stub
/*
- * On entry $a0 is uint32_t* gprs_ and $a1 is uint32_t* fprs_
+ * On entry $a0 is uint32_t* gprs_ and $a1 is uint32_t* fprs_.
+ * Note that fprs_ is expected to be an address that is a multiple of 8.
* FIXME: just guessing about the shape of the jmpbuf. Where will pc be?
*/
ENTRY art_quick_do_long_jump
- LDu $f0, $f1, 0*8, $a1, $t1
- LDu $f2, $f3, 1*8, $a1, $t1
- LDu $f4, $f5, 2*8, $a1, $t1
- LDu $f6, $f7, 3*8, $a1, $t1
- LDu $f8, $f9, 4*8, $a1, $t1
- LDu $f10, $f11, 5*8, $a1, $t1
- LDu $f12, $f13, 6*8, $a1, $t1
- LDu $f14, $f15, 7*8, $a1, $t1
- LDu $f16, $f17, 8*8, $a1, $t1
- LDu $f18, $f19, 9*8, $a1, $t1
- LDu $f20, $f21, 10*8, $a1, $t1
- LDu $f22, $f23, 11*8, $a1, $t1
- LDu $f24, $f25, 12*8, $a1, $t1
- LDu $f26, $f27, 13*8, $a1, $t1
- LDu $f28, $f29, 14*8, $a1, $t1
- LDu $f30, $f31, 15*8, $a1, $t1
+ CHECK_ALIGNMENT $a1, $t1, 8
+ ldc1 $f0, 0*8($a1)
+ ldc1 $f2, 1*8($a1)
+ ldc1 $f4, 2*8($a1)
+ ldc1 $f6, 3*8($a1)
+ ldc1 $f8, 4*8($a1)
+ ldc1 $f10, 5*8($a1)
+ ldc1 $f12, 6*8($a1)
+ ldc1 $f14, 7*8($a1)
+ ldc1 $f16, 8*8($a1)
+ ldc1 $f18, 9*8($a1)
+ ldc1 $f20, 10*8($a1)
+ ldc1 $f22, 11*8($a1)
+ ldc1 $f24, 12*8($a1)
+ ldc1 $f26, 13*8($a1)
+ ldc1 $f28, 14*8($a1)
+ ldc1 $f30, 15*8($a1)
.set push
.set nomacro
@@ -1067,7 +1078,8 @@ loopEnd:
jalr $zero, $ra
sw $v1, 4($t0) # store the other half of the result
5:
- SDu $f0, $f1, 0, $t0, $t1 # store floating point result
+ CHECK_ALIGNMENT $t0, $t1, 8
+ sdc1 $f0, 0($t0) # store floating point result
jalr $zero, $ra
nop
@@ -1225,7 +1237,8 @@ loopEndS:
jalr $zero, $ra
sw $v1, 4($t0) # store the other half of the result
6:
- SDu $f0, $f1, 0, $t0, $t1 # store floating point result
+ CHECK_ALIGNMENT $t0, $t1, 8
+ sdc1 $f0, 0($t0) # store floating point result
jalr $zero, $ra
nop
@@ -2252,7 +2265,7 @@ ENTRY art_quick_generic_jni_trampoline
move $a0, rSELF # pass Thread::Current
move $a2, $v0 # pass result
move $a3, $v1
- addiu $sp, $sp, -24 # reserve arg slots
+ addiu $sp, $sp, -32 # reserve arg slots
la $t9, artQuickGenericJniEndTrampoline
jalr $t9
s.d $f0, 16($sp) # pass result_f
@@ -3243,7 +3256,8 @@ ENTRY art_quick_invoke_polymorphic
lhu $v0, 16($sp) # Move char from JValue result to return value register.
.Lstore_double_result:
.Lstore_float_result:
- LDu $f0, $f1, 16, $sp, $t0 # Move double/float from JValue result to return value register.
+ CHECK_ALIGNMENT $sp, $t0
+ ldc1 $f0, 16($sp) # Move double/float from JValue result to return value register.
b .Lcleanup_and_return
nop
.Lstore_long_result:
diff --git a/runtime/arch/mips/quick_method_frame_info_mips.h b/runtime/arch/mips/quick_method_frame_info_mips.h
index 45a21ab942..8c86252152 100644
--- a/runtime/arch/mips/quick_method_frame_info_mips.h
+++ b/runtime/arch/mips/quick_method_frame_info_mips.h
@@ -35,8 +35,24 @@ static constexpr uint32_t kMipsCalleeSaveRefSpills =
static constexpr uint32_t kMipsCalleeSaveArgSpills =
(1 << art::mips::A1) | (1 << art::mips::A2) | (1 << art::mips::A3) | (1 << art::mips::T0) |
(1 << art::mips::T1);
+// We want to save all floating point register pairs at addresses
+// which are multiples of 8 so that we can eliminate use of the
+// SDu/LDu macros by using sdc1/ldc1 to store/load floating
+// register values using a single instruction. Because integer
+// registers are stored at the top of the frame, to achieve having
+// the floating point register pairs aligned on multiples of 8 the
+// number of integer registers saved must be even. Previously, the
+// only case in which we saved floating point registers beneath an
+// odd number of integer registers was when "type" is
+// CalleeSaveType::kSaveAllCalleeSaves. (There are other cases in
+// which an odd number of integer registers are saved but those
+// cases don't save any floating point registers. If no floating
+// point registers are saved we don't care if the number of integer
+// registers saved is odd or even). To save an even number of
+// integer registers in this particular case we add the ZERO
+// register to the list of registers which get saved.
static constexpr uint32_t kMipsCalleeSaveAllSpills =
- (1 << art::mips::S0) | (1 << art::mips::S1);
+ (1 << art::mips::ZERO) | (1 << art::mips::S0) | (1 << art::mips::S1);
static constexpr uint32_t kMipsCalleeSaveEverythingSpills =
(1 << art::mips::AT) | (1 << art::mips::V0) | (1 << art::mips::V1) |
(1 << art::mips::A0) | (1 << art::mips::A1) | (1 << art::mips::A2) | (1 << art::mips::A3) |
diff --git a/runtime/common_dex_operations.h b/runtime/common_dex_operations.h
index fcc5393490..6a78637ab1 100644
--- a/runtime/common_dex_operations.h
+++ b/runtime/common_dex_operations.h
@@ -17,10 +17,20 @@
#ifndef ART_RUNTIME_COMMON_DEX_OPERATIONS_H_
#define ART_RUNTIME_COMMON_DEX_OPERATIONS_H_
+#include "android-base/logging.h"
#include "art_field.h"
#include "art_method.h"
+#include "base/macros.h"
+#include "base/mutex.h"
#include "class_linker.h"
+#include "handle_scope-inl.h"
+#include "instrumentation.h"
+#include "interpreter/shadow_frame.h"
#include "interpreter/unstarted_runtime.h"
+#include "mirror/class.h"
+#include "mirror/object.h"
+#include "obj_ptr-inl.h"
+#include "primitive.h"
#include "runtime.h"
#include "stack.h"
#include "thread.h"
@@ -61,6 +71,18 @@ inline void PerformCall(Thread* self,
}
}
+template <typename T>
+inline void DCheckStaticState(Thread* self, T* entity) REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (kIsDebugBuild) {
+ ObjPtr<mirror::Class> klass = entity->GetDeclaringClass();
+ if (entity->IsStatic()) {
+ klass->AssertInitializedOrInitializingInThread(self);
+ } else {
+ CHECK(klass->IsInitializing() || klass->IsErroneousResolved());
+ }
+ }
+}
+
template<Primitive::Type field_type>
static ALWAYS_INLINE bool DoFieldGetCommon(Thread* self,
const ShadowFrame& shadow_frame,
@@ -68,7 +90,7 @@ static ALWAYS_INLINE bool DoFieldGetCommon(Thread* self,
ArtField* field,
JValue* result)
REQUIRES_SHARED(Locks::mutator_lock_) {
- field->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self);
+ DCheckStaticState(self, field);
// Report this field access to instrumentation if needed.
instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
@@ -126,7 +148,7 @@ ALWAYS_INLINE bool DoFieldPutCommon(Thread* self,
ArtField* field,
JValue& value)
REQUIRES_SHARED(Locks::mutator_lock_) {
- field->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self);
+ DCheckStaticState(self, field);
// Report this field access to instrumentation if needed. Since we only have the offset of
// the field from the base of the object, we need to look for it first.
diff --git a/runtime/dex_file_annotations.cc b/runtime/dex_file_annotations.cc
index fe33bded2b..845202ff72 100644
--- a/runtime/dex_file_annotations.cc
+++ b/runtime/dex_file_annotations.cc
@@ -134,8 +134,13 @@ const DexFile::AnnotationSetItem* FindAnnotationSetForField(ArtField* field)
REQUIRES_SHARED(Locks::mutator_lock_) {
const DexFile* dex_file = field->GetDexFile();
ObjPtr<mirror::Class> klass = field->GetDeclaringClass();
+ const DexFile::ClassDef* class_def = klass->GetClassDef();
+ if (class_def == nullptr) {
+ DCHECK(klass->IsProxyClass());
+ return nullptr;
+ }
const DexFile::AnnotationsDirectoryItem* annotations_dir =
- dex_file->GetAnnotationsDirectory(*klass->GetClassDef());
+ dex_file->GetAnnotationsDirectory(*class_def);
if (annotations_dir == nullptr) {
return nullptr;
}
@@ -258,6 +263,9 @@ const uint8_t* SearchEncodedAnnotation(const DexFile& dex_file,
const DexFile::AnnotationSetItem* FindAnnotationSetForMethod(ArtMethod* method)
REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (method->IsProxyMethod()) {
+ return nullptr;
+ }
const DexFile* dex_file = method->GetDexFile();
const DexFile::AnnotationsDirectoryItem* annotations_dir =
dex_file->GetAnnotationsDirectory(method->GetClassDef());
@@ -305,8 +313,13 @@ const DexFile::ParameterAnnotationsItem* FindAnnotationsItemForMethod(ArtMethod*
const DexFile::AnnotationSetItem* FindAnnotationSetForClass(const ClassData& klass)
REQUIRES_SHARED(Locks::mutator_lock_) {
const DexFile& dex_file = klass.GetDexFile();
+ const DexFile::ClassDef* class_def = klass.GetClassDef();
+ if (class_def == nullptr) {
+ DCHECK(klass.GetRealClass()->IsProxyClass());
+ return nullptr;
+ }
const DexFile::AnnotationsDirectoryItem* annotations_dir =
- dex_file.GetAnnotationsDirectory(*klass.GetClassDef());
+ dex_file.GetAnnotationsDirectory(*class_def);
if (annotations_dir == nullptr) {
return nullptr;
}
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index 68a75b0196..2deb3b7cf5 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -18,6 +18,7 @@
#include <limits>
+#include "common_dex_operations.h"
#include "common_throws.h"
#include "dex_file_types.h"
#include "interpreter_common.h"
@@ -287,11 +288,12 @@ static inline JValue Execute(
}
}
- shadow_frame.GetMethod()->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self);
+ ArtMethod* method = shadow_frame.GetMethod();
+
+ DCheckStaticState(self, method);
// Lock counting is a special version of accessibility checks, and for simplicity and
// reduction of template parameters, we gate it behind access-checks mode.
- ArtMethod* method = shadow_frame.GetMethod();
DCHECK(!method->SkipAccessChecks() || !method->MustCountLocks());
bool transaction_active = Runtime::Current()->IsActiveTransaction();
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index a9db48716f..ca6547897e 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -513,6 +513,10 @@ void Runtime::Abort(const char* msg) {
UNUSED(old_value);
#endif
+#ifdef ART_TARGET_ANDROID
+ android_set_abort_message(msg);
+#endif
+
// Ensure that we don't have multiple threads trying to abort at once,
// which would result in significantly worse diagnostics.
MutexLock mu(Thread::Current(), *Locks::abort_lock_);
diff --git a/test/1929-exception-catch-exception/build b/test/1929-exception-catch-exception/build
deleted file mode 100644
index 10ffcc537d..0000000000
--- a/test/1929-exception-catch-exception/build
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2017 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.
-
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
diff --git a/test/992-source-data/expected.txt b/test/992-source-data/expected.txt
index 4db8df0ada..7f59682b1d 100644
--- a/test/992-source-data/expected.txt
+++ b/test/992-source-data/expected.txt
@@ -1,10 +1,22 @@
class art.Test992 is defined in file "Test992.java"
+class art.Test992 does not have a known source file extension because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
class art.Test992$Target1 is defined in file "Test992.java"
+class art.Test992$Target1 does not have a known source file extension because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
class art.Target2 is defined in file "Target2.java"
+class art.Target2 does not have a known source file extension because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
int does not have a known source file because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
+int does not have a known source file extension because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
class java.lang.Integer is defined in file "Integer.java"
+class java.lang.Integer does not have a known source file extension because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
class java.lang.Object is defined in file "Object.java"
+class java.lang.Object does not have a known source file extension because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
interface java.lang.Runnable is defined in file "Runnable.java"
+interface java.lang.Runnable does not have a known source file extension because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
class [Ljava.lang.Object; does not have a known source file because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
+class [Ljava.lang.Object; does not have a known source file extension because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
class [I does not have a known source file because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
+class [I does not have a known source file extension because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
null does not have a known source file because java.lang.RuntimeException: JVMTI_ERROR_INVALID_CLASS
+null does not have a known source file extension because java.lang.RuntimeException: JVMTI_ERROR_INVALID_CLASS
+Proxy of [interface java.lang.Runnable] does not have a known source file because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
+Proxy of [interface java.lang.Runnable] does not have a known source file extension because java.lang.RuntimeException: JVMTI_ERROR_ABSENT_INFORMATION
diff --git a/test/992-source-data/source_file.cc b/test/992-source-data/source_file.cc
index 46d197d048..78687ff005 100644
--- a/test/992-source-data/source_file.cc
+++ b/test/992-source-data/source_file.cc
@@ -49,6 +49,19 @@ jstring JNICALL Java_art_Test992_getSourceFileName(JNIEnv* env,
return ret;
}
+extern "C" JNIEXPORT
+jstring JNICALL Java_art_Test992_getSourceDebugExtension(JNIEnv* env,
+ jclass klass ATTRIBUTE_UNUSED,
+ jclass target) {
+ char* ext = nullptr;
+ if (JvmtiErrorToException(env, jvmti_env, jvmti_env->GetSourceDebugExtension(target, &ext))) {
+ return nullptr;
+ }
+ jstring ret = env->NewStringUTF(ext);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(ext));
+ return ret;
+}
+
} // namespace Test992SourceFile
} // namespace art
diff --git a/test/992-source-data/src/art/Test992.java b/test/992-source-data/src/art/Test992.java
index d9ab112726..cc4f0c724c 100644
--- a/test/992-source-data/src/art/Test992.java
+++ b/test/992-source-data/src/art/Test992.java
@@ -16,6 +16,8 @@
package art;
+import java.lang.reflect.Proxy;
+import java.util.Arrays;
import java.util.Base64;
public class Test992 {
@@ -33,15 +35,30 @@ public class Test992 {
doTest(new Object[0].getClass());
doTest(new int[0].getClass());
doTest(null);
+ doTest(Proxy.getProxyClass(Test992.class.getClassLoader(), Runnable.class));
}
+ public static String printClass(Class<?> k) {
+ if (k != null && Proxy.class.isAssignableFrom(k)) {
+ return String.format("Proxy of %s", Arrays.toString(k.getInterfaces()));
+ } else {
+ return String.format("%s", k);
+ }
+ }
public static void doTest(Class<?> k) {
+ String pk = printClass(k);
+ try {
+ System.out.println(pk + " is defined in file \"" + getSourceFileName(k) + "\"");
+ } catch (Exception e) {
+ System.out.println(pk + " does not have a known source file because " + e);
+ }
try {
- System.out.println(k + " is defined in file \"" + getSourceFileName(k) + "\"");
+ System.out.println(pk + " has extension \"" + getSourceDebugExtension(k) + "\"");
} catch (Exception e) {
- System.out.println(k + " does not have a known source file because " + e);
+ System.out.println(pk + " does not have a known source file extension because " + e);
}
}
public static native String getSourceFileName(Class<?> k) throws Exception;
+ public static native String getSourceDebugExtension(Class<?> k) throws Exception;
}