am 2d47df9f: Merge "Add missing error message propagation to ElfFile::SetMap"
* commit '2d47df9fcf5ec53e2afda3ee21a6f7cafb2fd3fb':
Add missing error message propagation to ElfFile::SetMap
diff --git a/Android.mk b/Android.mk
index 3112ab0..8024a3d 100644
--- a/Android.mk
+++ b/Android.mk
@@ -305,6 +305,8 @@
########################################################################
# oatdump targets
+ART_DUMP_OAT_PATH ?= $(OUT_DIR)
+
.PHONY: dump-oat
dump-oat: dump-oat-core dump-oat-boot
@@ -314,29 +316,29 @@
.PHONY: dump-oat-core-host
ifeq ($(ART_BUILD_HOST),true)
dump-oat-core-host: $(HOST_CORE_IMG_OUT) $(OATDUMP)
- $(OATDUMP) --image=$(HOST_CORE_IMG_OUT) --output=/tmp/core.host.oatdump.txt --host-prefix=""
- @echo Output in /tmp/core.host.oatdump.txt
+ $(OATDUMP) --image=$(HOST_CORE_IMG_OUT) --output=$(ART_DUMP_OAT_PATH)/core.host.oatdump.txt --host-prefix=""
+ @echo Output in $(ART_DUMP_OAT_PATH)/core.host.oatdump.txt
endif
.PHONY: dump-oat-core-target
ifeq ($(ART_BUILD_TARGET),true)
dump-oat-core-target: $(TARGET_CORE_IMG_OUT) $(OATDUMP)
- $(OATDUMP) --image=$(TARGET_CORE_IMG_OUT) --output=/tmp/core.target.oatdump.txt
- @echo Output in /tmp/core.target.oatdump.txt
+ $(OATDUMP) --image=$(TARGET_CORE_IMG_OUT) --output=$(ART_DUMP_OAT_PATH)/core.target.oatdump.txt
+ @echo Output in $(ART_DUMP_OAT_PATH)/core.target.oatdump.txt
endif
.PHONY: dump-oat-boot
ifeq ($(ART_BUILD_TARGET_NDEBUG),true)
dump-oat-boot: $(TARGET_BOOT_IMG_OUT) $(OATDUMP)
- $(OATDUMP) --image=$(TARGET_BOOT_IMG_OUT) --output=/tmp/boot.oatdump.txt
- @echo Output in /tmp/boot.oatdump.txt
+ $(OATDUMP) --image=$(TARGET_BOOT_IMG_OUT) --output=$(ART_DUMP_OAT_PATH)/boot.oatdump.txt
+ @echo Output in $(ART_DUMP_OAT_PATH)/boot.oatdump.txt
endif
.PHONY: dump-oat-Calculator
ifeq ($(ART_BUILD_TARGET_NDEBUG),true)
dump-oat-Calculator: $(TARGET_OUT_APPS)/Calculator.odex $(TARGET_BOOT_IMG_OUT) $(OATDUMP)
- $(OATDUMP) --oat-file=$< --output=/tmp/Calculator.oatdump.txt
- @echo Output in /tmp/Calculator.oatdump.txt
+ $(OATDUMP) --oat-file=$< --output=$(ART_DUMP_OAT_PATH)/Calculator.oatdump.txt
+ @echo Output in $(ART_DUMP_OAT_PATH)/Calculator.oatdump.txt
endif
########################################################################
diff --git a/build/Android.oat.mk b/build/Android.oat.mk
index f964346..c04b38b 100644
--- a/build/Android.oat.mk
+++ b/build/Android.oat.mk
@@ -26,7 +26,7 @@
# By default, do not run rerun dex2oat if the tool changes.
# Comment out the | to force dex2oat to rerun on after all changes.
-DEX2OAT_DEPENDENCY := #|
+DEX2OAT_DEPENDENCY := |
DEX2OAT_DEPENDENCY += $(DEX2OAT)
DEX2OAT_DEPENDENCY += $(LIBART_COMPILER)
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index 7225262..d1a9a13 100644
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -1245,84 +1245,87 @@
const DexFile::TypeId& declaring_type = cu_->dex_file->GetTypeId(target_mid.class_idx_);
StringPiece tgt_methods_declaring_class(
cu_->dex_file->StringDataByIdx(declaring_type.descriptor_idx_));
- if (tgt_methods_declaring_class.starts_with("Ljava/lang/Double;")) {
- std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
- if (tgt_method == "long java.lang.Double.doubleToRawLongBits(double)") {
- return GenInlinedDoubleCvt(info);
- }
- if (tgt_method == "double java.lang.Double.longBitsToDouble(long)") {
- return GenInlinedDoubleCvt(info);
- }
- } else if (tgt_methods_declaring_class.starts_with("Ljava/lang/Float;")) {
- std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
- if (tgt_method == "int java.lang.Float.floatToRawIntBits(float)") {
- return GenInlinedFloatCvt(info);
- }
- if (tgt_method == "float java.lang.Float.intBitsToFloat(int)") {
- return GenInlinedFloatCvt(info);
- }
- } else if (tgt_methods_declaring_class.starts_with("Ljava/lang/Integer;")) {
- std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
- if (tgt_method == "int java.lang.Integer.reverseBytes(int)") {
- return GenInlinedReverseBytes(info, kWord);
- }
- } else if (tgt_methods_declaring_class.starts_with("Ljava/lang/Long;")) {
- std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
- if (tgt_method == "long java.lang.Long.reverseBytes(long)") {
- return GenInlinedReverseBytes(info, kLong);
- }
- } else if (tgt_methods_declaring_class.starts_with("Ljava/lang/Math;") ||
- tgt_methods_declaring_class.starts_with("Ljava/lang/StrictMath;")) {
- std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
- if (tgt_method == "int java.lang.Math.abs(int)" ||
- tgt_method == "int java.lang.StrictMath.abs(int)") {
- return GenInlinedAbsInt(info);
- }
- if (tgt_method == "long java.lang.Math.abs(long)" ||
- tgt_method == "long java.lang.StrictMath.abs(long)") {
- return GenInlinedAbsLong(info);
- }
- if (tgt_method == "int java.lang.Math.max(int, int)" ||
- tgt_method == "int java.lang.StrictMath.max(int, int)") {
- return GenInlinedMinMaxInt(info, false /* is_min */);
- }
- if (tgt_method == "int java.lang.Math.min(int, int)" ||
- tgt_method == "int java.lang.StrictMath.min(int, int)") {
- return GenInlinedMinMaxInt(info, true /* is_min */);
- }
- if (tgt_method == "double java.lang.Math.sqrt(double)" ||
- tgt_method == "double java.lang.StrictMath.sqrt(double)") {
- return GenInlinedSqrt(info);
- }
- } else if (tgt_methods_declaring_class.starts_with("Ljava/lang/Short;")) {
- std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
- if (tgt_method == "short java.lang.Short.reverseBytes(short)") {
- return GenInlinedReverseBytes(info, kSignedHalf);
- }
- } else if (tgt_methods_declaring_class.starts_with("Ljava/lang/String;")) {
- std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
- if (tgt_method == "char java.lang.String.charAt(int)") {
- return GenInlinedCharAt(info);
- }
- if (tgt_method == "int java.lang.String.compareTo(java.lang.String)") {
- return GenInlinedStringCompareTo(info);
- }
- if (tgt_method == "boolean java.lang.String.is_empty()") {
- return GenInlinedStringIsEmptyOrLength(info, true /* is_empty */);
- }
- if (tgt_method == "int java.lang.String.index_of(int, int)") {
- return GenInlinedIndexOf(info, false /* base 0 */);
- }
- if (tgt_method == "int java.lang.String.index_of(int)") {
- return GenInlinedIndexOf(info, true /* base 0 */);
- }
- if (tgt_method == "int java.lang.String.length()") {
- return GenInlinedStringIsEmptyOrLength(info, false /* is_empty */);
- }
- } else if (tgt_methods_declaring_class.starts_with("Ljava/lang/Thread;")) {
- std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
- if (tgt_method == "java.lang.Thread java.lang.Thread.currentThread()") {
- return GenInlinedCurrentThread(info);
+ if (tgt_methods_declaring_class.starts_with("Ljava/lang/")) {
+ tgt_methods_declaring_class.remove_prefix(sizeof("Ljava/lang/") - 1);
+ if (tgt_methods_declaring_class.starts_with("Double;")) {
+ std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
+ if (tgt_method == "long java.lang.Double.doubleToRawLongBits(double)") {
+ return GenInlinedDoubleCvt(info);
+ }
+ if (tgt_method == "double java.lang.Double.longBitsToDouble(long)") {
+ return GenInlinedDoubleCvt(info);
+ }
+ } else if (tgt_methods_declaring_class.starts_with("Float;")) {
+ std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
+ if (tgt_method == "int java.lang.Float.floatToRawIntBits(float)") {
+ return GenInlinedFloatCvt(info);
+ }
+ if (tgt_method == "float java.lang.Float.intBitsToFloat(int)") {
+ return GenInlinedFloatCvt(info);
+ }
+ } else if (tgt_methods_declaring_class.starts_with("Integer;")) {
+ std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
+ if (tgt_method == "int java.lang.Integer.reverseBytes(int)") {
+ return GenInlinedReverseBytes(info, kWord);
+ }
+ } else if (tgt_methods_declaring_class.starts_with("Long;")) {
+ std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
+ if (tgt_method == "long java.lang.Long.reverseBytes(long)") {
+ return GenInlinedReverseBytes(info, kLong);
+ }
+ } else if (tgt_methods_declaring_class.starts_with("Math;") ||
+ tgt_methods_declaring_class.starts_with("StrictMath;")) {
+ std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
+ if (tgt_method == "int java.lang.Math.abs(int)" ||
+ tgt_method == "int java.lang.StrictMath.abs(int)") {
+ return GenInlinedAbsInt(info);
+ }
+ if (tgt_method == "long java.lang.Math.abs(long)" ||
+ tgt_method == "long java.lang.StrictMath.abs(long)") {
+ return GenInlinedAbsLong(info);
+ }
+ if (tgt_method == "int java.lang.Math.max(int, int)" ||
+ tgt_method == "int java.lang.StrictMath.max(int, int)") {
+ return GenInlinedMinMaxInt(info, false /* is_min */);
+ }
+ if (tgt_method == "int java.lang.Math.min(int, int)" ||
+ tgt_method == "int java.lang.StrictMath.min(int, int)") {
+ return GenInlinedMinMaxInt(info, true /* is_min */);
+ }
+ if (tgt_method == "double java.lang.Math.sqrt(double)" ||
+ tgt_method == "double java.lang.StrictMath.sqrt(double)") {
+ return GenInlinedSqrt(info);
+ }
+ } else if (tgt_methods_declaring_class.starts_with("Short;")) {
+ std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
+ if (tgt_method == "short java.lang.Short.reverseBytes(short)") {
+ return GenInlinedReverseBytes(info, kSignedHalf);
+ }
+ } else if (tgt_methods_declaring_class.starts_with("String;")) {
+ std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
+ if (tgt_method == "char java.lang.String.charAt(int)") {
+ return GenInlinedCharAt(info);
+ }
+ if (tgt_method == "int java.lang.String.compareTo(java.lang.String)") {
+ return GenInlinedStringCompareTo(info);
+ }
+ if (tgt_method == "boolean java.lang.String.is_empty()") {
+ return GenInlinedStringIsEmptyOrLength(info, true /* is_empty */);
+ }
+ if (tgt_method == "int java.lang.String.index_of(int, int)") {
+ return GenInlinedIndexOf(info, false /* base 0 */);
+ }
+ if (tgt_method == "int java.lang.String.index_of(int)") {
+ return GenInlinedIndexOf(info, true /* base 0 */);
+ }
+ if (tgt_method == "int java.lang.String.length()") {
+ return GenInlinedStringIsEmptyOrLength(info, false /* is_empty */);
+ }
+ } else if (tgt_methods_declaring_class.starts_with("Thread;")) {
+ std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
+ if (tgt_method == "java.lang.Thread java.lang.Thread.currentThread()") {
+ return GenInlinedCurrentThread(info);
+ }
}
} else if (tgt_methods_declaring_class.starts_with("Llibcore/io/Memory;")) {
std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index b9716d5..90276c2 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -715,14 +715,25 @@
if (image_root_object->IsObjectArray()) {
Indenter indent2_filter(indent1_os.rdbuf(), kIndentChar, kIndentBy1Count);
std::ostream indent2_os(&indent2_filter);
- // TODO: replace down_cast with AsObjectArray (g++ currently has a problem with this)
mirror::ObjectArray<mirror::Object>* image_root_object_array
- = down_cast<mirror::ObjectArray<mirror::Object>*>(image_root_object);
- // = image_root_object->AsObjectArray<Object>();
+ = image_root_object->AsObjectArray<mirror::Object>();
for (int i = 0; i < image_root_object_array->GetLength(); i++) {
mirror::Object* value = image_root_object_array->Get(i);
+ size_t run = 0;
+ for (int32_t j = i + 1; j < image_root_object_array->GetLength(); j++) {
+ if (value == image_root_object_array->Get(j)) {
+ run++;
+ } else {
+ break;
+ }
+ }
+ if (run == 0) {
+ indent2_os << StringPrintf("%d: ", i);
+ } else {
+ indent2_os << StringPrintf("%d to %zd: ", i, i + run);
+ i = i + run;
+ }
if (value != NULL) {
- indent2_os << i << ": ";
PrettyObjectValue(indent2_os, value->GetClass(), value);
} else {
indent2_os << i << ": null\n";
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index 9a853d0..1a058ea 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -69,12 +69,24 @@
.macro RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
add sp, #4 @ bottom word holds Method*
pop {r5-r8, r10-r11, lr} @ 7 words of callee saves
+ .cfi_restore r5
+ .cfi_restore r6
+ .cfi_restore r7
+ .cfi_restore r8
+ .cfi_restore r10
+ .cfi_restore r11
.cfi_adjust_cfa_offset -32
.endm
.macro RESTORE_REF_ONLY_CALLEE_SAVE_FRAME_AND_RETURN
add sp, #4 @ bottom word holds Method*
pop {r5-r8, r10-r11, lr} @ 7 words of callee saves
+ .cfi_restore r5
+ .cfi_restore r6
+ .cfi_restore r7
+ .cfi_restore r8
+ .cfi_restore r10
+ .cfi_restore r11
.cfi_adjust_cfa_offset -32
bx lr @ return
.endm
@@ -86,7 +98,6 @@
.macro SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
push {r1-r3, r5-r8, r10-r11, lr} @ 10 words of callee saves
.save {r1-r3, r5-r8, r10-r11, lr}
- .cfi_adjust_cfa_offset 40
.cfi_rel_offset r1, 0
.cfi_rel_offset r2, 4
.cfi_rel_offset r3, 8
@@ -97,6 +108,7 @@
.cfi_rel_offset r10, 28
.cfi_rel_offset r11, 32
.cfi_rel_offset lr, 36
+ .cfi_adjust_cfa_offset 40
sub sp, #8 @ 2 words of space, bottom word will hold Method*
.pad #8
.cfi_adjust_cfa_offset 8
@@ -105,6 +117,15 @@
.macro RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
add sp, #8 @ rewind sp
pop {r1-r3, r5-r8, r10-r11, lr} @ 10 words of callee saves
+ .cfi_restore r1
+ .cfi_restore r2
+ .cfi_restore r3
+ .cfi_restore r5
+ .cfi_restore r6
+ .cfi_restore r7
+ .cfi_restore r8
+ .cfi_restore r10
+ .cfi_restore r11
.cfi_adjust_cfa_offset -48
.endm
@@ -285,6 +306,11 @@
ldr ip, [sp, #24] @ load the result pointer
strd r0, [ip] @ store r0/r1 into result pointer
pop {r0, r4, r5, r9, r11, lr} @ restore spill regs
+ .cfi_restore r0
+ .cfi_restore r4
+ .cfi_restore r5
+ .cfi_restore r9
+ .cfi_restore lr
.cfi_adjust_cfa_offset -24
bx lr
END art_quick_invoke_stub
@@ -413,6 +439,8 @@
add sp, #4
.cfi_adjust_cfa_offset -4
pop {r0-r1, lr}
+ .cfi_restore r0
+ .cfi_restore r1
SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context
mov r2, r9 @ pass Thread::Current
mov r3, sp @ pass SP
@@ -689,6 +717,7 @@
.cfi_rel_offset r9, 0
bl artSet64StaticFromCode @ (field_idx, referrer, new_val, Thread*, SP)
add sp, #16 @ release out args
+ .cfi_adjust_cfa_offset -16
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME @ TODO: we can clearly save an add here
RETURN_IF_RESULT_IS_ZERO
DELIVER_PENDING_EXCEPTION
@@ -1137,6 +1166,8 @@
mov r2, r0 @ link register saved by instrumentation
mov lr, r1 @ r1 is holding link register if we're to bounce to deoptimize
pop {r0, r1} @ restore return value
+ .cfi_restore r0
+ .cfi_restore r1
add sp, #32 @ remove callee save frame
.cfi_adjust_cfa_offset -32
bx r2 @ return
@@ -1187,6 +1218,8 @@
mov r1,r10
pop {r9 - r10}
.cfi_adjust_cfa_offset -8
+ .cfi_restore r9
+ .cfi_restore r10
bx lr
END art_quick_mul_long
diff --git a/runtime/arch/mips/quick_entrypoints_mips.S b/runtime/arch/mips/quick_entrypoints_mips.S
index 451b1bb..8862711 100644
--- a/runtime/arch/mips/quick_entrypoints_mips.S
+++ b/runtime/arch/mips/quick_entrypoints_mips.S
@@ -89,28 +89,46 @@
.macro RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
lw $ra, 60($sp)
+ .cfi_restore 31
lw $s8, 56($sp)
+ .cfi_restore 30
lw $gp, 52($sp)
+ .cfi_restore 28
lw $s7, 48($sp)
+ .cfi_restore 23
lw $s6, 44($sp)
+ .cfi_restore 22
lw $s5, 40($sp)
+ .cfi_restore 21
lw $s4, 36($sp)
+ .cfi_restore 20
lw $s3, 32($sp)
+ .cfi_restore 19
lw $s2, 28($sp)
+ .cfi_restore 18
addiu $sp, $sp, 64
.cfi_adjust_cfa_offset -64
.endm
.macro RESTORE_REF_ONLY_CALLEE_SAVE_FRAME_AND_RETURN
lw $ra, 60($sp)
+ .cfi_restore 31
lw $s8, 56($sp)
+ .cfi_restore 30
lw $gp, 52($sp)
+ .cfi_restore 28
lw $s7, 48($sp)
+ .cfi_restore 23
lw $s6, 44($sp)
+ .cfi_restore 22
lw $s5, 40($sp)
+ .cfi_restore 21
lw $s4, 36($sp)
+ .cfi_restore 20
lw $s3, 32($sp)
+ .cfi_restore 19
lw $s2, 28($sp)
+ .cfi_restore 18
jr $ra
addiu $sp, $sp, 64
.cfi_adjust_cfa_offset -64
@@ -153,17 +171,29 @@
.macro RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
lw $ra, 60($sp)
+ .cfi_restore 31
lw $s8, 56($sp)
+ .cfi_restore 30
lw $gp, 52($sp)
+ .cfi_restore 28
lw $s7, 48($sp)
+ .cfi_restore 23
lw $s6, 44($sp)
+ .cfi_restore 22
lw $s5, 40($sp)
+ .cfi_restore 21
lw $s4, 36($sp)
+ .cfi_restore 20
lw $s3, 32($sp)
+ .cfi_restore 19
lw $s2, 28($sp)
+ .cfi_restore 18
lw $a3, 12($sp)
+ .cfi_restore 7
lw $a2, 8($sp)
+ .cfi_restore 6
lw $a1, 4($sp)
+ .cfi_restore 5
addiu $sp, $sp, 64 # pop frame
.cfi_adjust_cfa_offset -64
.endm
@@ -463,9 +493,13 @@
sw $zero, 0($sp) # store NULL for method* at bottom of frame
move $sp, $fp # restore the stack
lw $s0, 0($sp)
+ .cfi_restore 16
lw $s1, 4($sp)
+ .cfi_restore 17
lw $fp, 8($sp)
+ .cfi_restore 30
lw $ra, 12($sp)
+ .cfi_restore 31
addiu $sp, $sp, 16
.cfi_adjust_cfa_offset -16
lw $t0, 16($sp) # get result pointer
diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S
index 6fe4993..ee78d45 100644
--- a/runtime/arch/x86/quick_entrypoints_x86.S
+++ b/runtime/arch/x86/quick_entrypoints_x86.S
@@ -16,14 +16,19 @@
#include "asm_support_x86.S"
+// For x86, the CFA is esp+4, the address above the pushed return address on the stack.
+
/*
* Macro that sets up the callee save frame to conform with
* Runtime::CreateCalleeSaveMethod(kSaveAll)
*/
MACRO0(SETUP_SAVE_ALL_CALLEE_SAVE_FRAME)
PUSH edi // Save callee saves (ebx is saved/restored by the upcall)
+ .cfi_rel_offset edi, -8
PUSH esi
+ .cfi_rel_offset esi, -12
PUSH ebp
+ .cfi_rel_offset ebp, -16
subl MACRO_LITERAL(16), %esp // Grow stack by 4 words, bottom word will hold Method*
.cfi_adjust_cfa_offset 16
END_MACRO
@@ -34,8 +39,11 @@
*/
MACRO0(SETUP_REF_ONLY_CALLEE_SAVE_FRAME)
PUSH edi // Save callee saves (ebx is saved/restored by the upcall)
+ .cfi_rel_offset edi, -8
PUSH esi
+ .cfi_rel_offset esi, -12
PUSH ebp
+ .cfi_rel_offset ebp, -16
subl MACRO_LITERAL(16), %esp // Grow stack by 4 words, bottom word will hold Method*
.cfi_adjust_cfa_offset 16
END_MACRO
@@ -43,8 +51,11 @@
MACRO0(RESTORE_REF_ONLY_CALLEE_SAVE_FRAME)
addl MACRO_LITERAL(16), %esp // Unwind stack up to return address
POP ebp // Restore callee saves (ebx is saved/restored by the upcall)
+ .cfi_restore ebp
POP esi
+ .cfi_restore esi
POP edi
+ .cfi_restore edi
.cfi_adjust_cfa_offset -28
END_MACRO
@@ -54,23 +65,36 @@
*/
MACRO0(SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME)
PUSH edi // Save callee saves
+ .cfi_rel_offset edi, -8
PUSH esi
+ .cfi_rel_offset esi, -12
PUSH ebp
+ .cfi_rel_offset ebp, -16
PUSH ebx // Save args
+ .cfi_rel_offset ebx, -20
PUSH edx
+ .cfi_rel_offset edx, -24
PUSH ecx
+ .cfi_rel_offset ecx, -28
PUSH eax // Align stack, eax will be clobbered by Method*
+ .cfi_rel_offset eax, -28
END_MACRO
MACRO0(RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME)
addl MACRO_LITERAL(4), %esp // Remove padding
.cfi_adjust_cfa_offset -4
POP ecx // Restore args except eax
+ .cfi_restore ecx
POP edx
+ .cfi_restore edx
POP ebx
+ .cfi_restore ebx
POP ebp // Restore callee saves
+ .cfi_restore ebp
POP esi
+ .cfi_restore esi
POP edi
+ .cfi_restore edi
END_MACRO
/*
@@ -188,12 +212,19 @@
// Set up the callee save frame to conform with Runtime::CreateCalleeSaveMethod(kRefsAndArgs)
// return address
PUSH edi
+ .cfi_rel_offset edi, -8
PUSH esi
+ .cfi_rel_offset esi, -12
PUSH ebp
- PUSH ebx
+ .cfi_rel_offset ebp, -16
+ PUSH ebx // Save args
+ .cfi_rel_offset ebx, -20
PUSH edx
+ .cfi_rel_offset edx, -24
PUSH ecx
- PUSH eax // <-- callee save Method* to go here
+ .cfi_rel_offset ecx, -28
+ PUSH eax // <-- callee save Method* to go here
+ .cfi_rel_offset eax, -32
movl %esp, %edx // remember SP
// Outgoing argument set up
subl MACRO_LITERAL(12), %esp // alignment padding
@@ -209,11 +240,16 @@
movl %edx, %edi // save code pointer in EDI
addl MACRO_LITERAL(36), %esp // Pop arguments skip eax
.cfi_adjust_cfa_offset -36
- POP ecx // Restore args
+ POP ecx // Restore args except eax
+ .cfi_restore ecx
POP edx
+ .cfi_restore edx
POP ebx
- POP ebp // Restore callee saves.
+ .cfi_restore ebx
+ POP ebp // Restore callee saves
+ .cfi_restore ebp
POP esi
+ .cfi_restore esi
// Swap EDI callee save with code pointer.
xchgl %edi, (%esp)
testl %eax, %eax // Branch forward if exception pending.
@@ -248,7 +284,9 @@
*/
DEFINE_FUNCTION art_quick_invoke_stub
PUSH ebp // save ebp
+ .cfi_rel_offset ebp, -8
PUSH ebx // save ebx
+ .cfi_rel_offset ebx, -12
mov %esp, %ebp // copy value of stack pointer into base pointer
.cfi_def_cfa_register ebp
mov 20(%ebp), %ebx // get arg array size
@@ -269,8 +307,11 @@
mov 12(%esp), %ebx // copy arg3 into ebx
call *METHOD_CODE_OFFSET(%eax) // call the method
mov %ebp, %esp // restore stack pointer
+ .cfi_def_cfa_register esp
POP ebx // pop ebx
+ .cfi_restore ebx
POP ebp // pop ebp
+ .cfi_restore ebp
mov 20(%esp), %ecx // get result pointer
cmpl LITERAL(68), 24(%esp) // test if result type char == 'D'
je return_double_quick
@@ -495,7 +536,9 @@
DEFINE_FUNCTION art_quick_check_cast
PUSH eax // alignment padding
PUSH ecx // pass arg2 - obj->klass
+ .cfi_rel_offset ecx, -12
PUSH eax // pass arg1 - checked class
+ .cfi_rel_offset eax, -16
call SYMBOL(artIsAssignableFromCode) // (Class* klass, Class* ref_klass)
testl %eax, %eax
jz 1f // jump forward if not assignable
@@ -504,7 +547,9 @@
ret
1:
POP eax // pop arguments
+ .cfi_restore eax
POP ecx
+ .cfi_restore ecx
addl LITERAL(4), %esp
.cfi_adjust_cfa_offset -12
SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index bdcf6ac..0eecd28 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -3489,9 +3489,9 @@
recent_allocation_records_ = new AllocRecord[gAllocRecordMax];
CHECK(recent_allocation_records_ != NULL);
}
- Runtime::Current()->InstrumentQuickAllocEntryPoints();
+ Runtime::Current()->GetInstrumentation()->InstrumentQuickAllocEntryPoints();
} else {
- Runtime::Current()->UninstrumentQuickAllocEntryPoints();
+ Runtime::Current()->GetInstrumentation()->UninstrumentQuickAllocEntryPoints();
delete[] recent_allocation_records_;
recent_allocation_records_ = NULL;
}
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 804c669..de3ab0e 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -237,7 +237,7 @@
CHECK_NE(max_allowed_footprint_, 0U);
if (running_on_valgrind_) {
- Runtime::Current()->InstrumentQuickAllocEntryPoints();
+ Runtime::Current()->GetInstrumentation()->InstrumentQuickAllocEntryPoints();
}
if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 7d2441b..91909e4 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -300,6 +300,10 @@
card_table_->MarkCard(dst);
}
+ void WriteBarrierEveryFieldOf(const mirror::Object* obj) {
+ card_table_->MarkCard(obj);
+ }
+
accounting::CardTable* GetCardTable() const {
return card_table_.get();
}
diff --git a/runtime/indenter.h b/runtime/indenter.h
index c432e1b..d055d4e 100644
--- a/runtime/indenter.h
+++ b/runtime/indenter.h
@@ -17,6 +17,7 @@
#ifndef ART_RUNTIME_INDENTER_H_
#define ART_RUNTIME_INDENTER_H_
+#include "base/logging.h"
#include "base/macros.h"
#include <streambuf>
@@ -30,16 +31,28 @@
private:
int_type overflow(int_type c) {
- if (c != std::char_traits<char>::eof()) {
- if (indent_next_) {
- for (size_t i = 0; i < count_; ++i) {
- out_sbuf_->sputc(text_);
+ if (UNLIKELY(c == std::char_traits<char>::eof())) {
+ out_sbuf_->pubsync();
+ return c;
+ }
+ if (indent_next_) {
+ for (size_t i = 0; i < count_; ++i) {
+ int_type r = out_sbuf_->sputc(text_);
+ if (UNLIKELY(r != text_)) {
+ out_sbuf_->pubsync();
+ r = out_sbuf_->sputc(text_);
+ CHECK_EQ(r, text_) << "Error writing to buffer. Disk full?";
}
}
- out_sbuf_->sputc(c);
- indent_next_ = (c == '\n');
}
- return std::char_traits<char>::not_eof(c);
+ indent_next_ = (c == '\n');
+ int_type r = out_sbuf_->sputc(c);
+ if (UNLIKELY(r != c)) {
+ out_sbuf_->pubsync();
+ r = out_sbuf_->sputc(c);
+ CHECK_EQ(r, c) << "Error writing to buffer. Disk full?";
+ }
+ return r;
}
int sync() {
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 8cf486f..0f4fa4e 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -39,6 +39,9 @@
#include "thread_list.h"
namespace art {
+
+extern void SetQuickAllocEntryPointsInstrumented(bool instrumented);
+
namespace instrumentation {
// Do we want to deoptimize for method entry and exit listeners or just try to intercept
@@ -391,6 +394,55 @@
}
}
+static void ResetQuickAllocEntryPointsForThread(Thread* thread, void* arg) {
+ thread->ResetQuickAllocEntryPointsForThread();
+}
+
+void Instrumentation::InstrumentQuickAllocEntryPoints() {
+ // TODO: the read of quick_alloc_entry_points_instrumentation_counter_ is racey and this code
+ // should be guarded by a lock.
+ DCHECK_GE(quick_alloc_entry_points_instrumentation_counter_, 0U);
+ bool enable_instrumentation = (quick_alloc_entry_points_instrumentation_counter_ == 0);
+ quick_alloc_entry_points_instrumentation_counter_++;
+ if (enable_instrumentation) {
+ // Instrumentation wasn't enabled so enable it.
+ SetQuickAllocEntryPointsInstrumented(true);
+ Runtime* runtime = Runtime::Current();
+ if (runtime->IsStarted()) {
+ ThreadList* tl = runtime->GetThreadList();
+ Thread* self = Thread::Current();
+ tl->SuspendAll();
+ {
+ MutexLock mu(self, *Locks::thread_list_lock_);
+ tl->ForEach(ResetQuickAllocEntryPointsForThread, NULL);
+ }
+ tl->ResumeAll();
+ }
+ }
+}
+
+void Instrumentation::UninstrumentQuickAllocEntryPoints() {
+ // TODO: the read of quick_alloc_entry_points_instrumentation_counter_ is racey and this code
+ // should be guarded by a lock.
+ DCHECK_GT(quick_alloc_entry_points_instrumentation_counter_, 0U);
+ quick_alloc_entry_points_instrumentation_counter_--;
+ bool disable_instrumentation = (quick_alloc_entry_points_instrumentation_counter_ == 0);
+ if (disable_instrumentation) {
+ SetQuickAllocEntryPointsInstrumented(false);
+ Runtime* runtime = Runtime::Current();
+ if (runtime->IsStarted()) {
+ ThreadList* tl = Runtime::Current()->GetThreadList();
+ Thread* self = Thread::Current();
+ tl->SuspendAll();
+ {
+ MutexLock mu(self, *Locks::thread_list_lock_);
+ tl->ForEach(ResetQuickAllocEntryPointsForThread, NULL);
+ }
+ tl->ResumeAll();
+ }
+ }
+}
+
void Instrumentation::UpdateMethodsCode(mirror::ArtMethod* method, const void* code) const {
if (LIKELY(!instrumentation_stubs_installed_)) {
method->SetEntryPointFromCompiledCode(code);
diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h
index 7a0aaf7..25a4eec 100644
--- a/runtime/instrumentation.h
+++ b/runtime/instrumentation.h
@@ -104,7 +104,8 @@
have_method_entry_listeners_(false), have_method_exit_listeners_(false),
have_method_unwind_listeners_(false), have_dex_pc_listeners_(false),
have_exception_caught_listeners_(false),
- interpreter_handler_table_(kMainHandlerTable) {}
+ interpreter_handler_table_(kMainHandlerTable),
+ quick_alloc_entry_points_instrumentation_counter_(0) {}
// Add a listener to be notified of the masked together sent of instrumentation events. This
// suspend the runtime to install stubs. You are expected to hold the mutator lock as a proxy
@@ -123,6 +124,9 @@
return interpreter_handler_table_;
}
+ void InstrumentQuickAllocEntryPoints() LOCKS_EXCLUDED(Locks::thread_list_lock_);
+ void UninstrumentQuickAllocEntryPoints() LOCKS_EXCLUDED(Locks::thread_list_lock_);
+
// Update the code of a method respecting any installed stubs.
void UpdateMethodsCode(mirror::ArtMethod* method, const void* code) const;
@@ -289,9 +293,14 @@
std::list<InstrumentationListener*> dex_pc_listeners_ GUARDED_BY(Locks::mutator_lock_);
std::list<InstrumentationListener*> exception_caught_listeners_ GUARDED_BY(Locks::mutator_lock_);
- // Current interpreter handler table. This is updated each time the thread state flags are modified.
+ // Current interpreter handler table. This is updated each time the thread state flags are
+ // modified.
InterpreterHandlerTable interpreter_handler_table_;
+ // Greater than 0 if quick alloc entry points instrumented.
+ // TODO: The access and changes to this is racy and should be guarded by a lock.
+ size_t quick_alloc_entry_points_instrumentation_counter_;
+
DISALLOW_COPY_AND_ASSIGN(Instrumentation);
};
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index bd187c1..87d02c9 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -40,48 +40,39 @@
namespace mirror {
Object* Object::Clone(Thread* self) {
- Class* c = GetClass();
+ mirror::Class* c = GetClass();
DCHECK(!c->IsClassClass());
-
// Object::SizeOf gets the right size even if we're an array.
// Using c->AllocObject() here would be wrong.
size_t num_bytes = SizeOf();
gc::Heap* heap = Runtime::Current()->GetHeap();
- SirtRef<Object> copy(self, heap->AllocObject(self, c, num_bytes));
- if (copy.get() == NULL) {
- return NULL;
+ SirtRef<mirror::Object> sirt_this(self, this);
+ Object* copy = heap->AllocObject(self, c, num_bytes);
+ if (UNLIKELY(copy == nullptr)) {
+ return nullptr;
}
-
// Copy instance data. We assume memcpy copies by words.
// TODO: expose and use move32.
- byte* src_bytes = reinterpret_cast<byte*>(this);
- byte* dst_bytes = reinterpret_cast<byte*>(copy.get());
+ byte* src_bytes = reinterpret_cast<byte*>(sirt_this.get());
+ byte* dst_bytes = reinterpret_cast<byte*>(copy);
size_t offset = sizeof(Object);
memcpy(dst_bytes + offset, src_bytes + offset, num_bytes - offset);
-
// Perform write barriers on copied object references.
+ c = copy->GetClass(); // Re-read Class in case it moved.
if (c->IsArrayClass()) {
if (!c->GetComponentType()->IsPrimitive()) {
const ObjectArray<Object>* array = copy->AsObjectArray<Object>();
- heap->WriteBarrierArray(copy.get(), 0, array->GetLength());
+ heap->WriteBarrierArray(copy, 0, array->GetLength());
}
} else {
- for (const Class* klass = c; klass != NULL; klass = klass->GetSuperClass()) {
- size_t num_reference_fields = klass->NumReferenceInstanceFields();
- for (size_t i = 0; i < num_reference_fields; ++i) {
- ArtField* field = klass->GetInstanceField(i);
- MemberOffset field_offset = field->GetOffset();
- const Object* ref = copy->GetFieldObject<const Object*>(field_offset, false);
- heap->WriteBarrierField(copy.get(), field_offset, ref);
- }
- }
+ heap->WriteBarrierEveryFieldOf(copy);
}
-
if (c->IsFinalizable()) {
- heap->AddFinalizerReference(Thread::Current(), copy.get());
+ SirtRef<mirror::Object> sirt_copy(self, copy);
+ heap->AddFinalizerReference(self, copy);
+ return sirt_copy.get();
}
-
- return copy.get();
+ return copy;
}
int32_t Object::GenerateIdentityHashCode() {
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 34cf45b..53c9b2e 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -102,8 +102,7 @@
use_compile_time_class_path_(false),
main_thread_group_(NULL),
system_thread_group_(NULL),
- system_class_loader_(NULL),
- quick_alloc_entry_points_instrumentation_counter_(0) {
+ system_class_loader_(NULL) {
for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
callee_save_methods_[i] = NULL;
}
@@ -1077,9 +1076,9 @@
GetStats()->Clear(~0);
// TODO: wouldn't it make more sense to clear _all_ threads' stats?
Thread::Current()->GetStats()->Clear(~0);
- InstrumentQuickAllocEntryPoints();
+ GetInstrumentation()->InstrumentQuickAllocEntryPoints();
} else {
- UninstrumentQuickAllocEntryPoints();
+ GetInstrumentation()->UninstrumentQuickAllocEntryPoints();
}
stats_enabled_ = new_state;
}
@@ -1336,46 +1335,4 @@
compile_time_class_paths_.Put(class_loader, class_path);
}
-static void ResetQuickAllocEntryPointsForThread(Thread* thread, void* arg) {
- thread->ResetQuickAllocEntryPointsForThread();
-}
-
-void SetQuickAllocEntryPointsInstrumented(bool instrumented);
-
-void Runtime::InstrumentQuickAllocEntryPoints() {
- ThreadList* tl = thread_list_;
- Thread* self = Thread::Current();
- tl->SuspendAll();
- {
- MutexLock mu(self, *Locks::runtime_shutdown_lock_);
- MutexLock mu2(self, *Locks::thread_list_lock_);
- DCHECK_GE(quick_alloc_entry_points_instrumentation_counter_, 0);
- int old_counter = quick_alloc_entry_points_instrumentation_counter_++;
- if (old_counter == 0) {
- // If it was disabled, enable it.
- SetQuickAllocEntryPointsInstrumented(true);
- tl->ForEach(ResetQuickAllocEntryPointsForThread, NULL);
- }
- }
- tl->ResumeAll();
-}
-
-void Runtime::UninstrumentQuickAllocEntryPoints() {
- ThreadList* tl = thread_list_;
- Thread* self = Thread::Current();
- tl->SuspendAll();
- {
- MutexLock mu(self, *Locks::runtime_shutdown_lock_);
- MutexLock mu2(self, *Locks::thread_list_lock_);
- DCHECK_GT(quick_alloc_entry_points_instrumentation_counter_, 0);
- int new_counter = --quick_alloc_entry_points_instrumentation_counter_;
- if (new_counter == 0) {
- // Disable it if the counter becomes zero.
- SetQuickAllocEntryPointsInstrumented(false);
- tl->ForEach(ResetQuickAllocEntryPointsForThread, NULL);
- }
- }
- tl->ResumeAll();
-}
-
} // namespace art
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 0ce2642..24b4c87 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -442,9 +442,6 @@
const std::vector<const DexFile*>& GetCompileTimeClassPath(jobject class_loader);
void SetCompileTimeClassPath(jobject class_loader, std::vector<const DexFile*>& class_path);
- void InstrumentQuickAllocEntryPoints();
- void UninstrumentQuickAllocEntryPoints();
-
private:
static void InitPlatformSignalHandlers();
@@ -567,8 +564,6 @@
// As returned by ClassLoader.getSystemClassLoader().
jobject system_class_loader_;
- int quick_alloc_entry_points_instrumentation_counter_;
-
DISALLOW_COPY_AND_ASSIGN(Runtime);
};