summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2014-01-06 12:55:46 -0800
committerIan Rogers <irogers@google.com>2014-02-06 23:20:27 -0800
commitef7d42fca18c16fbaf103822ad16f23246e2905d (patch)
treec67eea52a349c2ea7f2c3bdda8e73933c05531a8 /runtime
parent822115a225185d2896607eb08d70ce5c7099adef (diff)
downloadart-ef7d42fca18c16fbaf103822ad16f23246e2905d.zip
art-ef7d42fca18c16fbaf103822ad16f23246e2905d.tar.gz
art-ef7d42fca18c16fbaf103822ad16f23246e2905d.tar.bz2
Object model changes to support 64bit.
Modify mirror objects so that references between them use an ObjectReference value type rather than an Object* so that functionality to compress larger references can be captured in the ObjectRefererence implementation. ObjectReferences are 32bit and all other aspects of object layout remain as they are currently. Expand fields in objects holding pointers so they can hold 64bit pointers. Its expected the size of these will come down by improving where we hold compiler meta-data. Stub out x86_64 architecture specific runtime implementation. Modify OutputStream so that reads and writes are of unsigned quantities. Make the use of portable or quick code more explicit. Templatize AtomicInteger to support more than just int32_t as a type. Add missing, and fix issues relating to, missing annotalysis information on the mutator lock. Refactor and share implementations for array copy between System and uses elsewhere in the runtime. Fix numerous 64bit build issues. Change-Id: I1a5694c251a42c9eff71084dfdd4b51fff716822
Diffstat (limited to 'runtime')
-rw-r--r--runtime/Android.mk24
-rw-r--r--runtime/arch/arm/context_arm.h2
-rw-r--r--runtime/arch/arm/portable_entrypoints_arm.S2
-rw-r--r--runtime/arch/arm/quick_entrypoints_arm.S2
-rw-r--r--runtime/arch/context.cc7
-rw-r--r--runtime/arch/context.h5
-rw-r--r--runtime/arch/mips/context_mips.h2
-rw-r--r--runtime/arch/mips/portable_entrypoints_mips.S68
-rw-r--r--runtime/arch/mips/quick_entrypoints_mips.S8
-rw-r--r--runtime/arch/x86/context_x86.cc8
-rw-r--r--runtime/arch/x86/context_x86.h2
-rw-r--r--runtime/arch/x86/jni_entrypoints_x86.S2
-rw-r--r--runtime/arch/x86/portable_entrypoints_x86.S2
-rw-r--r--runtime/arch/x86/quick_entrypoints_x86.S2
-rw-r--r--runtime/arch/x86_64/asm_support_x86_64.S146
-rw-r--r--runtime/arch/x86_64/asm_support_x86_64.h31
-rw-r--r--runtime/arch/x86_64/context_x86_64.cc76
-rw-r--r--runtime/arch/x86_64/context_x86_64.h69
-rw-r--r--runtime/arch/x86_64/entrypoints_init_x86_64.cc224
-rw-r--r--runtime/arch/x86_64/jni_entrypoints_x86_64.S22
-rw-r--r--runtime/arch/x86_64/portable_entrypoints_x86_64.S28
-rw-r--r--runtime/arch/x86_64/quick_entrypoints_x86_64.S401
-rw-r--r--runtime/arch/x86_64/registers_x86_64.cc38
-rw-r--r--runtime/arch/x86_64/registers_x86_64.h54
-rw-r--r--runtime/arch/x86_64/thread_x86_64.cc69
-rw-r--r--runtime/asm_support.h3
-rw-r--r--runtime/atomic.cc2
-rw-r--r--runtime/atomic.h71
-rw-r--r--runtime/atomic_integer.h86
-rw-r--r--runtime/barrier_test.cc2
-rw-r--r--runtime/base/bit_vector_test.cc4
-rw-r--r--runtime/base/mutex.cc6
-rw-r--r--runtime/base/mutex.h2
-rw-r--r--runtime/base/unix_file/fd_file.cc16
-rw-r--r--runtime/base/unix_file/fd_file.h4
-rw-r--r--runtime/base/unix_file/mapped_file.cc6
-rw-r--r--runtime/base/unix_file/mapped_file_test.cc13
-rw-r--r--runtime/base/unix_file/null_file_test.cc6
-rw-r--r--runtime/base/unix_file/random_access_file_test.h24
-rw-r--r--runtime/check_jni.cc174
-rw-r--r--runtime/class_linker-inl.h10
-rw-r--r--runtime/class_linker.cc175
-rw-r--r--runtime/class_linker.h37
-rw-r--r--runtime/class_linker_test.cc37
-rw-r--r--runtime/common_test.h79
-rw-r--r--runtime/common_throws.cc33
-rw-r--r--runtime/common_throws.h31
-rw-r--r--runtime/debugger.cc45
-rw-r--r--runtime/debugger.h4
-rw-r--r--runtime/dex_file-inl.h2
-rw-r--r--runtime/dex_file.cc2
-rw-r--r--runtime/dex_file.h2
-rw-r--r--runtime/elf_file.cc3
-rw-r--r--runtime/entrypoints/entrypoint_utils.h55
-rw-r--r--runtime/entrypoints/interpreter/interpreter_entrypoints.cc18
-rw-r--r--runtime/entrypoints/portable/portable_cast_entrypoints.cc12
-rw-r--r--runtime/entrypoints/portable/portable_field_entrypoints.cc16
-rw-r--r--runtime/entrypoints/portable/portable_fillarray_entrypoints.cc2
-rw-r--r--runtime/entrypoints/portable/portable_invoke_entrypoints.cc2
-rw-r--r--runtime/entrypoints/portable/portable_throw_entrypoints.cc2
-rw-r--r--runtime/entrypoints/portable/portable_trampoline_entrypoints.cc32
-rw-r--r--runtime/entrypoints/quick/quick_cast_entrypoints.cc3
-rw-r--r--runtime/entrypoints/quick/quick_dexcache_entrypoints.cc6
-rw-r--r--runtime/entrypoints/quick/quick_field_entrypoints.cc38
-rw-r--r--runtime/entrypoints/quick/quick_fillarray_entrypoints.cc2
-rw-r--r--runtime/entrypoints/quick/quick_invoke_entrypoints.cc24
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc12
-rw-r--r--runtime/exception_test.cc95
-rw-r--r--runtime/gc/accounting/atomic_stack.h4
-rw-r--r--runtime/gc/accounting/card_table.cc6
-rw-r--r--runtime/gc/accounting/mod_union_table.cc41
-rw-r--r--runtime/gc/accounting/mod_union_table.h11
-rw-r--r--runtime/gc/accounting/space_bitmap-inl.h13
-rw-r--r--runtime/gc/accounting/space_bitmap.cc2
-rw-r--r--runtime/gc/accounting/space_bitmap.h4
-rw-r--r--runtime/gc/collector/mark_sweep-inl.h14
-rw-r--r--runtime/gc/collector/mark_sweep.h2
-rw-r--r--runtime/gc/collector/semi_space.cc6
-rw-r--r--runtime/gc/collector/semi_space.h2
-rw-r--r--runtime/gc/heap.cc66
-rw-r--r--runtime/gc/heap.h35
-rw-r--r--runtime/gc/reference_queue.cc11
-rw-r--r--runtime/gc/reference_queue.h4
-rw-r--r--runtime/gc/space/bump_pointer_space.cc4
-rw-r--r--runtime/gc/space/bump_pointer_space.h6
-rw-r--r--runtime/gc/space/dlmalloc_space.cc2
-rw-r--r--runtime/gc/space/dlmalloc_space.h10
-rw-r--r--runtime/gc/space/image_space.cc6
-rw-r--r--runtime/gc/space/image_space.h2
-rw-r--r--runtime/gc/space/large_object_space.cc10
-rw-r--r--runtime/gc/space/large_object_space.h5
-rw-r--r--runtime/gc/space/malloc_space.cc2
-rw-r--r--runtime/gc/space/malloc_space.h27
-rw-r--r--runtime/gc/space/rosalloc_space.cc2
-rw-r--r--runtime/gc/space/rosalloc_space.h10
-rw-r--r--runtime/gc/space/space.h2
-rw-r--r--runtime/gc/space/space_test.cc72
-rw-r--r--runtime/gc/space/zygote_space.h2
-rw-r--r--runtime/globals.h2
-rw-r--r--runtime/hprof/hprof.cc180
-rw-r--r--runtime/instruction_set.h1
-rw-r--r--runtime/instrumentation.cc112
-rw-r--r--runtime/instrumentation.h29
-rw-r--r--runtime/interpreter/interpreter.cc2
-rw-r--r--runtime/interpreter/interpreter_common.cc21
-rw-r--r--runtime/interpreter/interpreter_common.h6
-rw-r--r--runtime/interpreter/interpreter_goto_table_impl.cc2
-rw-r--r--runtime/interpreter/interpreter_switch_impl.cc2
-rw-r--r--runtime/invoke_arg_array_builder.h16
-rw-r--r--runtime/jdwp/jdwp.h2
-rw-r--r--runtime/jni_internal.cc16
-rw-r--r--runtime/jni_internal_test.cc62
-rw-r--r--runtime/lock_word-inl.h7
-rw-r--r--runtime/lock_word.h2
-rw-r--r--runtime/mem_map.cc8
-rw-r--r--runtime/mem_map.h2
-rw-r--r--runtime/mem_map_test.cc143
-rw-r--r--runtime/mirror/array-inl.h117
-rw-r--r--runtime/mirror/array.cc4
-rw-r--r--runtime/mirror/array.h59
-rw-r--r--runtime/mirror/art_field-inl.h60
-rw-r--r--runtime/mirror/art_field.h104
-rw-r--r--runtime/mirror/art_method-inl.h77
-rw-r--r--runtime/mirror/art_method.cc67
-rw-r--r--runtime/mirror/art_method.h310
-rw-r--r--runtime/mirror/class-inl.h130
-rw-r--r--runtime/mirror/class.cc60
-rw-r--r--runtime/mirror/class.h328
-rw-r--r--runtime/mirror/class_loader.h6
-rw-r--r--runtime/mirror/dex_cache-inl.h2
-rw-r--r--runtime/mirror/dex_cache.h60
-rw-r--r--runtime/mirror/iftable.h9
-rw-r--r--runtime/mirror/object-inl.h165
-rw-r--r--runtime/mirror/object.cc9
-rw-r--r--runtime/mirror/object.h149
-rw-r--r--runtime/mirror/object_array-inl.h162
-rw-r--r--runtime/mirror/object_array.h24
-rw-r--r--runtime/mirror/object_reference.h91
-rw-r--r--runtime/mirror/object_test.cc7
-rw-r--r--runtime/mirror/proxy.h18
-rw-r--r--runtime/mirror/stack_trace_element.h29
-rw-r--r--runtime/mirror/string.cc28
-rw-r--r--runtime/mirror/string.h34
-rw-r--r--runtime/mirror/throwable.cc12
-rw-r--r--runtime/mirror/throwable.h22
-rw-r--r--runtime/modifiers.h1
-rw-r--r--runtime/monitor.cc18
-rw-r--r--runtime/monitor.h17
-rw-r--r--runtime/monitor_pool.cc56
-rw-r--r--runtime/monitor_pool.h94
-rw-r--r--runtime/native/dalvik_system_DexFile.cc2
-rw-r--r--runtime/native/dalvik_system_VMRuntime.cc5
-rw-r--r--runtime/native/dalvik_system_VMStack.cc2
-rw-r--r--runtime/native/dalvik_system_Zygote.cc2
-rw-r--r--runtime/native/java_lang_System.cc342
-rw-r--r--runtime/native/sun_misc_Unsafe.cc58
-rw-r--r--runtime/oat_file.cc61
-rw-r--r--runtime/oat_file.h26
-rw-r--r--runtime/object_utils.h89
-rw-r--r--runtime/offsets.h8
-rw-r--r--runtime/primitive.h3
-rw-r--r--runtime/profiler.cc4
-rw-r--r--runtime/reference_table.cc12
-rw-r--r--runtime/runtime.cc115
-rw-r--r--runtime/runtime.h6
-rw-r--r--runtime/runtime_linux.cc6
-rw-r--r--runtime/sirt_ref.h12
-rw-r--r--runtime/stack.cc36
-rw-r--r--runtime/stack.h99
-rw-r--r--runtime/stack_indirect_reference_table.h15
-rw-r--r--runtime/thread.cc40
-rw-r--r--runtime/thread.h14
-rw-r--r--runtime/thread_pool.cc2
-rw-r--r--runtime/thread_pool_test.cc2
-rw-r--r--runtime/trace.cc20
-rw-r--r--runtime/trace.h10
-rw-r--r--runtime/utf.cc2
-rw-r--r--runtime/utf.h2
-rw-r--r--runtime/utils.cc30
-rw-r--r--runtime/utils.h44
-rw-r--r--runtime/verifier/method_verifier.cc11
-rw-r--r--runtime/verifier/method_verifier.h3
-rw-r--r--runtime/verifier/reg_type.h2
-rw-r--r--runtime/well_known_classes.cc2
-rw-r--r--runtime/zip_archive.cc2
185 files changed, 4384 insertions, 2524 deletions
diff --git a/runtime/Android.mk b/runtime/Android.mk
index d735051..223ae7c 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -215,12 +215,13 @@ LIBART_LDFLAGS += -Wl,--no-fatal-warnings
else # TARGET_ARCH != x86
ifeq ($(TARGET_ARCH),x86_64)
LIBART_TARGET_SRC_FILES += \
- arch/x86/context_x86.cc \
- arch/x86/entrypoints_init_x86.cc \
- arch/x86/jni_entrypoints_x86.S \
- arch/x86/portable_entrypoints_x86.S \
- arch/x86/quick_entrypoints_x86.S \
- arch/x86/thread_x86.cc
+ arch/x86_64/context_x86_64.cc \
+ arch/x86_64/entrypoints_init_x86_64.cc \
+ arch/x86_64/jni_entrypoints_x86_64.S \
+ arch/x86_64/portable_entrypoints_x86_64.S \
+ arch/x86_64/quick_entrypoints_x86_64.S \
+ arch/x86_64/thread_x86_64.cc \
+ monitor_pool.cc
LIBART_LDFLAGS += -Wl,--no-fatal-warnings
else # TARGET_ARCH != x86_64
ifeq ($(TARGET_ARCH),mips)
@@ -255,6 +256,16 @@ LIBART_HOST_SRC_FILES := \
thread_linux.cc
ifeq ($(HOST_ARCH),x86)
+ifneq ($(BUILD_HOST_64bit),)
+LIBART_HOST_SRC_FILES += \
+ arch/x86_64/context_x86_64.cc \
+ arch/x86_64/entrypoints_init_x86_64.cc \
+ arch/x86_64/jni_entrypoints_x86_64.S \
+ arch/x86_64/portable_entrypoints_x86_64.S \
+ arch/x86_64/quick_entrypoints_x86_64.S \
+ arch/x86_64/thread_x86_64.cc \
+ monitor_pool.cc
+else
LIBART_HOST_SRC_FILES += \
arch/x86/context_x86.cc \
arch/x86/entrypoints_init_x86.cc \
@@ -262,6 +273,7 @@ LIBART_HOST_SRC_FILES += \
arch/x86/portable_entrypoints_x86.S \
arch/x86/quick_entrypoints_x86.S \
arch/x86/thread_x86.cc
+endif
else # HOST_ARCH != x86
$(error unsupported HOST_ARCH=$(HOST_ARCH))
endif # HOST_ARCH != x86
diff --git a/runtime/arch/arm/context_arm.h b/runtime/arch/arm/context_arm.h
index 00651ff..020cae0 100644
--- a/runtime/arch/arm/context_arm.h
+++ b/runtime/arch/arm/context_arm.h
@@ -35,7 +35,7 @@ class ArmContext : public Context {
virtual void Reset();
- virtual void FillCalleeSaves(const StackVisitor& fr);
+ virtual void FillCalleeSaves(const StackVisitor& fr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
virtual void SetSP(uintptr_t new_sp) {
SetGPR(SP, new_sp);
diff --git a/runtime/arch/arm/portable_entrypoints_arm.S b/runtime/arch/arm/portable_entrypoints_arm.S
index ac519d5..98d17dc 100644
--- a/runtime/arch/arm/portable_entrypoints_arm.S
+++ b/runtime/arch/arm/portable_entrypoints_arm.S
@@ -53,7 +53,7 @@ ENTRY art_portable_invoke_stub
mov ip, #0 @ set ip to 0
str ip, [sp] @ store NULL for method* at bottom of frame
add sp, #16 @ first 4 args are not passed on stack for portable
- ldr ip, [r0, #METHOD_CODE_OFFSET] @ get pointer to the code
+ ldr ip, [r0, #METHOD_PORTABLE_CODE_OFFSET] @ get pointer to the code
blx ip @ call the method
mov sp, r11 @ restore the stack pointer
ldr ip, [sp, #24] @ load the result pointer
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index 34de93f..0e5c60a 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -302,7 +302,7 @@ ENTRY art_quick_invoke_stub
ldr r3, [sp, #12] @ copy arg value for r3
mov ip, #0 @ set ip to 0
str ip, [sp] @ store NULL for method* at bottom of frame
- ldr ip, [r0, #METHOD_CODE_OFFSET] @ get pointer to the code
+ ldr ip, [r0, #METHOD_QUICK_CODE_OFFSET] @ get pointer to the code
blx ip @ call the method
mov sp, r11 @ restore the stack pointer
ldr ip, [sp, #24] @ load the result pointer
diff --git a/runtime/arch/context.cc b/runtime/arch/context.cc
index 7075e42..5eaf809 100644
--- a/runtime/arch/context.cc
+++ b/runtime/arch/context.cc
@@ -22,6 +22,10 @@
#include "mips/context_mips.h"
#elif defined(__i386__)
#include "x86/context_x86.h"
+#elif defined(__x86_64__)
+#include "x86_64/context_x86_64.h"
+#else
+#include "base/logging.h"
#endif
namespace art {
@@ -33,8 +37,11 @@ Context* Context::Create() {
return new mips::MipsContext();
#elif defined(__i386__)
return new x86::X86Context();
+#elif defined(__x86_64__)
+ return new x86_64::X86_64Context();
#else
UNIMPLEMENTED(FATAL);
+ return nullptr;
#endif
}
diff --git a/runtime/arch/context.h b/runtime/arch/context.h
index 91e0cd6..3d11178 100644
--- a/runtime/arch/context.h
+++ b/runtime/arch/context.h
@@ -20,6 +20,8 @@
#include <stddef.h>
#include <stdint.h>
+#include "locks.h"
+
namespace art {
class StackVisitor;
@@ -38,7 +40,8 @@ class Context {
// Read values from callee saves in the given frame. The frame also holds
// the method that holds the layout.
- virtual void FillCalleeSaves(const StackVisitor& fr) = 0;
+ virtual void FillCalleeSaves(const StackVisitor& fr)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
// Set the stack pointer value
virtual void SetSP(uintptr_t new_sp) = 0;
diff --git a/runtime/arch/mips/context_mips.h b/runtime/arch/mips/context_mips.h
index 5595f86..4145cd3 100644
--- a/runtime/arch/mips/context_mips.h
+++ b/runtime/arch/mips/context_mips.h
@@ -33,7 +33,7 @@ class MipsContext : public Context {
virtual void Reset();
- virtual void FillCalleeSaves(const StackVisitor& fr);
+ virtual void FillCalleeSaves(const StackVisitor& fr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
virtual void SetSP(uintptr_t new_sp) {
SetGPR(SP, new_sp);
diff --git a/runtime/arch/mips/portable_entrypoints_mips.S b/runtime/arch/mips/portable_entrypoints_mips.S
index 9208a8a..7545ce0 100644
--- a/runtime/arch/mips/portable_entrypoints_mips.S
+++ b/runtime/arch/mips/portable_entrypoints_mips.S
@@ -61,5 +61,73 @@ ENTRY art_portable_proxy_invoke_handler
.cfi_adjust_cfa_offset -64
END art_portable_proxy_invoke_handler
+ /*
+ * Invocation stub for portable code.
+ * On entry:
+ * a0 = method pointer
+ * a1 = argument array or NULL for no argument methods
+ * a2 = size of argument array in bytes
+ * a3 = (managed) thread pointer
+ * [sp + 16] = JValue* result
+ * [sp + 20] = result type char
+ */
+ENTRY art_portable_invoke_stub
+ GENERATE_GLOBAL_POINTER
+ sw $a0, 0($sp) # save out a0
+ addiu $sp, $sp, -16 # spill s0, s1, fp, ra
+ .cfi_adjust_cfa_offset 16
+ sw $ra, 12($sp)
+ .cfi_rel_offset 31, 12
+ sw $fp, 8($sp)
+ .cfi_rel_offset 30, 8
+ sw $s1, 4($sp)
+ .cfi_rel_offset 17, 4
+ sw $s0, 0($sp)
+ .cfi_rel_offset 16, 0
+ move $fp, $sp # save sp in fp
+ .cfi_def_cfa_register 30
+ move $s1, $a3 # move managed thread pointer into s1
+ addiu $s0, $zero, SUSPEND_CHECK_INTERVAL # reset s0 to suspend check interval
+ addiu $t0, $a2, 16 # create space for method pointer in frame
+ srl $t0, $t0, 3 # shift the frame size right 3
+ sll $t0, $t0, 3 # shift the frame size left 3 to align to 16 bytes
+ subu $sp, $sp, $t0 # reserve stack space for argument array
+ addiu $a0, $sp, 4 # pass stack pointer + method ptr as dest for memcpy
+ jal memcpy # (dest, src, bytes)
+ addiu $sp, $sp, -16 # make space for argument slots for memcpy
+ addiu $sp, $sp, 16 # restore stack after memcpy
+ lw $a0, 16($fp) # restore method*
+ lw $a1, 4($sp) # copy arg value for a1
+ lw $a2, 8($sp) # copy arg value for a2
+ lw $a3, 12($sp) # copy arg value for a3
+ lw $t9, METHOD_PORTABLE_CODE_OFFSET($a0) # get pointer to the code
+ jalr $t9 # call the method
+ 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
+ lw $t1, 20($sp) # get result type char
+ li $t2, 68 # put char 'D' into t2
+ beq $t1, $t2, 1f # branch if result type char == 'D'
+ li $t3, 70 # put char 'F' into t3
+ beq $t1, $t3, 1f # branch if result type char == 'F'
+ sw $v0, 0($t0) # store the result
+ jr $ra
+ sw $v1, 4($t0) # store the other half of the result
+1:
+ s.s $f0, 0($t0) # store floating point result
+ jr $ra
+ s.s $f1, 4($t0) # store other half of floating point result
+END art_portable_invoke_stub
+
UNIMPLEMENTED art_portable_resolution_trampoline
UNIMPLEMENTED art_portable_to_interpreter_bridge
diff --git a/runtime/arch/mips/quick_entrypoints_mips.S b/runtime/arch/mips/quick_entrypoints_mips.S
index 2d1e87a..c60bca0 100644
--- a/runtime/arch/mips/quick_entrypoints_mips.S
+++ b/runtime/arch/mips/quick_entrypoints_mips.S
@@ -449,7 +449,7 @@ INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvoke
INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
/*
- * Common invocation stub for portable and quick.
+ * Invocation stub for quick code.
* On entry:
* a0 = method pointer
* a1 = argument array or NULL for no argument methods
@@ -458,9 +458,6 @@ INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvo
* [sp + 16] = JValue* result
* [sp + 20] = result type char
*/
- .type art_portable_invoke_stub, %function
- .global art_portable_invoke_stub
-art_portable_invoke_stub:
ENTRY art_quick_invoke_stub
GENERATE_GLOBAL_POINTER
sw $a0, 0($sp) # save out a0
@@ -490,7 +487,7 @@ ENTRY art_quick_invoke_stub
lw $a1, 4($sp) # copy arg value for a1
lw $a2, 8($sp) # copy arg value for a2
lw $a3, 12($sp) # copy arg value for a3
- lw $t9, METHOD_CODE_OFFSET($a0) # get pointer to the code
+ lw $t9, METHOD_QUICK_CODE_OFFSET($a0) # get pointer to the code
jalr $t9 # call the method
sw $zero, 0($sp) # store NULL for method* at bottom of frame
move $sp, $fp # restore the stack
@@ -518,7 +515,6 @@ ENTRY art_quick_invoke_stub
jr $ra
s.s $f1, 4($t0) # store other half of floating point result
END art_quick_invoke_stub
- .size art_portable_invoke_stub, .-art_portable_invoke_stub
/*
* Entry from managed code that calls artHandleFillArrayDataFromCode and delivers exception on
diff --git a/runtime/arch/x86/context_x86.cc b/runtime/arch/x86/context_x86.cc
index 66a51f7..d7dca64 100644
--- a/runtime/arch/x86/context_x86.cc
+++ b/runtime/arch/x86/context_x86.cc
@@ -23,7 +23,7 @@
namespace art {
namespace x86 {
-static const uint32_t gZero = 0;
+static const uintptr_t gZero = 0;
void X86Context::Reset() {
for (int i = 0; i < kNumberOfCpuRegisters; i++) {
@@ -55,8 +55,8 @@ void X86Context::FillCalleeSaves(const StackVisitor& fr) {
void X86Context::SmashCallerSaves() {
// This needs to be 0 because we want a null/zero return value.
- gprs_[EAX] = const_cast<uint32_t*>(&gZero);
- gprs_[EDX] = const_cast<uint32_t*>(&gZero);
+ gprs_[EAX] = const_cast<uintptr_t*>(&gZero);
+ gprs_[EDX] = const_cast<uintptr_t*>(&gZero);
gprs_[ECX] = NULL;
gprs_[EBX] = NULL;
}
@@ -89,7 +89,7 @@ void X86Context::DoLongJump() {
: "g"(&gprs[0]) // input.
:); // clobber.
#else
- UNIMPLEMENTED(FATAL);
+ UNIMPLEMENTED(FATAL);
#endif
}
diff --git a/runtime/arch/x86/context_x86.h b/runtime/arch/x86/context_x86.h
index d7d2210..598314d 100644
--- a/runtime/arch/x86/context_x86.h
+++ b/runtime/arch/x86/context_x86.h
@@ -33,7 +33,7 @@ class X86Context : public Context {
virtual void Reset();
- virtual void FillCalleeSaves(const StackVisitor& fr);
+ virtual void FillCalleeSaves(const StackVisitor& fr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
virtual void SetSP(uintptr_t new_sp) {
SetGPR(ESP, new_sp);
diff --git a/runtime/arch/x86/jni_entrypoints_x86.S b/runtime/arch/x86/jni_entrypoints_x86.S
index 72047d5..2eb5ada 100644
--- a/runtime/arch/x86/jni_entrypoints_x86.S
+++ b/runtime/arch/x86/jni_entrypoints_x86.S
@@ -17,7 +17,7 @@
#include "asm_support_x86.S"
/*
- * Portable resolution trampoline.
+ * Jni dlsym lookup stub.
*/
DEFINE_FUNCTION art_jni_dlsym_lookup_stub
subl LITERAL(4), %esp // align stack
diff --git a/runtime/arch/x86/portable_entrypoints_x86.S b/runtime/arch/x86/portable_entrypoints_x86.S
index 48de7c1..4bd6173 100644
--- a/runtime/arch/x86/portable_entrypoints_x86.S
+++ b/runtime/arch/x86/portable_entrypoints_x86.S
@@ -46,7 +46,7 @@ DEFINE_FUNCTION art_portable_invoke_stub
addl LITERAL(12), %esp // pop arguments to memcpy
mov 12(%ebp), %eax // move method pointer into eax
mov %eax, (%esp) // push method pointer onto stack
- call *METHOD_CODE_OFFSET(%eax) // call the method
+ call *METHOD_PORTABLE_CODE_OFFSET(%eax) // call the method
mov %ebp, %esp // restore stack pointer
POP ebx // pop ebx
POP ebp // pop ebp
diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S
index 74ec761..9c3eb30 100644
--- a/runtime/arch/x86/quick_entrypoints_x86.S
+++ b/runtime/arch/x86/quick_entrypoints_x86.S
@@ -275,7 +275,7 @@ DEFINE_FUNCTION art_quick_invoke_stub
mov 4(%esp), %ecx // copy arg1 into ecx
mov 8(%esp), %edx // copy arg2 into edx
mov 12(%esp), %ebx // copy arg3 into ebx
- call *METHOD_CODE_OFFSET(%eax) // call the method
+ call *METHOD_QUICK_CODE_OFFSET(%eax) // call the method
mov %ebp, %esp // restore stack pointer
CFI_DEF_CFA_REGISTER(esp)
POP ebx // pop ebx
diff --git a/runtime/arch/x86_64/asm_support_x86_64.S b/runtime/arch/x86_64/asm_support_x86_64.S
new file mode 100644
index 0000000..b59c0cb
--- /dev/null
+++ b/runtime/arch/x86_64/asm_support_x86_64.S
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef ART_RUNTIME_ARCH_X86_64_ASM_SUPPORT_X86_64_S_
+#define ART_RUNTIME_ARCH_X86_64_ASM_SUPPORT_X86_64_S_
+
+#include "asm_support_x86_64.h"
+
+#if defined(__APPLE__)
+ // Mac OS' as(1) doesn't let you name macro parameters.
+ #define MACRO0(macro_name) .macro macro_name
+ #define MACRO1(macro_name, macro_arg1) .macro macro_name
+ #define MACRO2(macro_name, macro_arg1, macro_args2) .macro macro_name
+ #define MACRO3(macro_name, macro_arg1, macro_args2, macro_args3) .macro macro_name
+ #define END_MACRO .endmacro
+
+ // Mac OS' as(1) uses $0, $1, and so on for macro arguments, and function names
+ // are mangled with an extra underscore prefix. The use of $x for arguments
+ // mean that literals need to be represented with $$x in macros.
+ #define SYMBOL(name) _ ## name
+ #define PLT_SYMBOL(name) _ ## name
+ #define VAR(name,index) SYMBOL($index)
+ #define PLT_VAR(name, index) SYMBOL($index)
+ #define REG_VAR(name,index) %$index
+ #define CALL_MACRO(name,index) $index
+ #define LITERAL(value) $value
+ #define MACRO_LITERAL(value) $$value
+
+ // Mac OS' doesn't like cfi_* directives
+ #define CFI_STARTPROC
+ #define CFI_ENDPROC
+ #define CFI_ADJUST_CFA_OFFSET(size)
+ #define CFI_DEF_CFA(reg,size)
+ #define CFI_DEF_CFA_REGISTER(reg)
+ #define CFI_RESTORE(reg)
+ #define CFI_REL_OFFSET(reg,size)
+
+ // Mac OS' doesn't support certain directives
+ #define FUNCTION_TYPE(name)
+ #define SIZE(name)
+#else
+ // Regular gas(1) lets you name macro parameters.
+ #define MACRO0(macro_name) .macro macro_name
+ #define MACRO1(macro_name, macro_arg1) .macro macro_name macro_arg1
+ #define MACRO2(macro_name, macro_arg1, macro_arg2) .macro macro_name macro_arg1, macro_arg2
+ #define MACRO3(macro_name, macro_arg1, macro_arg2, macro_arg3) .macro macro_name macro_arg1, macro_arg2, macro_arg3
+ #define END_MACRO .endm
+
+ // Regular gas(1) uses \argument_name for macro arguments.
+ // We need to turn on alternate macro syntax so we can use & instead or the preprocessor
+ // will screw us by inserting a space between the \ and the name. Even in this mode there's
+ // no special meaning to $, so literals are still just $x. The use of altmacro means % is a
+ // special character meaning care needs to be taken when passing registers as macro arguments.
+ .altmacro
+ #define SYMBOL(name) name
+ #define PLT_SYMBOL(name) name@PLT
+ #define VAR(name,index) name&
+ #define PLT_VAR(name, index) name&@PLT
+ #define REG_VAR(name,index) %name
+ #define CALL_MACRO(name,index) name&
+ #define LITERAL(value) $value
+ #define MACRO_LITERAL(value) $value
+
+ // CFI support
+ #define CFI_STARTPROC .cfi_startproc
+ #define CFI_ENDPROC .cfi_endproc
+ #define CFI_ADJUST_CFA_OFFSET(size) .cfi_adjust_cfa_offset size
+ #define CFI_DEF_CFA(reg,size) .cfi_def_cfa reg,size
+ #define CFI_DEF_CFA_REGISTER(reg) .cfi_def_cfa_register reg
+ #define CFI_RESTORE(reg) .cfi_restore reg
+ #define CFI_REL_OFFSET(reg,size) .cfi_rel_offset reg,size
+
+ #define FUNCTION_TYPE(name) .type name&, @function
+ #define SIZE(name) .size name, .-name
+#endif
+
+ /* Cache alignment for function entry */
+MACRO0(ALIGN_FUNCTION_ENTRY)
+ .balign 16
+END_MACRO
+
+MACRO1(DEFINE_FUNCTION, c_name)
+ FUNCTION_TYPE(\c_name)
+ .globl VAR(c_name, 0)
+ ALIGN_FUNCTION_ENTRY
+VAR(c_name, 0):
+ CFI_STARTPROC
+END_MACRO
+
+MACRO1(END_FUNCTION, c_name)
+ CFI_ENDPROC
+ SIZE(\c_name)
+END_MACRO
+
+MACRO1(PUSH, reg)
+ pushq REG_VAR(reg, 0)
+ CFI_ADJUST_CFA_OFFSET(8)
+ CFI_REL_OFFSET(REG_VAR(reg, 0), 0)
+END_MACRO
+
+MACRO1(POP, reg)
+ popq REG_VAR(reg,0)
+ CFI_ADJUST_CFA_OFFSET(-8)
+ CFI_RESTORE(REG_VAR(reg,0))
+END_MACRO
+
+MACRO1(UNIMPLEMENTED,name)
+ FUNCTION_TYPE(\name)
+ .globl VAR(name, 0)
+ ALIGN_FUNCTION_ENTRY
+VAR(name, 0):
+ CFI_STARTPROC
+ int3
+ int3
+ CFI_ENDPROC
+ SIZE(\name)
+END_MACRO
+
+MACRO0(SETUP_GOT_NOSAVE)
+ call __x86.get_pc_thunk.bx
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+END_MACRO
+
+MACRO0(SETUP_GOT)
+ PUSH ebx
+ SETUP_GOT_NOSAVE
+END_MACRO
+
+MACRO0(UNDO_SETUP_GOT)
+ POP ebx
+END_MACRO
+
+#endif // ART_RUNTIME_ARCH_X86_64_ASM_SUPPORT_X86_64_S_
diff --git a/runtime/arch/x86_64/asm_support_x86_64.h b/runtime/arch/x86_64/asm_support_x86_64.h
new file mode 100644
index 0000000..d425ed8
--- /dev/null
+++ b/runtime/arch/x86_64/asm_support_x86_64.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef ART_RUNTIME_ARCH_X86_64_ASM_SUPPORT_X86_64_H_
+#define ART_RUNTIME_ARCH_X86_64_ASM_SUPPORT_X86_64_H_
+
+#include "asm_support.h"
+
+// Offset of field Thread::self_ verified in InitCpu
+#define THREAD_SELF_OFFSET 72
+// Offset of field Thread::card_table_ verified in InitCpu
+#define THREAD_CARD_TABLE_OFFSET 8
+// Offset of field Thread::exception_ verified in InitCpu
+#define THREAD_EXCEPTION_OFFSET 16
+// Offset of field Thread::thin_lock_thread_id_ verified in InitCpu
+#define THREAD_ID_OFFSET 112
+
+#endif // ART_RUNTIME_ARCH_X86_64_ASM_SUPPORT_X86_64_H_
diff --git a/runtime/arch/x86_64/context_x86_64.cc b/runtime/arch/x86_64/context_x86_64.cc
new file mode 100644
index 0000000..4d1131c
--- /dev/null
+++ b/runtime/arch/x86_64/context_x86_64.cc
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2011 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 "context_x86_64.h"
+
+#include "mirror/art_method.h"
+#include "mirror/object-inl.h"
+#include "stack.h"
+
+namespace art {
+namespace x86_64 {
+
+static const uintptr_t gZero = 0;
+
+void X86_64Context::Reset() {
+ for (int i = 0; i < kNumberOfCpuRegisters; i++) {
+ gprs_[i] = NULL;
+ }
+ gprs_[RSP] = &rsp_;
+ // Initialize registers with easy to spot debug values.
+ rsp_ = X86_64Context::kBadGprBase + RSP;
+ rip_ = X86_64Context::kBadGprBase + kNumberOfCpuRegisters;
+}
+
+void X86_64Context::FillCalleeSaves(const StackVisitor& fr) {
+ mirror::ArtMethod* method = fr.GetMethod();
+ uint32_t core_spills = method->GetCoreSpillMask();
+ size_t spill_count = __builtin_popcount(core_spills);
+ DCHECK_EQ(method->GetFpSpillMask(), 0u);
+ size_t frame_size = method->GetFrameSizeInBytes();
+ if (spill_count > 0) {
+ // Lowest number spill is farthest away, walk registers and fill into context.
+ int j = 2; // Offset j to skip return address spill.
+ for (int i = 0; i < kNumberOfCpuRegisters; i++) {
+ if (((core_spills >> i) & 1) != 0) {
+ gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_size);
+ j++;
+ }
+ }
+ }
+}
+
+void X86_64Context::SmashCallerSaves() {
+ // This needs to be 0 because we want a null/zero return value.
+ gprs_[RAX] = const_cast<uintptr_t*>(&gZero);
+ gprs_[RDX] = const_cast<uintptr_t*>(&gZero);
+ gprs_[RCX] = nullptr;
+ gprs_[RBX] = nullptr;
+}
+
+void X86_64Context::SetGPR(uint32_t reg, uintptr_t value) {
+ CHECK_LT(reg, static_cast<uint32_t>(kNumberOfCpuRegisters));
+ CHECK_NE(gprs_[reg], &gZero);
+ CHECK(gprs_[reg] != NULL);
+ *gprs_[reg] = value;
+}
+
+void X86_64Context::DoLongJump() {
+ UNIMPLEMENTED(FATAL);
+}
+
+} // namespace x86_64
+} // namespace art
diff --git a/runtime/arch/x86_64/context_x86_64.h b/runtime/arch/x86_64/context_x86_64.h
new file mode 100644
index 0000000..3e49165
--- /dev/null
+++ b/runtime/arch/x86_64/context_x86_64.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef ART_RUNTIME_ARCH_X86_64_CONTEXT_X86_64_H_
+#define ART_RUNTIME_ARCH_X86_64_CONTEXT_X86_64_H_
+
+#include "arch/context.h"
+#include "base/logging.h"
+#include "registers_x86_64.h"
+
+namespace art {
+namespace x86_64 {
+
+class X86_64Context : public Context {
+ public:
+ X86_64Context() {
+ Reset();
+ }
+ virtual ~X86_64Context() {}
+
+ virtual void Reset();
+
+ virtual void FillCalleeSaves(const StackVisitor& fr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ virtual void SetSP(uintptr_t new_sp) {
+ SetGPR(RSP, new_sp);
+ }
+
+ virtual void SetPC(uintptr_t new_pc) {
+ rip_ = new_pc;
+ }
+
+ virtual uintptr_t GetGPR(uint32_t reg) {
+ const uint32_t kNumberOfCpuRegisters = 8;
+ DCHECK_LT(reg, kNumberOfCpuRegisters);
+ return *gprs_[reg];
+ }
+
+ virtual void SetGPR(uint32_t reg, uintptr_t value);
+
+ virtual void SmashCallerSaves();
+ virtual void DoLongJump();
+
+ private:
+ // Pointers to register locations, floating point registers are all caller save. Values are
+ // initialized to NULL or the special registers below.
+ uintptr_t* gprs_[kNumberOfCpuRegisters];
+ // Hold values for rsp and rip if they are not located within a stack frame. RIP is somewhat
+ // special in that it cannot be encoded normally as a register operand to an instruction (except
+ // in 64bit addressing modes).
+ uintptr_t rsp_, rip_;
+};
+} // namespace x86_64
+} // namespace art
+
+#endif // ART_RUNTIME_ARCH_X86_64_CONTEXT_X86_64_H_
diff --git a/runtime/arch/x86_64/entrypoints_init_x86_64.cc b/runtime/arch/x86_64/entrypoints_init_x86_64.cc
new file mode 100644
index 0000000..589c7d9
--- /dev/null
+++ b/runtime/arch/x86_64/entrypoints_init_x86_64.cc
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2012 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 "entrypoints/portable/portable_entrypoints.h"
+#include "entrypoints/quick/quick_entrypoints.h"
+#include "entrypoints/entrypoint_utils.h"
+
+namespace art {
+
+// Interpreter entrypoints.
+extern "C" void artInterpreterToInterpreterBridge(Thread* self, MethodHelper& mh,
+ const DexFile::CodeItem* code_item,
+ ShadowFrame* shadow_frame, JValue* result);
+extern "C" void artInterpreterToCompiledCodeBridge(Thread* self, MethodHelper& mh,
+ const DexFile::CodeItem* code_item,
+ ShadowFrame* shadow_frame, JValue* result);
+
+// Portable entrypoints.
+extern "C" void art_portable_resolution_trampoline(mirror::ArtMethod*);
+extern "C" void art_portable_to_interpreter_bridge(mirror::ArtMethod*);
+
+// Cast entrypoints.
+extern "C" uint32_t art_quick_is_assignable(const mirror::Class* klass,
+ const mirror::Class* ref_class);
+extern "C" void art_quick_check_cast(void*, void*);
+
+// DexCache entrypoints.
+extern "C" void* art_quick_initialize_static_storage(uint32_t, void*);
+extern "C" void* art_quick_initialize_type(uint32_t, void*);
+extern "C" void* art_quick_initialize_type_and_verify_access(uint32_t, void*);
+extern "C" void* art_quick_resolve_string(void*, uint32_t);
+
+// Field entrypoints.
+extern "C" int art_quick_set32_instance(uint32_t, void*, int32_t);
+extern "C" int art_quick_set32_static(uint32_t, int32_t);
+extern "C" int art_quick_set64_instance(uint32_t, void*, int64_t);
+extern "C" int art_quick_set64_static(uint32_t, int64_t);
+extern "C" int art_quick_set_obj_instance(uint32_t, void*, void*);
+extern "C" int art_quick_set_obj_static(uint32_t, void*);
+extern "C" int32_t art_quick_get32_instance(uint32_t, void*);
+extern "C" int32_t art_quick_get32_static(uint32_t);
+extern "C" int64_t art_quick_get64_instance(uint32_t, void*);
+extern "C" int64_t art_quick_get64_static(uint32_t);
+extern "C" void* art_quick_get_obj_instance(uint32_t, void*);
+extern "C" void* art_quick_get_obj_static(uint32_t);
+
+// Array entrypoints.
+extern "C" void art_quick_aput_obj_with_null_and_bound_check(void*, uint32_t, void*);
+extern "C" void art_quick_aput_obj_with_bound_check(void*, uint32_t, void*);
+extern "C" void art_quick_aput_obj(void*, uint32_t, void*);
+extern "C" void art_quick_handle_fill_data(void*, void*);
+
+// Lock entrypoints.
+extern "C" void art_quick_lock_object(void*);
+extern "C" void art_quick_unlock_object(void*);
+
+// Math entrypoints.
+extern "C" double art_quick_fmod(double, double);
+extern "C" float art_quick_fmodf(float, float);
+extern "C" double art_quick_l2d(int64_t);
+extern "C" float art_quick_l2f(int64_t);
+extern "C" int64_t art_quick_d2l(double);
+extern "C" int64_t art_quick_f2l(float);
+extern "C" int32_t art_quick_idivmod(int32_t, int32_t);
+extern "C" int64_t art_quick_ldiv(int64_t, int64_t);
+extern "C" int64_t art_quick_lmod(int64_t, int64_t);
+extern "C" int64_t art_quick_lmul(int64_t, int64_t);
+extern "C" uint64_t art_quick_lshl(uint64_t, uint32_t);
+extern "C" uint64_t art_quick_lshr(uint64_t, uint32_t);
+extern "C" uint64_t art_quick_lushr(uint64_t, uint32_t);
+
+// Intrinsic entrypoints.
+extern "C" int32_t art_quick_memcmp16(void*, void*, int32_t);
+extern "C" int32_t art_quick_indexof(void*, uint32_t, uint32_t, uint32_t);
+extern "C" int32_t art_quick_string_compareto(void*, void*);
+extern "C" void* art_quick_memcpy(void*, const void*, size_t);
+
+// Invoke entrypoints.
+extern "C" void art_quick_imt_conflict_trampoline(mirror::ArtMethod*);
+extern "C" void art_quick_resolution_trampoline(mirror::ArtMethod*);
+extern "C" void art_quick_to_interpreter_bridge(mirror::ArtMethod*);
+extern "C" void art_quick_invoke_direct_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_quick_invoke_interface_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_quick_invoke_static_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_quick_invoke_super_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_quick_invoke_virtual_trampoline_with_access_check(uint32_t, void*);
+
+// Thread entrypoints.
+extern void CheckSuspendFromCode(Thread* thread);
+extern "C" void art_quick_test_suspend();
+
+// Throw entrypoints.
+extern "C" void art_quick_deliver_exception(void*);
+extern "C" void art_quick_throw_array_bounds(int32_t index, int32_t limit);
+extern "C" void art_quick_throw_div_zero();
+extern "C" void art_quick_throw_no_such_method(int32_t method_idx);
+extern "C" void art_quick_throw_null_pointer_exception();
+extern "C" void art_quick_throw_stack_overflow(void*);
+
+extern void ResetQuickAllocEntryPoints(QuickEntryPoints* qpoints);
+
+void InitEntryPoints(InterpreterEntryPoints* ipoints, JniEntryPoints* jpoints,
+ PortableEntryPoints* ppoints, QuickEntryPoints* qpoints) {
+ // Interpreter
+ ipoints->pInterpreterToInterpreterBridge = artInterpreterToInterpreterBridge;
+ ipoints->pInterpreterToCompiledCodeBridge = artInterpreterToCompiledCodeBridge;
+
+ // JNI
+ jpoints->pDlsymLookup = art_jni_dlsym_lookup_stub;
+
+ // Portable
+ ppoints->pPortableResolutionTrampoline = art_portable_resolution_trampoline;
+ ppoints->pPortableToInterpreterBridge = art_portable_to_interpreter_bridge;
+
+ // Alloc
+ ResetQuickAllocEntryPoints(qpoints);
+
+ // Cast
+ qpoints->pInstanceofNonTrivial = art_quick_is_assignable;
+ qpoints->pCheckCast = art_quick_check_cast;
+
+ // DexCache
+ qpoints->pInitializeStaticStorage = art_quick_initialize_static_storage;
+ qpoints->pInitializeTypeAndVerifyAccess = art_quick_initialize_type_and_verify_access;
+ qpoints->pInitializeType = art_quick_initialize_type;
+ qpoints->pResolveString = art_quick_resolve_string;
+
+ // Field
+ qpoints->pSet32Instance = art_quick_set32_instance;
+ qpoints->pSet32Static = art_quick_set32_static;
+ qpoints->pSet64Instance = art_quick_set64_instance;
+ qpoints->pSet64Static = art_quick_set64_static;
+ qpoints->pSetObjInstance = art_quick_set_obj_instance;
+ qpoints->pSetObjStatic = art_quick_set_obj_static;
+ qpoints->pGet32Instance = art_quick_get32_instance;
+ qpoints->pGet64Instance = art_quick_get64_instance;
+ qpoints->pGetObjInstance = art_quick_get_obj_instance;
+ qpoints->pGet32Static = art_quick_get32_static;
+ qpoints->pGet64Static = art_quick_get64_static;
+ qpoints->pGetObjStatic = art_quick_get_obj_static;
+
+ // Array
+ qpoints->pAputObjectWithNullAndBoundCheck = art_quick_aput_obj_with_null_and_bound_check;
+ qpoints->pAputObjectWithBoundCheck = art_quick_aput_obj_with_bound_check;
+ qpoints->pAputObject = art_quick_aput_obj;
+ qpoints->pHandleFillArrayData = art_quick_handle_fill_data;
+
+ // JNI
+ qpoints->pJniMethodStart = JniMethodStart;
+ qpoints->pJniMethodStartSynchronized = JniMethodStartSynchronized;
+ qpoints->pJniMethodEnd = JniMethodEnd;
+ qpoints->pJniMethodEndSynchronized = JniMethodEndSynchronized;
+ qpoints->pJniMethodEndWithReference = JniMethodEndWithReference;
+ qpoints->pJniMethodEndWithReferenceSynchronized = JniMethodEndWithReferenceSynchronized;
+
+ // Locks
+ qpoints->pLockObject = art_quick_lock_object;
+ qpoints->pUnlockObject = art_quick_unlock_object;
+
+ // Math
+ // points->pCmpgDouble = NULL; // Not needed on x86.
+ // points->pCmpgFloat = NULL; // Not needed on x86.
+ // points->pCmplDouble = NULL; // Not needed on x86.
+ // points->pCmplFloat = NULL; // Not needed on x86.
+ qpoints->pFmod = art_quick_fmod;
+ // qpoints->pSqrt = NULL; // Not needed on x86.
+ qpoints->pL2d = art_quick_l2d;
+ qpoints->pFmodf = art_quick_fmodf;
+ qpoints->pL2f = art_quick_l2f;
+ // points->pD2iz = NULL; // Not needed on x86.
+ // points->pF2iz = NULL; // Not needed on x86.
+ qpoints->pIdivmod = art_quick_idivmod;
+ qpoints->pD2l = art_quick_d2l;
+ qpoints->pF2l = art_quick_f2l;
+ qpoints->pLdiv = art_quick_ldiv;
+ qpoints->pLmod = art_quick_lmod;
+ qpoints->pLmul = art_quick_lmul;
+ qpoints->pShlLong = art_quick_lshl;
+ qpoints->pShrLong = art_quick_lshr;
+ qpoints->pUshrLong = art_quick_lushr;
+
+ // Intrinsics
+ qpoints->pIndexOf = art_quick_indexof;
+ qpoints->pMemcmp16 = art_quick_memcmp16;
+ qpoints->pStringCompareTo = art_quick_string_compareto;
+ qpoints->pMemcpy = art_quick_memcpy;
+
+ // Invocation
+ qpoints->pQuickImtConflictTrampoline = art_quick_imt_conflict_trampoline;
+ qpoints->pQuickResolutionTrampoline = art_quick_resolution_trampoline;
+ qpoints->pQuickToInterpreterBridge = art_quick_to_interpreter_bridge;
+ qpoints->pInvokeDirectTrampolineWithAccessCheck = art_quick_invoke_direct_trampoline_with_access_check;
+ qpoints->pInvokeInterfaceTrampolineWithAccessCheck = art_quick_invoke_interface_trampoline_with_access_check;
+ qpoints->pInvokeStaticTrampolineWithAccessCheck = art_quick_invoke_static_trampoline_with_access_check;
+ qpoints->pInvokeSuperTrampolineWithAccessCheck = art_quick_invoke_super_trampoline_with_access_check;
+ qpoints->pInvokeVirtualTrampolineWithAccessCheck = art_quick_invoke_virtual_trampoline_with_access_check;
+
+ // Thread
+ qpoints->pCheckSuspend = CheckSuspendFromCode;
+ qpoints->pTestSuspend = art_quick_test_suspend;
+
+ // Throws
+ qpoints->pDeliverException = art_quick_deliver_exception;
+ qpoints->pThrowArrayBounds = art_quick_throw_array_bounds;
+ qpoints->pThrowDivZero = art_quick_throw_div_zero;
+ qpoints->pThrowNoSuchMethod = art_quick_throw_no_such_method;
+ qpoints->pThrowNullPointer = art_quick_throw_null_pointer_exception;
+ qpoints->pThrowStackOverflow = art_quick_throw_stack_overflow;
+};
+
+} // namespace art
diff --git a/runtime/arch/x86_64/jni_entrypoints_x86_64.S b/runtime/arch/x86_64/jni_entrypoints_x86_64.S
new file mode 100644
index 0000000..35fcccb
--- /dev/null
+++ b/runtime/arch/x86_64/jni_entrypoints_x86_64.S
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 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 "asm_support_x86_64.S"
+
+ /*
+ * Jni dlsym lookup stub.
+ */
+UNIMPLEMENTED art_jni_dlsym_lookup_stub
diff --git a/runtime/arch/x86_64/portable_entrypoints_x86_64.S b/runtime/arch/x86_64/portable_entrypoints_x86_64.S
new file mode 100644
index 0000000..2e9d19a
--- /dev/null
+++ b/runtime/arch/x86_64/portable_entrypoints_x86_64.S
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012 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 "asm_support_x86_64.S"
+
+ /*
+ * Portable invocation stub.
+ */
+UNIMPLEMENTED art_portable_invoke_stub
+
+UNIMPLEMENTED art_portable_proxy_invoke_handler
+
+UNIMPLEMENTED art_portable_resolution_trampoline
+
+UNIMPLEMENTED art_portable_to_interpreter_bridge
diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
new file mode 100644
index 0000000..e01a31b
--- /dev/null
+++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2012 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 "asm_support_x86_64.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)
+ int3
+ int3
+END_MACRO
+
+ /*
+ * Macro that sets up the callee save frame to conform with
+ * Runtime::CreateCalleeSaveMethod(kRefsOnly)
+ */
+MACRO0(SETUP_REF_ONLY_CALLEE_SAVE_FRAME)
+ int3
+ int3
+END_MACRO
+
+MACRO0(RESTORE_REF_ONLY_CALLEE_SAVE_FRAME)
+ int3
+ int3
+END_MACRO
+
+ /*
+ * Macro that sets up the callee save frame to conform with
+ * Runtime::CreateCalleeSaveMethod(kRefsAndArgs)
+ */
+MACRO0(SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME)
+ int3
+ int3
+END_MACRO
+
+MACRO0(RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME)
+ int3
+END_MACRO
+
+ /*
+ * Macro that set calls through to artDeliverPendingExceptionFromCode, where the pending
+ * exception is Thread::Current()->exception_.
+ */
+MACRO0(DELIVER_PENDING_EXCEPTION)
+ int3
+ int3
+END_MACRO
+
+MACRO2(NO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
+ DEFINE_FUNCTION VAR(c_name, 0)
+ int3
+ int3
+ END_FUNCTION VAR(c_name, 0)
+END_MACRO
+
+MACRO2(ONE_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
+ DEFINE_FUNCTION VAR(c_name, 0)
+ int3
+ int3
+ END_FUNCTION VAR(c_name, 0)
+END_MACRO
+
+MACRO2(TWO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
+ DEFINE_FUNCTION VAR(c_name, 0)
+ int3
+ int3
+ END_FUNCTION VAR(c_name, 0)
+END_MACRO
+
+ /*
+ * Called by managed code to create and deliver a NullPointerException.
+ */
+NO_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception, artThrowNullPointerExceptionFromCode
+
+ /*
+ * Called by managed code to create and deliver an ArithmeticException.
+ */
+NO_ARG_RUNTIME_EXCEPTION art_quick_throw_div_zero, artThrowDivZeroFromCode
+
+ /*
+ * Called by managed code to create and deliver a StackOverflowError.
+ */
+NO_ARG_RUNTIME_EXCEPTION art_quick_throw_stack_overflow, artThrowStackOverflowFromCode
+
+ /*
+ * Called by managed code, saves callee saves and then calls artThrowException
+ * that will place a mock Method* at the bottom of the stack. Arg1 holds the exception.
+ */
+ONE_ARG_RUNTIME_EXCEPTION art_quick_deliver_exception, artDeliverExceptionFromCode
+
+ /*
+ * Called by managed code to create and deliver a NoSuchMethodError.
+ */
+ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_no_such_method, artThrowNoSuchMethodFromCode
+
+ /*
+ * Called by managed code to create and deliver an ArrayIndexOutOfBoundsException. Arg1 holds
+ * index, arg2 holds limit.
+ */
+TWO_ARG_RUNTIME_EXCEPTION art_quick_throw_array_bounds, artThrowArrayBoundsFromCode
+
+ /*
+ * All generated callsites for interface invokes and invocation slow paths will load arguments
+ * as usual - except instead of loading arg0/r0 with the target Method*, arg0/r0 will contain
+ * the method_idx. This wrapper will save arg1-arg3, load the caller's Method*, align the
+ * stack and call the appropriate C helper.
+ * NOTE: "this" is first visible argument of the target, and so can be found in arg1/r1.
+ *
+ * The helper will attempt to locate the target and return a 64-bit result in r0/r1 consisting
+ * of the target Method* in r0 and method->code_ in r1.
+ *
+ * If unsuccessful, the helper will return NULL/NULL. There will bea pending exception in the
+ * thread and we branch to another stub to deliver it.
+ *
+ * On success this wrapper will restore arguments and *jump* to the target, leaving the lr
+ * pointing back to the original caller.
+ */
+MACRO2(INVOKE_TRAMPOLINE, c_name, cxx_name)
+ DEFINE_FUNCTION VAR(c_name, 0)
+ int3
+ int3
+ END_FUNCTION VAR(c_name, 0)
+END_MACRO
+
+INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline, artInvokeInterfaceTrampoline
+INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline_with_access_check, artInvokeInterfaceTrampolineWithAccessCheck
+
+INVOKE_TRAMPOLINE art_quick_invoke_static_trampoline_with_access_check, artInvokeStaticTrampolineWithAccessCheck
+INVOKE_TRAMPOLINE art_quick_invoke_direct_trampoline_with_access_check, artInvokeDirectTrampolineWithAccessCheck
+INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck
+INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
+
+ /*
+ * Quick invocation stub.
+ */
+DEFINE_FUNCTION art_quick_invoke_stub
+ int3
+ int3
+END_FUNCTION art_quick_invoke_stub
+
+MACRO3(NO_ARG_DOWNCALL, c_name, cxx_name, return_macro)
+ DEFINE_FUNCTION VAR(c_name, 0)
+ int3
+ int3
+ END_FUNCTION VAR(c_name, 0)
+END_MACRO
+
+MACRO3(ONE_ARG_DOWNCALL, c_name, cxx_name, return_macro)
+ DEFINE_FUNCTION VAR(c_name, 0)
+ int3
+ int3
+ END_FUNCTION VAR(c_name, 0)
+END_MACRO
+
+MACRO3(TWO_ARG_DOWNCALL, c_name, cxx_name, return_macro)
+ DEFINE_FUNCTION VAR(c_name, 0)
+ int3
+ int3
+ END_FUNCTION VAR(c_name, 0)
+END_MACRO
+
+MACRO3(THREE_ARG_DOWNCALL, c_name, cxx_name, return_macro)
+ DEFINE_FUNCTION VAR(c_name, 0)
+ int3
+ int3
+ END_FUNCTION VAR(c_name, 0)
+END_MACRO
+
+MACRO0(RETURN_IF_RESULT_IS_NON_ZERO)
+ int3
+ testl %eax, %eax // eax == 0 ?
+ jz 1f // if eax == 0 goto 1
+ ret // return
+1: // deliver exception on current thread
+ DELIVER_PENDING_EXCEPTION
+END_MACRO
+
+MACRO0(RETURN_IF_EAX_ZERO)
+ int3
+ testl %eax, %eax // eax == 0 ?
+ jnz 1f // if eax != 0 goto 1
+ ret // return
+1: // deliver exception on current thread
+ DELIVER_PENDING_EXCEPTION
+END_MACRO
+
+MACRO0(RETURN_OR_DELIVER_PENDING_EXCEPTION)
+ int3
+ int3
+ DELIVER_PENDING_EXCEPTION
+END_MACRO
+
+// Generate the allocation entrypoints for each allocator.
+// TODO: use arch/quick_alloc_entrypoints.S. Currently we don't as we need to use concatenation
+// macros to work around differences between OS/X's as and binutils as (OS/X lacks named arguments
+// to macros and the VAR macro won't concatenate arguments properly), this also breaks having
+// multi-line macros that use each other (hence using 1 macro per newline below).
+#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(c_suffix, cxx_suffix) \
+ TWO_ARG_DOWNCALL art_quick_alloc_object ## c_suffix, artAllocObjectFromCode ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
+#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(c_suffix, cxx_suffix) \
+ TWO_ARG_DOWNCALL art_quick_alloc_object_resolved ## c_suffix, artAllocObjectFromCodeResolved ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
+#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(c_suffix, cxx_suffix) \
+ TWO_ARG_DOWNCALL art_quick_alloc_object_initialized ## c_suffix, artAllocObjectFromCodeInitialized ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
+#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(c_suffix, cxx_suffix) \
+ TWO_ARG_DOWNCALL art_quick_alloc_object_with_access_check ## c_suffix, artAllocObjectFromCodeWithAccessCheck ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
+#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(c_suffix, cxx_suffix) \
+ THREE_ARG_DOWNCALL art_quick_alloc_array ## c_suffix, artAllocArrayFromCode ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
+#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(c_suffix, cxx_suffix) \
+ THREE_ARG_DOWNCALL art_quick_alloc_array_resolved ## c_suffix, artAllocArrayFromCodeResolved ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
+#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(c_suffix, cxx_suffix) \
+ THREE_ARG_DOWNCALL art_quick_alloc_array_with_access_check ## c_suffix, artAllocArrayFromCodeWithAccessCheck ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
+#define GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(c_suffix, cxx_suffix) \
+ THREE_ARG_DOWNCALL art_quick_check_and_alloc_array ## c_suffix, artCheckAndAllocArrayFromCode ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
+#define GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(c_suffix, cxx_suffix) \
+ THREE_ARG_DOWNCALL art_quick_check_and_alloc_array_with_access_check ## c_suffix, artCheckAndAllocArrayFromCodeWithAccessCheck ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
+
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_dlmalloc, DlMalloc)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_dlmalloc, DlMalloc)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_dlmalloc, DlMalloc)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_dlmalloc, DlMalloc)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_dlmalloc, DlMalloc)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_dlmalloc, DlMalloc)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_dlmalloc, DlMalloc)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_dlmalloc, DlMalloc)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_dlmalloc, DlMalloc)
+
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_dlmalloc_instrumented, DlMallocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_dlmalloc_instrumented, DlMallocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_dlmalloc_instrumented, DlMallocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_dlmalloc_instrumented, DlMallocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_dlmalloc_instrumented, DlMallocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_dlmalloc_instrumented, DlMallocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_dlmalloc_instrumented, DlMallocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_dlmalloc_instrumented, DlMallocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_dlmalloc_instrumented, DlMallocInstrumented)
+
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_rosalloc, RosAlloc)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_rosalloc, RosAlloc)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_rosalloc, RosAlloc)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_rosalloc, RosAlloc)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_rosalloc, RosAlloc)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_rosalloc, RosAlloc)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_rosalloc, RosAlloc)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_rosalloc, RosAlloc)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_rosalloc, RosAlloc)
+
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_rosalloc_instrumented, RosAllocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_rosalloc_instrumented, RosAllocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_rosalloc_instrumented, RosAllocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_rosalloc_instrumented, RosAllocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_rosalloc_instrumented, RosAllocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_rosalloc_instrumented, RosAllocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_rosalloc_instrumented, RosAllocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_rosalloc_instrumented, RosAllocInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_rosalloc_instrumented, RosAllocInstrumented)
+
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_bump_pointer, BumpPointer)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_bump_pointer, BumpPointer)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_bump_pointer, BumpPointer)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_bump_pointer, BumpPointer)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_bump_pointer, BumpPointer)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_bump_pointer, BumpPointer)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_bump_pointer, BumpPointer)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_bump_pointer, BumpPointer)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_bump_pointer, BumpPointer)
+
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_bump_pointer_instrumented, BumpPointerInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_bump_pointer_instrumented, BumpPointerInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_bump_pointer_instrumented, BumpPointerInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_bump_pointer_instrumented, BumpPointerInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_bump_pointer_instrumented, BumpPointerInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_bump_pointer_instrumented, BumpPointerInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_bump_pointer_instrumented, BumpPointerInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_bump_pointer_instrumented, BumpPointerInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_bump_pointer_instrumented, BumpPointerInstrumented)
+
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_tlab, TLAB)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_tlab, TLAB)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_tlab, TLAB)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_tlab, TLAB)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_tlab, TLAB)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_tlab, TLAB)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_tlab, TLAB)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_tlab, TLAB)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_tlab, TLAB)
+
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_tlab_instrumented, TLABInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_tlab_instrumented, TLABInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_tlab_instrumented, TLABInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_tlab_instrumented, TLABInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_tlab_instrumented, TLABInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_tlab_instrumented, TLABInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_tlab_instrumented, TLABInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_tlab_instrumented, TLABInstrumented)
+GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_tlab_instrumented, TLABInstrumented)
+
+TWO_ARG_DOWNCALL art_quick_resolve_string, artResolveStringFromCode, RETURN_IF_RESULT_IS_NON_ZERO
+TWO_ARG_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode, RETURN_IF_RESULT_IS_NON_ZERO
+TWO_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_RESULT_IS_NON_ZERO
+TWO_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_RESULT_IS_NON_ZERO
+
+TWO_ARG_DOWNCALL art_quick_handle_fill_data, artHandleFillArrayDataFromCode, RETURN_IF_EAX_ZERO
+
+DEFINE_FUNCTION art_quick_lock_object
+ int3
+ int3
+END_FUNCTION art_quick_lock_object
+
+DEFINE_FUNCTION art_quick_unlock_object
+ int3
+ int3
+END_FUNCTION art_quick_unlock_object
+
+DEFINE_FUNCTION art_quick_is_assignable
+ int3
+ int3
+END_FUNCTION art_quick_is_assignable
+
+DEFINE_FUNCTION art_quick_check_cast
+ int3
+ int3
+END_FUNCTION art_quick_check_cast
+
+ /*
+ * Entry from managed code for array put operations of objects where the value being stored
+ * needs to be checked for compatibility.
+ * eax = array, ecx = index, edx = value
+ */
+UNIMPLEMENTED art_quick_aput_obj_with_null_and_bound_check
+UNIMPLEMENTED art_quick_aput_obj_with_bound_check
+UNIMPLEMENTED art_quick_aput_obj
+UNIMPLEMENTED art_quick_memcpy
+
+NO_ARG_DOWNCALL art_quick_test_suspend, artTestSuspendFromCode, ret
+
+UNIMPLEMENTED art_quick_fmod
+UNIMPLEMENTED art_quick_fmodf
+UNIMPLEMENTED art_quick_l2d
+UNIMPLEMENTED art_quick_l2f
+UNIMPLEMENTED art_quick_d2l
+UNIMPLEMENTED art_quick_f2l
+UNIMPLEMENTED art_quick_idivmod
+UNIMPLEMENTED art_quick_ldiv
+UNIMPLEMENTED art_quick_lmod
+UNIMPLEMENTED art_quick_lmul
+UNIMPLEMENTED art_quick_lshl
+UNIMPLEMENTED art_quick_lshr
+UNIMPLEMENTED art_quick_lushr
+UNIMPLEMENTED art_quick_set32_instance
+UNIMPLEMENTED art_quick_set64_instance
+UNIMPLEMENTED art_quick_set_obj_instance
+UNIMPLEMENTED art_quick_get32_instance
+UNIMPLEMENTED art_quick_get64_instance
+UNIMPLEMENTED art_quick_get_obj_instance
+UNIMPLEMENTED art_quick_set32_static
+UNIMPLEMENTED art_quick_set64_static
+UNIMPLEMENTED art_quick_set_obj_static
+UNIMPLEMENTED art_quick_get32_static
+UNIMPLEMENTED art_quick_get64_static
+UNIMPLEMENTED art_quick_get_obj_static
+UNIMPLEMENTED art_quick_proxy_invoke_handler
+
+ /*
+ * Called to resolve an imt conflict.
+ */
+UNIMPLEMENTED art_quick_imt_conflict_trampoline
+UNIMPLEMENTED art_quick_resolution_trampoline
+UNIMPLEMENTED art_quick_to_interpreter_bridge
+
+ /*
+ * Routine that intercepts method calls and returns.
+ */
+UNIMPLEMENTED art_quick_instrumentation_entry
+UNIMPLEMENTED art_quick_instrumentation_exit
+
+ /*
+ * Instrumentation has requested that we deoptimize into the interpreter. The deoptimization
+ * will long jump to the upcall with a special exception of -1.
+ */
+UNIMPLEMENTED art_quick_deoptimize
+
+UNIMPLEMENTED art_quick_indexof
+UNIMPLEMENTED art_quick_string_compareto
+UNIMPLEMENTED art_quick_memcmp16
diff --git a/runtime/arch/x86_64/registers_x86_64.cc b/runtime/arch/x86_64/registers_x86_64.cc
new file mode 100644
index 0000000..38f3494
--- /dev/null
+++ b/runtime/arch/x86_64/registers_x86_64.cc
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2011 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 "registers_x86_64.h"
+
+#include <ostream>
+
+namespace art {
+namespace x86_64 {
+
+static const char* kRegisterNames[] = {
+ "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+};
+std::ostream& operator<<(std::ostream& os, const Register& rhs) {
+ if (rhs >= RAX && rhs <= R15) {
+ os << kRegisterNames[rhs];
+ } else {
+ os << "Register[" << static_cast<int>(rhs) << "]";
+ }
+ return os;
+}
+
+} // namespace x86_64
+} // namespace art
diff --git a/runtime/arch/x86_64/registers_x86_64.h b/runtime/arch/x86_64/registers_x86_64.h
new file mode 100644
index 0000000..9808d91
--- /dev/null
+++ b/runtime/arch/x86_64/registers_x86_64.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef ART_RUNTIME_ARCH_X86_64_REGISTERS_X86_64_H_
+#define ART_RUNTIME_ARCH_X86_64_REGISTERS_X86_64_H_
+
+#include <iosfwd>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "globals.h"
+
+namespace art {
+namespace x86_64 {
+
+enum Register {
+ RAX = 0,
+ RCX = 1,
+ RDX = 2,
+ RBX = 3,
+ RSP = 4,
+ RBP = 5,
+ RSI = 6,
+ RDI = 7,
+ R8 = 8,
+ R9 = 9,
+ R10 = 10,
+ R11 = 11,
+ R12 = 12,
+ R13 = 13,
+ R14 = 14,
+ R15 = 15,
+ kNumberOfCpuRegisters = 16,
+ kNoRegister = -1 // Signals an illegal register.
+};
+std::ostream& operator<<(std::ostream& os, const Register& rhs);
+
+} // namespace x86_64
+} // namespace art
+
+#endif // ART_RUNTIME_ARCH_X86_64_REGISTERS_X86_64_H_
diff --git a/runtime/arch/x86_64/thread_x86_64.cc b/runtime/arch/x86_64/thread_x86_64.cc
new file mode 100644
index 0000000..9e45a72
--- /dev/null
+++ b/runtime/arch/x86_64/thread_x86_64.cc
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2011 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 "thread.h"
+
+#include "asm_support_x86_64.h"
+#include "base/macros.h"
+#include "thread-inl.h"
+#include "thread_list.h"
+
+#include <asm/prctl.h>
+#include <sys/prctl.h>
+#include <sys/syscall.h>
+
+namespace art {
+
+static void arch_prctl(int code, void* val) {
+ syscall(__NR_arch_prctl, code, val);
+}
+void Thread::InitCpu() {
+ static Mutex modify_ldt_lock("modify_ldt lock");
+ MutexLock mu(Thread::Current(), modify_ldt_lock);
+ arch_prctl(ARCH_SET_GS, this);
+
+ // Allow easy indirection back to Thread*.
+ self_ = this;
+
+ // Sanity check that reads from %gs point to this Thread*.
+ Thread* self_check;
+ CHECK_EQ(THREAD_SELF_OFFSET, OFFSETOF_MEMBER(Thread, self_));
+ __asm__ __volatile__("movq %%gs:(%1), %0"
+ : "=r"(self_check) // output
+ : "r"(THREAD_SELF_OFFSET) // input
+ :); // clobber
+ CHECK_EQ(self_check, this);
+
+ // Sanity check other offsets.
+ CHECK_EQ(THREAD_EXCEPTION_OFFSET, OFFSETOF_MEMBER(Thread, exception_));
+ CHECK_EQ(THREAD_CARD_TABLE_OFFSET, OFFSETOF_MEMBER(Thread, card_table_));
+ CHECK_EQ(THREAD_ID_OFFSET, OFFSETOF_MEMBER(Thread, thin_lock_thread_id_));
+}
+
+void Thread::CleanupCpu() {
+ // Sanity check that reads from %gs point to this Thread*.
+ Thread* self_check;
+ CHECK_EQ(THREAD_SELF_OFFSET, OFFSETOF_MEMBER(Thread, self_));
+ __asm__ __volatile__("movq %%gs:(%1), %0"
+ : "=r"(self_check) // output
+ : "r"(THREAD_SELF_OFFSET) // input
+ :); // clobber
+ CHECK_EQ(self_check, this);
+
+ // Do nothing.
+}
+
+} // namespace art
diff --git a/runtime/asm_support.h b/runtime/asm_support.h
index 06c7b53..4c42099 100644
--- a/runtime/asm_support.h
+++ b/runtime/asm_support.h
@@ -40,6 +40,7 @@
// Offsets within java.lang.Method.
#define METHOD_DEX_CACHE_METHODS_OFFSET 12
-#define METHOD_CODE_OFFSET 36
+#define METHOD_PORTABLE_CODE_OFFSET 40
+#define METHOD_QUICK_CODE_OFFSET 48
#endif // ART_RUNTIME_ASM_SUPPORT_H_
diff --git a/runtime/atomic.cc b/runtime/atomic.cc
index bac0a99..63f2cf8 100644
--- a/runtime/atomic.cc
+++ b/runtime/atomic.cc
@@ -24,7 +24,7 @@ namespace art {
std::vector<Mutex*>* QuasiAtomic::gSwapMutexes = nullptr;
Mutex* QuasiAtomic::GetSwapMutex(const volatile int64_t* addr) {
- return (*gSwapMutexes)[(reinterpret_cast<unsigned>(addr) >> 3U) % kSwapMutexCount];
+ return (*gSwapMutexes)[(reinterpret_cast<uintptr_t>(addr) >> 3U) % kSwapMutexCount];
}
void QuasiAtomic::Startup() {
diff --git a/runtime/atomic.h b/runtime/atomic.h
index b1e9870..2a47e46 100644
--- a/runtime/atomic.h
+++ b/runtime/atomic.h
@@ -26,6 +26,69 @@ namespace art {
class Mutex;
+template<typename T>
+class Atomic {
+ public:
+ Atomic<T>() : value_(0) { }
+
+ explicit Atomic<T>(T value) : value_(value) { }
+
+ Atomic<T>& operator=(T desired) {
+ Store(desired);
+ return *this;
+ }
+
+ T Load() const {
+ return value_;
+ }
+
+ operator T() const {
+ return Load();
+ }
+
+ T FetchAndAdd(const T value) {
+ return __sync_fetch_and_add(&value_, value); // Return old_value.
+ }
+
+ T FetchAndSub(const T value) {
+ return __sync_fetch_and_sub(&value_, value); // Return old value.
+ }
+
+ T operator++() { // Prefix operator.
+ return __sync_add_and_fetch(&value_, 1); // Return new value.
+ }
+
+ T operator++(int) { // Postfix operator.
+ return __sync_fetch_and_add(&value_, 1); // Return old value.
+ }
+
+ T operator--() { // Prefix operator.
+ return __sync_sub_and_fetch(&value_, 1); // Return new value.
+ }
+
+ T operator--(int) { // Postfix operator.
+ return __sync_fetch_and_sub(&value_, 1); // Return old value.
+ }
+
+ bool CompareAndSwap(T expected_value, T desired_value) {
+ return __sync_bool_compare_and_swap(&value_, expected_value, desired_value);
+ }
+
+ volatile T* Address() {
+ return &value_;
+ }
+
+ private:
+ // Unsafe = operator for non atomic operations on the integer.
+ void Store(T desired) {
+ value_ = desired;
+ }
+
+ volatile T value_;
+};
+
+typedef Atomic<int32_t> AtomicInteger;
+
// NOTE: Two "quasiatomic" operations on the exact same memory address
// are guaranteed to operate atomically with respect to each other,
// but no guarantees are made about quasiatomic operations mixed with
@@ -80,7 +143,7 @@ class QuasiAtomic {
static void MembarLoadStore() {
#if defined(__arm__)
__asm__ __volatile__("dmb ish" : : : "memory");
- #elif defined(__i386__)
+ #elif defined(__i386__) || defined(__x86_64__)
__asm__ __volatile__("" : : : "memory");
#elif defined(__mips__)
__asm__ __volatile__("sync" : : : "memory");
@@ -92,7 +155,7 @@ class QuasiAtomic {
static void MembarLoadLoad() {
#if defined(__arm__)
__asm__ __volatile__("dmb ish" : : : "memory");
- #elif defined(__i386__)
+ #elif defined(__i386__) || defined(__x86_64__)
__asm__ __volatile__("" : : : "memory");
#elif defined(__mips__)
__asm__ __volatile__("sync" : : : "memory");
@@ -104,7 +167,7 @@ class QuasiAtomic {
static void MembarStoreStore() {
#if defined(__arm__)
__asm__ __volatile__("dmb ishst" : : : "memory");
- #elif defined(__i386__)
+ #elif defined(__i386__) || defined(__x86_64__)
__asm__ __volatile__("" : : : "memory");
#elif defined(__mips__)
__asm__ __volatile__("sync" : : : "memory");
@@ -116,7 +179,7 @@ class QuasiAtomic {
static void MembarStoreLoad() {
#if defined(__arm__)
__asm__ __volatile__("dmb ish" : : : "memory");
- #elif defined(__i386__)
+ #elif defined(__i386__) || defined(__x86_64__)
__asm__ __volatile__("mfence" : : : "memory");
#elif defined(__mips__)
__asm__ __volatile__("sync" : : : "memory");
diff --git a/runtime/atomic_integer.h b/runtime/atomic_integer.h
deleted file mode 100644
index 651ca4a..0000000
--- a/runtime/atomic_integer.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef ART_RUNTIME_ATOMIC_INTEGER_H_
-#define ART_RUNTIME_ATOMIC_INTEGER_H_
-
-#include <stdint.h>
-
-namespace art {
-
-class AtomicInteger {
- public:
- AtomicInteger() : value_(0) { }
-
- explicit AtomicInteger(int32_t value) : value_(value) { }
-
- AtomicInteger& operator=(int32_t desired) {
- Store(desired);
- return *this;
- }
-
- int32_t Load() const {
- return value_;
- }
-
- operator int32_t() const {
- return Load();
- }
-
- int32_t FetchAndAdd(const int32_t value) {
- return __sync_fetch_and_add(&value_, value); // Return old_value.
- }
-
- int32_t FetchAndSub(const int32_t value) {
- return __sync_fetch_and_sub(&value_, value); // Return old value.
- }
-
- int32_t operator++() { // Prefix operator.
- return __sync_add_and_fetch(&value_, 1); // Return new value.
- }
-
- int32_t operator++(int32_t) { // Postfix operator.
- return __sync_fetch_and_add(&value_, 1); // Return old value.
- }
-
- int32_t operator--() { // Prefix operator.
- return __sync_sub_and_fetch(&value_, 1); // Return new value.
- }
-
- int32_t operator--(int32_t) { // Postfix operator.
- return __sync_fetch_and_sub(&value_, 1); // Return old value.
- }
-
- bool CompareAndSwap(int32_t expected_value, int32_t desired_value) {
- return __sync_bool_compare_and_swap(&value_, expected_value, desired_value);
- }
-
- volatile int32_t* Address() {
- return &value_;
- }
-
- private:
- // Unsafe = operator for non atomic operations on the integer.
- void Store(int32_t desired) {
- value_ = desired;
- }
-
- volatile int32_t value_;
-};
-
-} // namespace art
-
-#endif // ART_RUNTIME_ATOMIC_INTEGER_H_
diff --git a/runtime/barrier_test.cc b/runtime/barrier_test.cc
index 91fc143..69951c5 100644
--- a/runtime/barrier_test.cc
+++ b/runtime/barrier_test.cc
@@ -18,7 +18,7 @@
#include <string>
-#include "atomic_integer.h"
+#include "atomic.h"
#include "common_test.h"
#include "mirror/object_array-inl.h"
#include "thread_pool.h"
diff --git a/runtime/base/bit_vector_test.cc b/runtime/base/bit_vector_test.cc
index d99d059..3fc9b86 100644
--- a/runtime/base/bit_vector_test.cc
+++ b/runtime/base/bit_vector_test.cc
@@ -25,7 +25,7 @@ TEST(BitVector, Test) {
BitVector bv(kBits, false, Allocator::GetMallocAllocator());
EXPECT_EQ(1U, bv.GetStorageSize());
- EXPECT_EQ(kWordSize, bv.GetSizeOf());
+ EXPECT_EQ(sizeof(uint32_t), bv.GetSizeOf());
EXPECT_FALSE(bv.IsExpandable());
EXPECT_EQ(0U, bv.NumSetBits());
@@ -70,7 +70,7 @@ TEST(BitVector, NoopAllocator) {
BitVector bv(0U, false, Allocator::GetNoopAllocator(), kWords, bits);
EXPECT_EQ(kWords, bv.GetStorageSize());
- EXPECT_EQ(kWords * kWordSize, bv.GetSizeOf());
+ EXPECT_EQ(kWords * sizeof(uint32_t), bv.GetSizeOf());
EXPECT_EQ(bits, bv.GetRawStorage());
EXPECT_EQ(0U, bv.NumSetBits());
diff --git a/runtime/base/mutex.cc b/runtime/base/mutex.cc
index 05e3a83..ff72d16 100644
--- a/runtime/base/mutex.cc
+++ b/runtime/base/mutex.cc
@@ -47,7 +47,7 @@ static bool ComputeRelativeTimeSpec(timespec* result_ts, const timespec& lhs, co
struct AllMutexData {
// A guard for all_mutexes_ that's not a mutex (Mutexes must CAS to acquire and busy wait).
- AtomicInteger all_mutexes_guard;
+ Atomic<const BaseMutex*> all_mutexes_guard;
// All created mutexes guarded by all_mutexes_guard_.
std::set<BaseMutex*>* all_mutexes;
AllMutexData() : all_mutexes(NULL) {}
@@ -57,12 +57,12 @@ static struct AllMutexData gAllMutexData[kAllMutexDataSize];
class ScopedAllMutexesLock {
public:
explicit ScopedAllMutexesLock(const BaseMutex* mutex) : mutex_(mutex) {
- while (!gAllMutexData->all_mutexes_guard.CompareAndSwap(0, reinterpret_cast<int32_t>(mutex))) {
+ while (!gAllMutexData->all_mutexes_guard.CompareAndSwap(0, mutex)) {
NanoSleep(100);
}
}
~ScopedAllMutexesLock() {
- while (!gAllMutexData->all_mutexes_guard.CompareAndSwap(reinterpret_cast<int32_t>(mutex_), 0)) {
+ while (!gAllMutexData->all_mutexes_guard.CompareAndSwap(mutex_, 0)) {
NanoSleep(100);
}
}
diff --git a/runtime/base/mutex.h b/runtime/base/mutex.h
index 1c1dcaf..63ed6cb 100644
--- a/runtime/base/mutex.h
+++ b/runtime/base/mutex.h
@@ -23,7 +23,7 @@
#include <iosfwd>
#include <string>
-#include "atomic_integer.h"
+#include "atomic.h"
#include "base/logging.h"
#include "base/macros.h"
#include "globals.h"
diff --git a/runtime/base/unix_file/fd_file.cc b/runtime/base/unix_file/fd_file.cc
index f48c76d..87d1c06 100644
--- a/runtime/base/unix_file/fd_file.cc
+++ b/runtime/base/unix_file/fd_file.cc
@@ -102,11 +102,11 @@ bool FdFile::IsOpened() const {
return fd_ >= 0;
}
-bool FdFile::ReadFully(void* buffer, int64_t byte_count) {
+bool FdFile::ReadFully(void* buffer, size_t byte_count) {
char* ptr = static_cast<char*>(buffer);
while (byte_count > 0) {
- int bytes_read = TEMP_FAILURE_RETRY(read(fd_, ptr, byte_count));
- if (bytes_read <= 0) {
+ ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd_, ptr, byte_count));
+ if (bytes_read == -1) {
return false;
}
byte_count -= bytes_read; // Reduce the number of remaining bytes.
@@ -115,15 +115,15 @@ bool FdFile::ReadFully(void* buffer, int64_t byte_count) {
return true;
}
-bool FdFile::WriteFully(const void* buffer, int64_t byte_count) {
+bool FdFile::WriteFully(const void* buffer, size_t byte_count) {
const char* ptr = static_cast<const char*>(buffer);
while (byte_count > 0) {
- int bytes_read = TEMP_FAILURE_RETRY(write(fd_, ptr, byte_count));
- if (bytes_read < 0) {
+ ssize_t bytes_written = TEMP_FAILURE_RETRY(write(fd_, ptr, byte_count));
+ if (bytes_written == -1) {
return false;
}
- byte_count -= bytes_read; // Reduce the number of remaining bytes.
- ptr += bytes_read; // Move the buffer forward.
+ byte_count -= bytes_written; // Reduce the number of remaining bytes.
+ ptr += bytes_written; // Move the buffer forward.
}
return true;
}
diff --git a/runtime/base/unix_file/fd_file.h b/runtime/base/unix_file/fd_file.h
index 19e3511..01f4ca2 100644
--- a/runtime/base/unix_file/fd_file.h
+++ b/runtime/base/unix_file/fd_file.h
@@ -61,8 +61,8 @@ class FdFile : public RandomAccessFile {
return file_path_;
}
void DisableAutoClose();
- bool ReadFully(void* buffer, int64_t byte_count);
- bool WriteFully(const void* buffer, int64_t byte_count);
+ bool ReadFully(void* buffer, size_t byte_count);
+ bool WriteFully(const void* buffer, size_t byte_count);
private:
int fd_;
diff --git a/runtime/base/unix_file/mapped_file.cc b/runtime/base/unix_file/mapped_file.cc
index b63fdd3..bc23a74 100644
--- a/runtime/base/unix_file/mapped_file.cc
+++ b/runtime/base/unix_file/mapped_file.cc
@@ -101,7 +101,8 @@ int64_t MappedFile::Read(char* buf, int64_t byte_count, int64_t offset) const {
errno = EINVAL;
return -errno;
}
- int64_t read_size = std::max(0LL, std::min(byte_count, file_size_ - offset));
+ int64_t read_size = std::max(static_cast<int64_t>(0),
+ std::min(byte_count, file_size_ - offset));
if (read_size > 0) {
memcpy(buf, data() + offset, read_size);
}
@@ -136,7 +137,8 @@ int64_t MappedFile::Write(const char* buf, int64_t byte_count, int64_t offset) {
errno = EINVAL;
return -errno;
}
- int64_t write_size = std::max(0LL, std::min(byte_count, file_size_ - offset));
+ int64_t write_size = std::max(static_cast<int64_t>(0),
+ std::min(byte_count, file_size_ - offset));
if (write_size > 0) {
memcpy(data() + offset, buf, write_size);
}
diff --git a/runtime/base/unix_file/mapped_file_test.cc b/runtime/base/unix_file/mapped_file_test.cc
index 3dda02f..49750f4 100644
--- a/runtime/base/unix_file/mapped_file_test.cc
+++ b/runtime/base/unix_file/mapped_file_test.cc
@@ -65,7 +65,7 @@ TEST_F(MappedFileTest, OpenClose) {
ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadOnlyMode));
EXPECT_GE(file.Fd(), 0);
EXPECT_TRUE(file.IsOpened());
- EXPECT_EQ(kContent.size(), file.size());
+ EXPECT_EQ(kContent.size(), static_cast<uint64_t>(file.size()));
EXPECT_EQ(0, file.Close());
EXPECT_EQ(-1, file.Fd());
EXPECT_FALSE(file.IsOpened());
@@ -86,7 +86,7 @@ TEST_F(MappedFileTest, CanUseAfterMapReadOnly) {
EXPECT_FALSE(file.IsMapped());
EXPECT_TRUE(file.MapReadOnly());
EXPECT_TRUE(file.IsMapped());
- EXPECT_EQ(kContent.size(), file.size());
+ EXPECT_EQ(kContent.size(), static_cast<uint64_t>(file.size()));
ASSERT_TRUE(file.data());
EXPECT_EQ(0, memcmp(kContent.c_str(), file.data(), file.size()));
EXPECT_EQ(0, file.Flush());
@@ -113,7 +113,7 @@ TEST_F(MappedFileTest, CanWriteNewData) {
ASSERT_TRUE(file.Open(new_path, MappedFile::kReadWriteMode));
EXPECT_TRUE(file.MapReadWrite(kContent.size()));
EXPECT_TRUE(file.IsMapped());
- EXPECT_EQ(kContent.size(), file.size());
+ EXPECT_EQ(kContent.size(), static_cast<uint64_t>(file.size()));
ASSERT_TRUE(file.data());
memcpy(file.data(), kContent.c_str(), kContent.size());
EXPECT_EQ(0, file.Close());
@@ -200,15 +200,16 @@ TEST_F(MappedFileTest, WriteMappedReadWrite) {
// A zero-length write is a no-op.
EXPECT_EQ(0, file.Write(kContent.c_str(), 0, 0));
// But the file size is as given when mapped.
- EXPECT_EQ(kContent.size(), file.GetLength());
+ EXPECT_EQ(kContent.size(), static_cast<uint64_t>(file.GetLength()));
// Data written past the end are discarded.
EXPECT_EQ(kContent.size() - 1,
- file.Write(kContent.c_str(), kContent.size(), 1));
+ static_cast<uint64_t>(file.Write(kContent.c_str(), kContent.size(), 1)));
EXPECT_EQ(0, memcmp(kContent.c_str(), file.data() + 1, kContent.size() - 1));
// Data can be overwritten.
- EXPECT_EQ(kContent.size(), file.Write(kContent.c_str(), kContent.size(), 0));
+ EXPECT_EQ(kContent.size(),
+ static_cast<uint64_t>(file.Write(kContent.c_str(), kContent.size(), 0)));
EXPECT_EQ(0, memcmp(kContent.c_str(), file.data(), kContent.size()));
}
diff --git a/runtime/base/unix_file/null_file_test.cc b/runtime/base/unix_file/null_file_test.cc
index 0f20acd..410fdfc 100644
--- a/runtime/base/unix_file/null_file_test.cc
+++ b/runtime/base/unix_file/null_file_test.cc
@@ -48,7 +48,7 @@ TEST_F(NullFileTest, GetLength) {
NullFile f;
// The length is always 0.
ASSERT_EQ(0, f.GetLength());
- ASSERT_EQ(content.size(), f.Write(content.data(), content.size(), 0));
+ ASSERT_EQ(content.size(), static_cast<uint64_t>(f.Write(content.data(), content.size(), 0)));
ASSERT_EQ(0, f.GetLength());
}
@@ -58,8 +58,8 @@ TEST_F(NullFileTest, Write) {
// You can't write at a negative offset...
ASSERT_EQ(-EINVAL, f.Write(content.data(), content.size(), -128));
// But you can write anywhere else...
- ASSERT_EQ(content.size(), f.Write(content.data(), content.size(), 0));
- ASSERT_EQ(content.size(), f.Write(content.data(), content.size(), 128));
+ ASSERT_EQ(content.size(), static_cast<uint64_t>(f.Write(content.data(), content.size(), 0)));
+ ASSERT_EQ(content.size(), static_cast<uint64_t>(f.Write(content.data(), content.size(), 128)));
// ...though the file will remain empty.
ASSERT_EQ(0, f.GetLength());
}
diff --git a/runtime/base/unix_file/random_access_file_test.h b/runtime/base/unix_file/random_access_file_test.h
index 9d8550d..3152788 100644
--- a/runtime/base/unix_file/random_access_file_test.h
+++ b/runtime/base/unix_file/random_access_file_test.h
@@ -71,7 +71,7 @@ class RandomAccessFileTest : public testing::Test {
ASSERT_EQ(0, file->Read(buf, 123, 0));
const std::string content("hello");
- ASSERT_EQ(content.size(), file->Write(content.data(), content.size(), 0));
+ ASSERT_EQ(content.size(), static_cast<uint64_t>(file->Write(content.data(), content.size(), 0)));
TestReadContent(content, file.get());
}
@@ -83,21 +83,21 @@ class RandomAccessFileTest : public testing::Test {
ASSERT_EQ(-EINVAL, file->Read(buf.get(), 0, -123));
// Reading too much gets us just what's in the file.
- ASSERT_EQ(content.size(), file->Read(buf.get(), buf_size, 0));
+ ASSERT_EQ(content.size(), static_cast<uint64_t>(file->Read(buf.get(), buf_size, 0)));
ASSERT_EQ(std::string(buf.get(), content.size()), content);
// We only get as much as we ask for.
const size_t short_request = 2;
ASSERT_LT(short_request, content.size());
- ASSERT_EQ(short_request, file->Read(buf.get(), short_request, 0));
+ ASSERT_EQ(short_request, static_cast<uint64_t>(file->Read(buf.get(), short_request, 0)));
ASSERT_EQ(std::string(buf.get(), short_request),
content.substr(0, short_request));
// We don't have to start at the beginning.
const int non_zero_offset = 2;
ASSERT_GT(non_zero_offset, 0);
- ASSERT_EQ(short_request,
- file->Read(buf.get(), short_request, non_zero_offset));
+ ASSERT_EQ(short_request, static_cast<uint64_t>(file->Read(buf.get(), short_request,
+ non_zero_offset)));
ASSERT_EQ(std::string(buf.get(), short_request),
content.substr(non_zero_offset, short_request));
@@ -109,8 +109,8 @@ class RandomAccessFileTest : public testing::Test {
void TestSetLength() {
const std::string content("hello");
UniquePtr<RandomAccessFile> file(MakeTestFile());
- ASSERT_EQ(content.size(), file->Write(content.data(), content.size(), 0));
- ASSERT_EQ(content.size(), file->GetLength());
+ ASSERT_EQ(content.size(), static_cast<uint64_t>(file->Write(content.data(), content.size(), 0)));
+ ASSERT_EQ(content.size(), static_cast<uint64_t>(file->GetLength()));
// Can't give a file a negative length.
ASSERT_EQ(-EINVAL, file->SetLength(-123));
@@ -143,20 +143,20 @@ class RandomAccessFileTest : public testing::Test {
ASSERT_EQ(0, file->GetLength());
// We can write data.
- ASSERT_EQ(content.size(), file->Write(content.data(), content.size(), 0));
- ASSERT_EQ(content.size(), file->GetLength());
+ ASSERT_EQ(content.size(), static_cast<uint64_t>(file->Write(content.data(), content.size(), 0)));
+ ASSERT_EQ(content.size(), static_cast<uint64_t>(file->GetLength()));
std::string new_content;
ASSERT_TRUE(ReadString(file.get(), &new_content));
ASSERT_EQ(new_content, content);
// We can read it back.
char buf[256];
- ASSERT_EQ(content.size(), file->Read(buf, sizeof(buf), 0));
+ ASSERT_EQ(content.size(), static_cast<uint64_t>(file->Read(buf, sizeof(buf), 0)));
ASSERT_EQ(std::string(buf, content.size()), content);
// We can append data past the end.
- ASSERT_EQ(content.size(),
- file->Write(content.data(), content.size(), file->GetLength() + 1));
+ ASSERT_EQ(content.size(), static_cast<uint64_t>(file->Write(content.data(), content.size(),
+ file->GetLength() + 1)));
int64_t new_length = 2*content.size() + 1;
ASSERT_EQ(file->GetLength(), new_length);
ASSERT_TRUE(ReadString(file.get(), &new_content));
diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc
index 1b79ee0..960c26d 100644
--- a/runtime/check_jni.cc
+++ b/runtime/check_jni.cc
@@ -40,23 +40,23 @@ namespace art {
static void JniAbort(const char* jni_function_name, const char* msg) {
Thread* self = Thread::Current();
ScopedObjectAccess soa(self);
- mirror::ArtMethod* current_method = self->GetCurrentMethod(NULL);
+ mirror::ArtMethod* current_method = self->GetCurrentMethod(nullptr);
std::ostringstream os;
os << "JNI DETECTED ERROR IN APPLICATION: " << msg;
- if (jni_function_name != NULL) {
+ if (jni_function_name != nullptr) {
os << "\n in call to " << jni_function_name;
}
// TODO: is this useful given that we're about to dump the calling thread's stack?
- if (current_method != NULL) {
+ if (current_method != nullptr) {
os << "\n from " << PrettyMethod(current_method);
}
os << "\n";
self->Dump(os);
JavaVMExt* vm = Runtime::Current()->GetJavaVM();
- if (vm->check_jni_abort_hook != NULL) {
+ if (vm->check_jni_abort_hook != nullptr) {
vm->check_jni_abort_hook(vm->check_jni_abort_hook_data, os.str());
} else {
// Ensure that we get a native stack trace for this thread.
@@ -118,10 +118,10 @@ static const char* gBuiltInPrefixes[] = {
"Ljavax/",
"Llibcore/",
"Lorg/apache/harmony/",
- NULL
+ nullptr
};
-static bool ShouldTrace(JavaVMExt* vm, const mirror::ArtMethod* method)
+static bool ShouldTrace(JavaVMExt* vm, mirror::ArtMethod* method)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// If both "-Xcheck:jni" and "-Xjnitrace:" are enabled, we print trace messages
// when a native method that matches the -Xjnitrace argument calls a JNI function
@@ -135,7 +135,7 @@ static bool ShouldTrace(JavaVMExt* vm, const mirror::ArtMethod* method)
if (VLOG_IS_ON(third_party_jni)) {
// Return true if we're trying to log all third-party JNI activity and 'method' doesn't look
// like part of Android.
- for (size_t i = 0; gBuiltInPrefixes[i] != NULL; ++i) {
+ for (size_t i = 0; gBuiltInPrefixes[i] != nullptr; ++i) {
if (StartsWith(class_name, gBuiltInPrefixes[i])) {
return false;
}
@@ -192,15 +192,16 @@ class ScopedCheck {
*
* Works for both static and instance fields.
*/
- void CheckFieldType(jobject java_object, jfieldID fid, char prim, bool isStatic)
+ void CheckFieldType(jvalue value, jfieldID fid, char prim, bool isStatic)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* f = CheckFieldID(fid);
- if (f == NULL) {
+ if (f == nullptr) {
return;
}
mirror::Class* field_type = FieldHelper(f).GetType();
if (!field_type->IsPrimitive()) {
- if (java_object != NULL) {
+ jobject java_object = value.l;
+ if (java_object != nullptr) {
mirror::Object* obj = soa_.Decode<mirror::Object*>(java_object);
// If java_object is a weak global ref whose referent has been cleared,
// obj will be NULL. Otherwise, obj should always be non-NULL
@@ -242,7 +243,7 @@ class ScopedCheck {
void CheckInstanceFieldID(jobject java_object, jfieldID fid)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::Object* o = soa_.Decode<mirror::Object*>(java_object);
- if (o == NULL || !Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) {
+ if (o == nullptr || !Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) {
Runtime::Current()->GetHeap()->DumpSpaces();
JniAbortF(function_name_, "field operation on invalid %s: %p",
ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
@@ -250,12 +251,12 @@ class ScopedCheck {
}
mirror::ArtField* f = CheckFieldID(fid);
- if (f == NULL) {
+ if (f == nullptr) {
return;
}
mirror::Class* c = o->GetClass();
FieldHelper fh(f);
- if (c->FindInstanceField(fh.GetName(), fh.GetTypeDescriptor()) == NULL) {
+ if (c->FindInstanceField(fh.GetName(), fh.GetTypeDescriptor()) == nullptr) {
JniAbortF(function_name_, "jfieldID %s not valid for an object of class %s",
PrettyField(f).c_str(), PrettyTypeOf(o).c_str());
}
@@ -265,7 +266,7 @@ class ScopedCheck {
* Verify that the pointer value is non-NULL.
*/
void CheckNonNull(const void* ptr) {
- if (ptr == NULL) {
+ if (ptr == nullptr) {
JniAbortF(function_name_, "non-nullable argument was NULL");
}
}
@@ -277,7 +278,7 @@ class ScopedCheck {
void CheckSig(jmethodID mid, const char* expectedType, bool isStatic)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtMethod* m = CheckMethodID(mid);
- if (m == NULL) {
+ if (m == nullptr) {
return;
}
if (*expectedType != MethodHelper(m).GetShorty()[0]) {
@@ -303,8 +304,8 @@ class ScopedCheck {
void CheckStaticFieldID(jclass java_class, jfieldID fid)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::Class* c = soa_.Decode<mirror::Class*>(java_class);
- const mirror::ArtField* f = CheckFieldID(fid);
- if (f == NULL) {
+ mirror::ArtField* f = CheckFieldID(fid);
+ if (f == nullptr) {
return;
}
if (f->GetDeclaringClass() != c) {
@@ -324,8 +325,8 @@ class ScopedCheck {
*/
void CheckStaticMethod(jclass java_class, jmethodID mid)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- const mirror::ArtMethod* m = CheckMethodID(mid);
- if (m == NULL) {
+ mirror::ArtMethod* m = CheckMethodID(mid);
+ if (m == nullptr) {
return;
}
mirror::Class* c = soa_.Decode<mirror::Class*>(java_class);
@@ -344,8 +345,8 @@ class ScopedCheck {
*/
void CheckVirtualMethod(jobject java_object, jmethodID mid)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- const mirror::ArtMethod* m = CheckMethodID(mid);
- if (m == NULL) {
+ mirror::ArtMethod* m = CheckMethodID(mid);
+ if (m == nullptr) {
return;
}
mirror::Object* o = soa_.Decode<mirror::Object*>(java_object);
@@ -394,17 +395,18 @@ class ScopedCheck {
void Check(bool entry, const char* fmt0, ...) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
va_list ap;
- const mirror::ArtMethod* traceMethod = NULL;
+ mirror::ArtMethod* traceMethod = nullptr;
if (has_method_ && (!soa_.Vm()->trace.empty() || VLOG_IS_ON(third_party_jni))) {
// We need to guard some of the invocation interface's calls: a bad caller might
// use DetachCurrentThread or GetEnv on a thread that's not yet attached.
Thread* self = Thread::Current();
- if ((flags_ & kFlag_Invocation) == 0 || self != NULL) {
- traceMethod = self->GetCurrentMethod(NULL);
+ if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
+ traceMethod = self->GetCurrentMethod(nullptr);
}
}
- if (((flags_ & kFlag_ForceTrace) != 0) || (traceMethod != NULL && ShouldTrace(soa_.Vm(), traceMethod))) {
+ if (((flags_ & kFlag_ForceTrace) != 0) ||
+ (traceMethod != nullptr && ShouldTrace(soa_.Vm(), traceMethod))) {
va_start(ap, fmt0);
std::string msg;
for (const char* fmt = fmt0; *fmt;) {
@@ -428,7 +430,7 @@ class ScopedCheck {
} else if (ch == 'I' || ch == 'S') { // jint, jshort
StringAppendF(&msg, "%d", va_arg(ap, int));
} else if (ch == 'J') { // jlong
- StringAppendF(&msg, "%lld", va_arg(ap, jlong));
+ StringAppendF(&msg, "%" PRId64, va_arg(ap, jlong));
} else if (ch == 'Z') { // jboolean
StringAppendF(&msg, "%s", va_arg(ap, int) ? "true" : "false");
} else if (ch == 'V') { // void
@@ -442,7 +444,7 @@ class ScopedCheck {
} else if (ch == 'L' || ch == 'a' || ch == 's') { // jobject, jarray, jstring
// For logging purposes, these are identical.
jobject o = va_arg(ap, jobject);
- if (o == NULL) {
+ if (o == nullptr) {
msg += "NULL";
} else {
StringAppendF(&msg, "%p", o);
@@ -453,7 +455,7 @@ class ScopedCheck {
} else if (ch == 'c') { // jclass
jclass jc = va_arg(ap, jclass);
mirror::Class* c = reinterpret_cast<mirror::Class*>(Thread::Current()->DecodeJObject(jc));
- if (c == NULL) {
+ if (c == nullptr) {
msg += "NULL";
} else if (c == kInvalidIndirectRefObject ||
!Runtime::Current()->GetHeap()->IsValidObjectAddress(c)) {
@@ -488,7 +490,7 @@ class ScopedCheck {
}
} else if (ch == 'p') { // void* ("pointer")
void* p = va_arg(ap, void*);
- if (p == NULL) {
+ if (p == nullptr) {
msg += "NULL";
} else {
StringAppendF(&msg, "(void*) %p", p);
@@ -506,7 +508,7 @@ class ScopedCheck {
}
} else if (ch == 'u') { // const char* (Modified UTF-8)
const char* utf = va_arg(ap, const char*);
- if (utf == NULL) {
+ if (utf == nullptr) {
msg += "NULL";
} else {
StringAppendF(&msg, "\"%s\"", utf);
@@ -563,7 +565,7 @@ class ScopedCheck {
}
} else if (ch == 'z') {
CheckLengthPositive(va_arg(ap, jsize));
- } else if (strchr("BCISZbfmpEv", ch) != NULL) {
+ } else if (strchr("BCISZbfmpEv", ch) != nullptr) {
va_arg(ap, uint32_t); // Skip this argument.
} else if (ch == 'D' || ch == 'F') {
va_arg(ap, double); // Skip this argument.
@@ -595,7 +597,7 @@ class ScopedCheck {
*/
bool CheckInstance(InstanceKind kind, jobject java_object)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- const char* what = NULL;
+ const char* what = nullptr;
switch (kind) {
case kClass:
what = "jclass";
@@ -616,7 +618,7 @@ class ScopedCheck {
LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
}
- if (java_object == NULL) {
+ if (java_object == nullptr) {
JniAbortF(function_name_, "%s received null %s", function_name_, what);
return false;
}
@@ -670,7 +672,7 @@ class ScopedCheck {
* Since we're dealing with objects, switch to "running" mode.
*/
void CheckArray(jarray java_array) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (java_array == NULL) {
+ if (java_array == nullptr) {
JniAbortF(function_name_, "jarray was NULL");
return;
}
@@ -692,29 +694,29 @@ class ScopedCheck {
}
mirror::ArtField* CheckFieldID(jfieldID fid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (fid == NULL) {
+ if (fid == nullptr) {
JniAbortF(function_name_, "jfieldID was NULL");
- return NULL;
+ return nullptr;
}
mirror::ArtField* f = soa_.DecodeField(fid);
if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f) || !f->IsArtField()) {
Runtime::Current()->GetHeap()->DumpSpaces();
JniAbortF(function_name_, "invalid jfieldID: %p", fid);
- return NULL;
+ return nullptr;
}
return f;
}
mirror::ArtMethod* CheckMethodID(jmethodID mid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (mid == NULL) {
+ if (mid == nullptr) {
JniAbortF(function_name_, "jmethodID was NULL");
- return NULL;
+ return nullptr;
}
mirror::ArtMethod* m = soa_.DecodeMethod(mid);
if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m) || !m->IsArtMethod()) {
Runtime::Current()->GetHeap()->DumpSpaces();
JniAbortF(function_name_, "invalid jmethodID: %p", mid);
- return NULL;
+ return nullptr;
}
return m;
}
@@ -727,7 +729,7 @@ class ScopedCheck {
*/
void CheckObject(jobject java_object)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (java_object == NULL) {
+ if (java_object == nullptr) {
return;
}
@@ -752,7 +754,7 @@ class ScopedCheck {
void CheckThread(int flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Thread* self = Thread::Current();
- if (self == NULL) {
+ if (self == nullptr) {
JniAbortF(function_name_, "a thread (tid %d) is making JNI calls without being attached", GetTid());
return;
}
@@ -813,7 +815,7 @@ class ScopedCheck {
// Verifies that "bytes" points to valid Modified UTF-8 data.
void CheckUtfString(const char* bytes, bool nullable) {
- if (bytes == NULL) {
+ if (bytes == nullptr) {
if (!nullable) {
JniAbortF(function_name_, "non-nullable const char* was NULL");
return;
@@ -821,9 +823,9 @@ class ScopedCheck {
return;
}
- const char* errorKind = NULL;
+ const char* errorKind = nullptr;
uint8_t utf8 = CheckUtfBytes(bytes, &errorKind);
- if (errorKind != NULL) {
+ if (errorKind != nullptr) {
JniAbortF(function_name_,
"input is not valid Modified UTF-8: illegal %s byte %#x\n"
" string: '%s'", errorKind, utf8, bytes);
@@ -998,7 +1000,7 @@ struct GuardedCopy {
const uint16_t* pat = reinterpret_cast<const uint16_t*>(fullBuf);
for (size_t i = sizeof(GuardedCopy) / 2; i < (kGuardLen / 2 - sizeof(GuardedCopy)) / 2; i++) {
if (pat[i] != kGuardPattern) {
- JniAbortF(functionName, "guard pattern(1) disturbed at %p +%d", fullBuf, i*2);
+ JniAbortF(functionName, "guard pattern(1) disturbed at %p +%zd", fullBuf, i*2);
}
}
@@ -1018,7 +1020,7 @@ struct GuardedCopy {
pat = reinterpret_cast<const uint16_t*>(fullBuf + offset);
for (size_t i = 0; i < kGuardLen / 4; i++) {
if (pat[i] != kGuardPattern) {
- JniAbortF(functionName, "guard pattern(2) disturbed at %p +%d", fullBuf, offset + i*2);
+ JniAbortF(functionName, "guard pattern(2) disturbed at %p +%zd", fullBuf, offset + i*2);
}
}
@@ -1037,7 +1039,7 @@ struct GuardedCopy {
private:
static uint8_t* DebugAlloc(size_t len) {
- void* result = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
+ void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
if (result == MAP_FAILED) {
PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
}
@@ -1081,8 +1083,8 @@ static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean*
mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
size_t component_size = a->GetClass()->GetComponentSize();
size_t byte_count = a->GetLength() * component_size;
- void* result = GuardedCopy::Create(a->GetRawData(component_size), byte_count, true);
- if (isCopy != NULL) {
+ void* result = GuardedCopy::Create(a->GetRawData(component_size, 0), byte_count, true);
+ if (isCopy != nullptr) {
*isCopy = JNI_TRUE;
}
return result;
@@ -1100,7 +1102,7 @@ static void ReleaseGuardedPACopy(JNIEnv* env, jarray java_array, void* dataBuf,
if (mode != JNI_ABORT) {
size_t len = GuardedCopy::FromData(dataBuf)->original_length;
- memcpy(a->GetRawData(a->GetClass()->GetComponentSize()), dataBuf, len);
+ memcpy(a->GetRawData(a->GetClass()->GetComponentSize(), 0), dataBuf, len);
}
if (mode != JNI_COMMIT) {
GuardedCopy::Destroy(dataBuf);
@@ -1223,7 +1225,7 @@ class CheckJNI {
static void DeleteGlobalRef(JNIEnv* env, jobject globalRef) {
CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, globalRef);
- if (globalRef != NULL && GetIndirectRefKind(globalRef) != kGlobal) {
+ if (globalRef != nullptr && GetIndirectRefKind(globalRef) != kGlobal) {
JniAbortF(__FUNCTION__, "DeleteGlobalRef on %s: %p",
ToStr<IndirectRefKind>(GetIndirectRefKind(globalRef)).c_str(), globalRef);
} else {
@@ -1234,7 +1236,7 @@ class CheckJNI {
static void DeleteWeakGlobalRef(JNIEnv* env, jweak weakGlobalRef) {
CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, weakGlobalRef);
- if (weakGlobalRef != NULL && GetIndirectRefKind(weakGlobalRef) != kWeakGlobal) {
+ if (weakGlobalRef != nullptr && GetIndirectRefKind(weakGlobalRef) != kWeakGlobal) {
JniAbortF(__FUNCTION__, "DeleteWeakGlobalRef on %s: %p",
ToStr<IndirectRefKind>(GetIndirectRefKind(weakGlobalRef)).c_str(), weakGlobalRef);
} else {
@@ -1245,7 +1247,7 @@ class CheckJNI {
static void DeleteLocalRef(JNIEnv* env, jobject localRef) {
CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, localRef);
- if (localRef != NULL && GetIndirectRefKind(localRef) != kLocal && !IsSirtLocalRef(env, localRef)) {
+ if (localRef != nullptr && GetIndirectRefKind(localRef) != kLocal && !IsSirtLocalRef(env, localRef)) {
JniAbortF(__FUNCTION__, "DeleteLocalRef on %s: %p",
ToStr<IndirectRefKind>(GetIndirectRefKind(localRef)).c_str(), localRef);
} else {
@@ -1318,7 +1320,7 @@ class CheckJNI {
return CHECK_JNI_EXIT("f", baseEnv(env)->GetStaticFieldID(env, c, name, sig));
}
-#define FIELD_ACCESSORS(_ctype, _jname, _type) \
+#define FIELD_ACCESSORS(_ctype, _jname, _jvalue_type, _type) \
static _ctype GetStatic##_jname##Field(JNIEnv* env, jclass c, jfieldID fid) { \
CHECK_JNI_ENTRY(kFlag_Default, "Ecf", env, c, fid); \
sc.CheckStaticFieldID(c, fid); \
@@ -1333,7 +1335,9 @@ class CheckJNI {
CHECK_JNI_ENTRY(kFlag_Default, "Ecf" _type, env, c, fid, value); \
sc.CheckStaticFieldID(c, fid); \
/* "value" arg only used when type == ref */ \
- sc.CheckFieldType((jobject)(uint32_t)value, fid, _type[0], true); \
+ jvalue java_type_value; \
+ java_type_value._jvalue_type = value; \
+ sc.CheckFieldType(java_type_value, fid, _type[0], true); \
baseEnv(env)->SetStatic##_jname##Field(env, c, fid, value); \
CHECK_JNI_EXIT_VOID(); \
} \
@@ -1341,20 +1345,22 @@ class CheckJNI {
CHECK_JNI_ENTRY(kFlag_Default, "ELf" _type, env, obj, fid, value); \
sc.CheckInstanceFieldID(obj, fid); \
/* "value" arg only used when type == ref */ \
- sc.CheckFieldType((jobject)(uint32_t) value, fid, _type[0], false); \
+ jvalue java_type_value; \
+ java_type_value._jvalue_type = value; \
+ sc.CheckFieldType(java_type_value, fid, _type[0], false); \
baseEnv(env)->Set##_jname##Field(env, obj, fid, value); \
CHECK_JNI_EXIT_VOID(); \
}
-FIELD_ACCESSORS(jobject, Object, "L");
-FIELD_ACCESSORS(jboolean, Boolean, "Z");
-FIELD_ACCESSORS(jbyte, Byte, "B");
-FIELD_ACCESSORS(jchar, Char, "C");
-FIELD_ACCESSORS(jshort, Short, "S");
-FIELD_ACCESSORS(jint, Int, "I");
-FIELD_ACCESSORS(jlong, Long, "J");
-FIELD_ACCESSORS(jfloat, Float, "F");
-FIELD_ACCESSORS(jdouble, Double, "D");
+FIELD_ACCESSORS(jobject, Object, l, "L");
+FIELD_ACCESSORS(jboolean, Boolean, z, "Z");
+FIELD_ACCESSORS(jbyte, Byte, b, "B");
+FIELD_ACCESSORS(jchar, Char, c, "C");
+FIELD_ACCESSORS(jshort, Short, s, "S");
+FIELD_ACCESSORS(jint, Int, i, "I");
+FIELD_ACCESSORS(jlong, Long, j, "J");
+FIELD_ACCESSORS(jfloat, Float, f, "F");
+FIELD_ACCESSORS(jdouble, Double, d, "D");
#define CALL(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig) \
/* Virtual... */ \
@@ -1484,11 +1490,11 @@ CALL(void, Void, , , VOID_RETURN, "V");
static const jchar* GetStringChars(JNIEnv* env, jstring java_string, jboolean* isCopy) {
CHECK_JNI_ENTRY(kFlag_CritOkay, "Esp", env, java_string, isCopy);
const jchar* result = baseEnv(env)->GetStringChars(env, java_string, isCopy);
- if (sc.ForceCopy() && result != NULL) {
+ if (sc.ForceCopy() && result != nullptr) {
mirror::String* s = sc.soa().Decode<mirror::String*>(java_string);
int byteCount = s->GetLength() * 2;
result = (const jchar*) GuardedCopy::Create(result, byteCount, false);
- if (isCopy != NULL) {
+ if (isCopy != nullptr) {
*isCopy = JNI_TRUE;
}
}
@@ -1519,9 +1525,9 @@ CALL(void, Void, , , VOID_RETURN, "V");
static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* isCopy) {
CHECK_JNI_ENTRY(kFlag_CritOkay, "Esp", env, string, isCopy);
const char* result = baseEnv(env)->GetStringUTFChars(env, string, isCopy);
- if (sc.ForceCopy() && result != NULL) {
+ if (sc.ForceCopy() && result != nullptr) {
result = (const char*) GuardedCopy::Create(result, strlen(result) + 1, false);
- if (isCopy != NULL) {
+ if (isCopy != nullptr) {
*isCopy = JNI_TRUE;
}
}
@@ -1578,7 +1584,7 @@ struct ForceCopyGetChecker {
ForceCopyGetChecker(ScopedCheck& sc, jboolean* isCopy) {
force_copy = sc.ForceCopy();
no_copy = 0;
- if (force_copy && isCopy != NULL) {
+ if (force_copy && isCopy != nullptr) {
// Capture this before the base call tramples on it.
no_copy = *reinterpret_cast<uint32_t*>(isCopy);
}
@@ -1586,7 +1592,7 @@ struct ForceCopyGetChecker {
template<typename ResultT>
ResultT Check(JNIEnv* env, jarray array, jboolean* isCopy, ResultT result) {
- if (force_copy && result != NULL) {
+ if (force_copy && result != nullptr) {
result = reinterpret_cast<ResultT>(CreateGuardedPACopy(env, array, isCopy));
}
return result;
@@ -1690,7 +1696,7 @@ PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* isCopy) {
CHECK_JNI_ENTRY(kFlag_CritGet, "Eap", env, array, isCopy);
void* result = baseEnv(env)->GetPrimitiveArrayCritical(env, array, isCopy);
- if (sc.ForceCopy() && result != NULL) {
+ if (sc.ForceCopy() && result != nullptr) {
result = CreateGuardedPACopy(env, array, isCopy);
}
return CHECK_JNI_EXIT("p", result);
@@ -1709,11 +1715,11 @@ PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
static const jchar* GetStringCritical(JNIEnv* env, jstring java_string, jboolean* isCopy) {
CHECK_JNI_ENTRY(kFlag_CritGet, "Esp", env, java_string, isCopy);
const jchar* result = baseEnv(env)->GetStringCritical(env, java_string, isCopy);
- if (sc.ForceCopy() && result != NULL) {
+ if (sc.ForceCopy() && result != nullptr) {
mirror::String* s = sc.soa().Decode<mirror::String*>(java_string);
int byteCount = s->GetLength() * 2;
result = (const jchar*) GuardedCopy::Create(result, byteCount, false);
- if (isCopy != NULL) {
+ if (isCopy != nullptr) {
*isCopy = JNI_TRUE;
}
}
@@ -1751,11 +1757,11 @@ PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
CHECK_JNI_ENTRY(kFlag_Default, "EpJ", env, address, capacity);
- if (address == NULL) {
+ if (address == nullptr) {
JniAbortF(__FUNCTION__, "non-nullable address is NULL");
}
if (capacity < 0) {
- JniAbortF(__FUNCTION__, "capacity must be non-negative: %lld", capacity);
+ JniAbortF(__FUNCTION__, "capacity must be non-negative: %" PRId64, capacity);
}
return CHECK_JNI_EXIT("L", baseEnv(env)->NewDirectByteBuffer(env, address, capacity));
}
@@ -1779,10 +1785,10 @@ PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
};
const JNINativeInterface gCheckNativeInterface = {
- NULL, // reserved0.
- NULL, // reserved1.
- NULL, // reserved2.
- NULL, // reserved3.
+ nullptr, // reserved0.
+ nullptr, // reserved1.
+ nullptr, // reserved2.
+ nullptr, // reserved3.
CheckJNI::GetVersion,
CheckJNI::DefineClass,
CheckJNI::FindClass,
@@ -2057,9 +2063,9 @@ class CheckJII {
};
const JNIInvokeInterface gCheckInvokeInterface = {
- NULL, // reserved0
- NULL, // reserved1
- NULL, // reserved2
+ nullptr, // reserved0
+ nullptr, // reserved1
+ nullptr, // reserved2
CheckJII::DestroyJavaVM,
CheckJII::AttachCurrentThread,
CheckJII::DetachCurrentThread,
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index 0436435..66c24b5 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -28,7 +28,7 @@
namespace art {
inline mirror::String* ClassLinker::ResolveString(uint32_t string_idx,
- const mirror::ArtMethod* referrer) {
+ mirror::ArtMethod* referrer) {
mirror::String* resolved_string = referrer->GetDexCacheStrings()->Get(string_idx);
if (UNLIKELY(resolved_string == NULL)) {
mirror::Class* declaring_class = referrer->GetDeclaringClass();
@@ -40,7 +40,7 @@ inline mirror::String* ClassLinker::ResolveString(uint32_t string_idx,
}
inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx,
- const mirror::ArtMethod* referrer) {
+ mirror::ArtMethod* referrer) {
mirror::Class* resolved_type = referrer->GetDexCacheResolvedTypes()->Get(type_idx);
if (UNLIKELY(resolved_type == NULL)) {
mirror::Class* declaring_class = referrer->GetDeclaringClass();
@@ -53,7 +53,7 @@ inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx,
return resolved_type;
}
-inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx, const mirror::ArtField* referrer) {
+inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx, mirror::ArtField* referrer) {
mirror::Class* declaring_class = referrer->GetDeclaringClass();
mirror::DexCache* dex_cache_ptr = declaring_class->GetDexCache();
mirror::Class* resolved_type = dex_cache_ptr->GetResolvedType(type_idx);
@@ -68,7 +68,7 @@ inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx, const mirror::
}
inline mirror::ArtMethod* ClassLinker::ResolveMethod(uint32_t method_idx,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
InvokeType type) {
mirror::ArtMethod* resolved_method =
referrer->GetDexCacheResolvedMethods()->Get(method_idx);
@@ -84,7 +84,7 @@ inline mirror::ArtMethod* ClassLinker::ResolveMethod(uint32_t method_idx,
}
inline mirror::ArtField* ClassLinker::ResolveField(uint32_t field_idx,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
bool is_static) {
mirror::Class* declaring_class = referrer->GetDeclaringClass();
mirror::ArtField* resolved_field =
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index f1f5905..978c99b 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -712,11 +712,11 @@ const DexFile* ClassLinker::FindDexFileInOatLocation(const char* dex_location,
return nullptr;
}
- uint32_t expected_image_oat_offset = reinterpret_cast<uint32_t>(image_header.GetOatDataBegin());
+ uintptr_t expected_image_oat_offset = reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin());
uint32_t actual_image_oat_offset = oat_file->GetOatHeader().GetImageFileLocationOatDataBegin();
if (expected_image_oat_offset != actual_image_oat_offset) {
- *error_msg = StringPrintf("Failed to find oat file at '%s' with expected image oat offset %ud, "
- "found %ud", oat_location, expected_image_oat_offset,
+ *error_msg = StringPrintf("Failed to find oat file at '%s' with expected image oat offset %"
+ PRIuPTR ", found %ud", oat_location, expected_image_oat_offset,
actual_image_oat_offset);
return nullptr;
}
@@ -858,7 +858,7 @@ bool ClassLinker::VerifyOatFileChecksums(const OatFile* oat_file,
Runtime* runtime = Runtime::Current();
const ImageHeader& image_header = runtime->GetHeap()->GetImageSpace()->GetImageHeader();
uint32_t image_oat_checksum = image_header.GetOatChecksum();
- uint32_t image_oat_data_begin = reinterpret_cast<uint32_t>(image_header.GetOatDataBegin());
+ uintptr_t image_oat_data_begin = reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin());
bool image_check = ((oat_file->GetOatHeader().GetImageFileLocationOatChecksum() == image_oat_checksum)
&& (oat_file->GetOatHeader().GetImageFileLocationOatDataBegin() == image_oat_data_begin));
@@ -885,7 +885,7 @@ bool ClassLinker::VerifyOatFileChecksums(const OatFile* oat_file,
ScopedObjectAccess soa(Thread::Current());
mirror::String* oat_location = image_header.GetImageRoot(ImageHeader::kOatLocation)->AsString();
std::string image_file(oat_location->ToModifiedUtf8());
- *error_msg = StringPrintf("oat file '%s' mismatch (0x%x, %d) with '%s' (0x%x, %d)",
+ *error_msg = StringPrintf("oat file '%s' mismatch (0x%x, %d) with '%s' (0x%x, %" PRIdPTR ")",
oat_file->GetLocation().c_str(),
oat_file->GetOatHeader().GetImageFileLocationOatChecksum(),
oat_file->GetOatHeader().GetImageFileLocationOatDataBegin(),
@@ -1023,7 +1023,8 @@ static void InitFromImageInterpretOnlyCallback(mirror::Object* obj, void* arg)
if (!method->IsNative()) {
method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterBridge);
if (method != Runtime::Current()->GetResolutionMethod()) {
- method->SetEntryPointFromCompiledCode(GetCompiledCodeToInterpreterBridge());
+ method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
+ method->SetEntryPointFromPortableCompiledCode(GetPortableToInterpreterBridge());
}
}
}
@@ -1572,7 +1573,7 @@ static uint32_t GetOatMethodIndexFromMethodIndex(const DexFile& dex_file, uint16
return 0;
}
-const OatFile::OatMethod ClassLinker::GetOatMethodFor(const mirror::ArtMethod* method) {
+const OatFile::OatMethod ClassLinker::GetOatMethodFor(mirror::ArtMethod* method) {
// Although we overwrite the trampoline of non-static methods, we may get here via the resolution
// method for direct methods (or virtual methods made direct).
mirror::Class* declaring_class = method->GetDeclaringClass();
@@ -1608,35 +1609,68 @@ const OatFile::OatMethod ClassLinker::GetOatMethodFor(const mirror::ArtMethod* m
}
// Special case to get oat code without overwriting a trampoline.
-const void* ClassLinker::GetOatCodeFor(const mirror::ArtMethod* method) {
+const void* ClassLinker::GetQuickOatCodeFor(mirror::ArtMethod* method) {
CHECK(!method->IsAbstract()) << PrettyMethod(method);
if (method->IsProxyMethod()) {
-#if !defined(ART_USE_PORTABLE_COMPILER)
- return reinterpret_cast<void*>(art_quick_proxy_invoke_handler);
-#else
- return reinterpret_cast<void*>(art_portable_proxy_invoke_handler);
-#endif
+ return GetQuickProxyInvokeHandler();
+ }
+ const void* result = GetOatMethodFor(method).GetQuickCode();
+ if (result == nullptr) {
+ if (method->IsPortableCompiled()) {
+ // No code? Do we expect portable code?
+ result = GetQuickToPortableBridge();
+ } else {
+ // No code? You must mean to go into the interpreter.
+ result = GetQuickToInterpreterBridge();
+ }
}
- const void* result = GetOatMethodFor(method).GetCode();
- if (result == NULL) {
- // No code? You must mean to go into the interpreter.
- result = GetCompiledCodeToInterpreterBridge();
+ return result;
+}
+
+const void* ClassLinker::GetPortableOatCodeFor(mirror::ArtMethod* method,
+ bool* have_portable_code) {
+ CHECK(!method->IsAbstract()) << PrettyMethod(method);
+ *have_portable_code = false;
+ if (method->IsProxyMethod()) {
+ return GetPortableProxyInvokeHandler();
+ }
+ const void* result = GetOatMethodFor(method).GetPortableCode();
+ if (result == nullptr) {
+ if (GetOatMethodFor(method).GetQuickCode() == nullptr) {
+ // No code? You must mean to go into the interpreter.
+ result = GetPortableToInterpreterBridge();
+ } else {
+ // No code? But there's quick code, so use a bridge.
+ result = GetPortableToQuickBridge();
+ }
+ } else {
+ *have_portable_code = true;
}
return result;
}
-const void* ClassLinker::GetOatCodeFor(const DexFile& dex_file, uint16_t class_def_idx,
- uint32_t method_idx) {
+const void* ClassLinker::GetQuickOatCodeFor(const DexFile& dex_file, uint16_t class_def_idx,
+ uint32_t method_idx) {
UniquePtr<const OatFile::OatClass> oat_class(GetOatClass(dex_file, class_def_idx));
CHECK(oat_class.get() != nullptr);
uint32_t oat_method_idx = GetOatMethodIndexFromMethodIndex(dex_file, class_def_idx, method_idx);
- return oat_class->GetOatMethod(oat_method_idx).GetCode();
+ return oat_class->GetOatMethod(oat_method_idx).GetQuickCode();
+}
+
+const void* ClassLinker::GetPortableOatCodeFor(const DexFile& dex_file, uint16_t class_def_idx,
+ uint32_t method_idx) {
+ UniquePtr<const OatFile::OatClass> oat_class(GetOatClass(dex_file, class_def_idx));
+ CHECK(oat_class.get() != nullptr);
+ uint32_t oat_method_idx = GetOatMethodIndexFromMethodIndex(dex_file, class_def_idx, method_idx);
+ return oat_class->GetOatMethod(oat_method_idx).GetPortableCode();
}
// Returns true if the method must run with interpreter, false otherwise.
-static bool NeedsInterpreter(const mirror::ArtMethod* method, const void* code) {
- if (code == NULL) {
+static bool NeedsInterpreter(mirror::ArtMethod* method, const void* quick_code,
+ const void* portable_code) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ if ((quick_code == nullptr) && (portable_code == nullptr)) {
// No code: need interpreter.
+ DCHECK(!method->IsNative());
return true;
}
#ifdef ART_SEA_IR_MODE
@@ -1684,13 +1718,26 @@ void ClassLinker::FixupStaticTrampolines(mirror::Class* klass) {
// Only update static methods.
continue;
}
- const void* code = oat_class->GetOatMethod(method_index).GetCode();
- const bool enter_interpreter = NeedsInterpreter(method, code);
+ const void* portable_code = oat_class->GetOatMethod(method_index).GetPortableCode();
+ const void* quick_code = oat_class->GetOatMethod(method_index).GetQuickCode();
+ const bool enter_interpreter = NeedsInterpreter(method, quick_code, portable_code);
+ bool have_portable_code = false;
if (enter_interpreter) {
// Use interpreter entry point.
- code = GetCompiledCodeToInterpreterBridge();
+ portable_code = GetPortableToInterpreterBridge();
+ quick_code = GetQuickToInterpreterBridge();
+ } else {
+ if (portable_code == nullptr) {
+ portable_code = GetPortableToQuickBridge();
+ } else {
+ have_portable_code = true;
+ }
+ if (quick_code == nullptr) {
+ quick_code = GetQuickToPortableBridge();
+ }
}
- runtime->GetInstrumentation()->UpdateMethodsCode(method, code);
+ runtime->GetInstrumentation()->UpdateMethodsCode(method, quick_code, portable_code,
+ have_portable_code);
}
// Ignore virtual methods on the iterator.
}
@@ -1699,7 +1746,8 @@ static void LinkCode(const SirtRef<mirror::ArtMethod>& method, const OatFile::Oa
uint32_t method_index)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Method shouldn't have already been linked.
- DCHECK(method->GetEntryPointFromCompiledCode() == NULL);
+ DCHECK(method->GetEntryPointFromQuickCompiledCode() == nullptr);
+ DCHECK(method->GetEntryPointFromPortableCompiledCode() == nullptr);
// Every kind of method should at least get an invoke stub from the oat_method.
// non-abstract methods also get their code pointers.
const OatFile::OatMethod oat_method = oat_class->GetOatMethod(method_index);
@@ -1707,7 +1755,9 @@ static void LinkCode(const SirtRef<mirror::ArtMethod>& method, const OatFile::Oa
// Install entry point from interpreter.
Runtime* runtime = Runtime::Current();
- bool enter_interpreter = NeedsInterpreter(method.get(), method->GetEntryPointFromCompiledCode());
+ bool enter_interpreter = NeedsInterpreter(method.get(),
+ method->GetEntryPointFromQuickCompiledCode(),
+ method->GetEntryPointFromPortableCompiledCode());
if (enter_interpreter) {
method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterBridge);
} else {
@@ -1715,18 +1765,29 @@ static void LinkCode(const SirtRef<mirror::ArtMethod>& method, const OatFile::Oa
}
if (method->IsAbstract()) {
- method->SetEntryPointFromCompiledCode(GetCompiledCodeToInterpreterBridge());
+ method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
+ method->SetEntryPointFromPortableCompiledCode(GetPortableToInterpreterBridge());
return;
}
+ bool have_portable_code = false;
if (method->IsStatic() && !method->IsConstructor()) {
// 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->SetEntryPointFromCompiledCode(GetResolutionTrampoline(runtime->GetClassLinker()));
+ method->SetEntryPointFromQuickCompiledCode(GetQuickResolutionTrampoline(runtime->GetClassLinker()));
+ method->SetEntryPointFromPortableCompiledCode(GetPortableResolutionTrampoline(runtime->GetClassLinker()));
} else if (enter_interpreter) {
// Set entry point from compiled code if there's no code or in interpreter only mode.
- method->SetEntryPointFromCompiledCode(GetCompiledCodeToInterpreterBridge());
+ method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
+ method->SetEntryPointFromPortableCompiledCode(GetPortableToInterpreterBridge());
+ } else if (method->GetEntryPointFromPortableCompiledCode() != nullptr) {
+ DCHECK(method->GetEntryPointFromQuickCompiledCode() == nullptr);
+ have_portable_code = true;
+ method->SetEntryPointFromQuickCompiledCode(GetQuickToPortableBridge());
+ } else {
+ DCHECK(method->GetEntryPointFromQuickCompiledCode() != nullptr);
+ method->SetEntryPointFromPortableCompiledCode(GetPortableToQuickBridge());
}
if (method->IsNative()) {
@@ -1736,7 +1797,9 @@ static void LinkCode(const SirtRef<mirror::ArtMethod>& method, const OatFile::Oa
// Allow instrumentation its chance to hijack code.
runtime->GetInstrumentation()->UpdateMethodsCode(method.get(),
- method->GetEntryPointFromCompiledCode());
+ method->GetEntryPointFromQuickCompiledCode(),
+ method->GetEntryPointFromPortableCompiledCode(),
+ have_portable_code);
}
void ClassLinker::LoadClass(const DexFile& dex_file,
@@ -2803,15 +2866,15 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccess& soa, jstring na
return klass.get();
}
-std::string ClassLinker::GetDescriptorForProxy(const mirror::Class* proxy_class) {
+std::string ClassLinker::GetDescriptorForProxy(mirror::Class* proxy_class) {
DCHECK(proxy_class->IsProxyClass());
mirror::String* name = proxy_class->GetName();
DCHECK(name != NULL);
return DotToDescriptor(name->ToModifiedUtf8().c_str());
}
-mirror::ArtMethod* ClassLinker::FindMethodForProxy(const mirror::Class* proxy_class,
- const mirror::ArtMethod* proxy_method) {
+mirror::ArtMethod* ClassLinker::FindMethodForProxy(mirror::Class* proxy_class,
+ mirror::ArtMethod* proxy_method) {
DCHECK(proxy_class->IsProxyClass());
DCHECK(proxy_method->IsProxyMethod());
// Locate the dex cache of the original interface/Object
@@ -2892,7 +2955,8 @@ mirror::ArtMethod* ClassLinker::CreateProxyMethod(Thread* self,
method->SetCoreSpillMask(refs_and_args->GetCoreSpillMask());
method->SetFpSpillMask(refs_and_args->GetFpSpillMask());
method->SetFrameSizeInBytes(refs_and_args->GetFrameSizeInBytes());
- method->SetEntryPointFromCompiledCode(GetProxyInvokeHandler());
+ method->SetEntryPointFromQuickCompiledCode(GetQuickProxyInvokeHandler());
+ method->SetEntryPointFromPortableCompiledCode(GetPortableProxyInvokeHandler());
method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
return method;
@@ -3175,7 +3239,7 @@ bool ClassLinker::ValidateSuperClassDescriptors(const SirtRef<mirror::Class>& kl
klass->GetClassLoader() != klass->GetSuperClass()->GetClassLoader()) {
SirtRef<mirror::Class> super(self, klass->GetSuperClass());
for (int i = super->GetVTable()->GetLength() - 1; i >= 0; --i) {
- const mirror::ArtMethod* method = klass->GetVTable()->Get(i);
+ mirror::ArtMethod* method = klass->GetVTable()->Get(i);
if (method != super->GetVTable()->Get(i) &&
!IsSameMethodSignatureInDifferentClassContexts(method, super.get(), klass.get())) {
ThrowLinkageError(klass.get(), "Class %s method %s resolves differently in superclass %s",
@@ -3189,7 +3253,7 @@ bool ClassLinker::ValidateSuperClassDescriptors(const SirtRef<mirror::Class>& kl
SirtRef<mirror::Class> interface(self, klass->GetIfTable()->GetInterface(i));
if (klass->GetClassLoader() != interface->GetClassLoader()) {
for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
- const mirror::ArtMethod* method = klass->GetIfTable()->GetMethodArray(i)->Get(j);
+ mirror::ArtMethod* method = klass->GetIfTable()->GetMethodArray(i)->Get(j);
if (!IsSameMethodSignatureInDifferentClassContexts(method, interface.get(),
method->GetDeclaringClass())) {
ThrowLinkageError(klass.get(), "Class %s method %s resolves differently in interface %s",
@@ -3206,9 +3270,9 @@ bool ClassLinker::ValidateSuperClassDescriptors(const SirtRef<mirror::Class>& kl
// Returns true if classes referenced by the signature of the method are the
// same classes in klass1 as they are in klass2.
-bool ClassLinker::IsSameMethodSignatureInDifferentClassContexts(const mirror::ArtMethod* method,
- const mirror::Class* klass1,
- const mirror::Class* klass2) {
+bool ClassLinker::IsSameMethodSignatureInDifferentClassContexts(mirror::ArtMethod* method,
+ mirror::Class* klass1,
+ mirror::Class* klass2) {
if (klass1 == klass2) {
return true;
}
@@ -3790,23 +3854,24 @@ struct LinkFieldsComparator {
explicit LinkFieldsComparator() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
}
// No thread safety analysis as will be called from STL. Checked lock held in constructor.
- bool operator()(const mirror::ArtField* field1, const mirror::ArtField* field2)
+ bool operator()(mirror::ArtField* field1, mirror::ArtField* field2)
NO_THREAD_SAFETY_ANALYSIS {
// First come reference fields, then 64-bit, and finally 32-bit
FieldHelper fh1(field1);
Primitive::Type type1 = fh1.GetTypeAsPrimitiveType();
FieldHelper fh2(field2);
Primitive::Type type2 = fh2.GetTypeAsPrimitiveType();
- bool isPrimitive1 = type1 != Primitive::kPrimNot;
- bool isPrimitive2 = type2 != Primitive::kPrimNot;
- bool is64bit1 = isPrimitive1 && (type1 == Primitive::kPrimLong || type1 == Primitive::kPrimDouble);
- bool is64bit2 = isPrimitive2 && (type2 == Primitive::kPrimLong || type2 == Primitive::kPrimDouble);
- int order1 = (!isPrimitive1 ? 0 : (is64bit1 ? 1 : 2));
- int order2 = (!isPrimitive2 ? 0 : (is64bit2 ? 1 : 2));
- if (order1 != order2) {
- return order1 < order2;
+ if (type1 != type2) {
+ bool is_primitive1 = type1 != Primitive::kPrimNot;
+ bool is_primitive2 = type2 != Primitive::kPrimNot;
+ bool is64bit1 = is_primitive1 && (type1 == Primitive::kPrimLong || type1 == Primitive::kPrimDouble);
+ bool is64bit2 = is_primitive2 && (type2 == Primitive::kPrimLong || type2 == Primitive::kPrimDouble);
+ int order1 = !is_primitive1 ? 0 : (is64bit1 ? 1 : 2);
+ int order2 = !is_primitive2 ? 0 : (is64bit2 ? 1 : 2);
+ if (order1 != order2) {
+ return order1 < order2;
+ }
}
-
// same basic group? then sort by string.
const char* name1 = fh1.GetName();
const char* name2 = fh2.GetName();
@@ -3996,14 +4061,14 @@ void ClassLinker::CreateReferenceOffsets(const SirtRef<mirror::Class>& klass, bo
size_t num_reference_fields =
is_static ? klass->NumReferenceStaticFieldsDuringLinking()
: klass->NumReferenceInstanceFieldsDuringLinking();
- const mirror::ObjectArray<mirror::ArtField>* fields =
+ mirror::ObjectArray<mirror::ArtField>* fields =
is_static ? klass->GetSFields() : klass->GetIFields();
// All of the fields that contain object references are guaranteed
// to be at the beginning of the fields list.
for (size_t i = 0; i < num_reference_fields; ++i) {
// Note that byte_offset is the offset from the beginning of
// object, not the offset into instance data
- const mirror::ArtField* field = fields->Get(i);
+ mirror::ArtField* field = fields->Get(i);
MemberOffset byte_offset = field->GetOffsetDuringLinking();
CHECK_EQ(byte_offset.Uint32Value() & (CLASS_OFFSET_ALIGNMENT - 1), 0U);
if (CLASS_CAN_ENCODE_OFFSET(byte_offset.Uint32Value())) {
@@ -4038,7 +4103,7 @@ mirror::String* ClassLinker::ResolveString(const DexFile& dex_file, uint32_t str
}
mirror::Class* ClassLinker::ResolveType(const DexFile& dex_file, uint16_t type_idx,
- const mirror::Class* referrer) {
+ mirror::Class* referrer) {
Thread* self = Thread::Current();
SirtRef<mirror::DexCache> dex_cache(self, referrer->GetDexCache());
SirtRef<mirror::ClassLoader> class_loader(self, referrer->GetClassLoader());
@@ -4081,7 +4146,7 @@ mirror::ArtMethod* ClassLinker::ResolveMethod(const DexFile& dex_file,
uint32_t method_idx,
const SirtRef<mirror::DexCache>& dex_cache,
const SirtRef<mirror::ClassLoader>& class_loader,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
InvokeType type) {
DCHECK(dex_cache.get() != NULL);
// Check for hit in the dex cache.
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 8722de3..7e31356 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -121,7 +121,7 @@ class ClassLinker {
// Resolve a String with the given index from the DexFile, storing the
// result in the DexCache. The referrer is used to identify the
// target DexCache and ClassLoader to use for resolution.
- mirror::String* ResolveString(uint32_t string_idx, const mirror::ArtMethod* referrer)
+ mirror::String* ResolveString(uint32_t string_idx, mirror::ArtMethod* referrer)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Resolve a String with the given index from the DexFile, storing the
@@ -133,17 +133,16 @@ class ClassLinker {
// Resolve a Type with the given index from the DexFile, storing the
// result in the DexCache. The referrer is used to identity the
// target DexCache and ClassLoader to use for resolution.
- mirror::Class* ResolveType(const DexFile& dex_file, uint16_t type_idx,
- const mirror::Class* referrer)
+ mirror::Class* ResolveType(const DexFile& dex_file, uint16_t type_idx, mirror::Class* referrer)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Resolve a Type with the given index from the DexFile, storing the
// result in the DexCache. The referrer is used to identify the
// target DexCache and ClassLoader to use for resolution.
- mirror::Class* ResolveType(uint16_t type_idx, const mirror::ArtMethod* referrer)
+ mirror::Class* ResolveType(uint16_t type_idx, mirror::ArtMethod* referrer)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- mirror::Class* ResolveType(uint16_t type_idx, const mirror::ArtField* referrer)
+ mirror::Class* ResolveType(uint16_t type_idx, mirror::ArtField* referrer)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Resolve a type with the given ID from the DexFile, storing the
@@ -164,15 +163,15 @@ class ClassLinker {
uint32_t method_idx,
const SirtRef<mirror::DexCache>& dex_cache,
const SirtRef<mirror::ClassLoader>& class_loader,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
InvokeType type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- mirror::ArtMethod* ResolveMethod(uint32_t method_idx, const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* ResolveMethod(uint32_t method_idx, mirror::ArtMethod* referrer,
InvokeType type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- mirror::ArtField* ResolveField(uint32_t field_idx, const mirror::ArtMethod* referrer,
+ mirror::ArtField* ResolveField(uint32_t field_idx, mirror::ArtMethod* referrer,
bool is_static)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -319,19 +318,23 @@ class ClassLinker {
mirror::Class* CreateProxyClass(ScopedObjectAccess& soa, jstring name, jobjectArray interfaces,
jobject loader, jobjectArray methods, jobjectArray throws)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- std::string GetDescriptorForProxy(const mirror::Class* proxy_class)
+ std::string GetDescriptorForProxy(mirror::Class* proxy_class)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- mirror::ArtMethod* FindMethodForProxy(const mirror::Class* proxy_class,
- const mirror::ArtMethod* proxy_method)
+ mirror::ArtMethod* FindMethodForProxy(mirror::Class* proxy_class,
+ mirror::ArtMethod* proxy_method)
LOCKS_EXCLUDED(dex_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Get the oat code for a method when its class isn't yet initialized
- const void* GetOatCodeFor(const mirror::ArtMethod* method)
+ const void* GetQuickOatCodeFor(mirror::ArtMethod* method)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ const void* GetPortableOatCodeFor(mirror::ArtMethod* method, bool* have_portable_code)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Get the oat code for a method from a method index.
- const void* GetOatCodeFor(const DexFile& dex_file, uint16_t class_def_idx, uint32_t method_idx)
+ const void* GetQuickOatCodeFor(const DexFile& dex_file, uint16_t class_def_idx, uint32_t method_idx)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ const void* GetPortableOatCodeFor(const DexFile& dex_file, uint16_t class_def_idx, uint32_t method_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
pid_t GetClassesLockOwner(); // For SignalCatcher.
@@ -368,7 +371,7 @@ class ClassLinker {
mirror::ArtMethod* AllocArtMethod(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
private:
- const OatFile::OatMethod GetOatMethodFor(const mirror::ArtMethod* method)
+ const OatFile::OatMethod GetOatMethodFor(mirror::ArtMethod* method)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
OatFile& GetImageOatFile(gc::space::ImageSpace* space)
@@ -451,9 +454,9 @@ class ClassLinker {
SirtRef<mirror::ClassLoader>& class_loader2)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsSameMethodSignatureInDifferentClassContexts(const mirror::ArtMethod* method,
- const mirror::Class* klass1,
- const mirror::Class* klass2)
+ bool IsSameMethodSignatureInDifferentClassContexts(mirror::ArtMethod* method,
+ mirror::Class* klass1,
+ mirror::Class* klass2)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool LinkClass(Thread* self, const SirtRef<mirror::Class>& klass,
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 1744050..fb979c2 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -55,7 +55,7 @@ class ClassLinkerTest : public CommonTest {
AssertPrimitiveClass(descriptor, class_linker_->FindSystemClass(descriptor.c_str()));
}
- void AssertPrimitiveClass(const std::string& descriptor, const mirror::Class* primitive)
+ void AssertPrimitiveClass(const std::string& descriptor, mirror::Class* primitive)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ClassHelper primitive_ch(primitive);
ASSERT_TRUE(primitive != NULL);
@@ -212,7 +212,7 @@ class ClassLinkerTest : public CommonTest {
}
}
EXPECT_EQ(klass->IsInterface(), klass->GetVTable() == NULL);
- const mirror::IfTable* iftable = klass->GetIfTable();
+ mirror::IfTable* iftable = klass->GetIfTable();
for (int i = 0; i < klass->GetIfTableCount(); i++) {
mirror::Class* interface = iftable->GetInterface(i);
ASSERT_TRUE(interface != NULL);
@@ -469,20 +469,23 @@ struct ArtMethodOffsets : public CheckOffsets<mirror::ArtMethod> {
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_cache_resolved_types_), "dexCacheResolvedTypes"));
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_cache_strings_), "dexCacheStrings"));
+ // alphabetical 64-bit
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, entry_point_from_interpreter_), "entryPointFromInterpreter"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, entry_point_from_jni_), "entryPointFromJni"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, entry_point_from_portable_compiled_code_), "entryPointFromPortableCompiledCode"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, entry_point_from_quick_compiled_code_), "entryPointFromQuickCompiledCode"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, gc_map_), "gcMap"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, quick_mapping_table_), "quickMappingTable"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, quick_vmap_table_), "quickVmapTable"));
+
// alphabetical 32-bit
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, access_flags_), "accessFlags"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, code_item_offset_), "codeItemOffset"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, core_spill_mask_), "coreSpillMask"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, entry_point_from_compiled_code_), "entryPointFromCompiledCode"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, entry_point_from_interpreter_), "entryPointFromInterpreter"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, fp_spill_mask_), "fpSpillMask"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, frame_size_in_bytes_), "frameSizeInBytes"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, gc_map_), "gcMap"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, mapping_table_), "mappingTable"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, method_dex_index_), "methodDexIndex"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_code_item_offset_), "dexCodeItemOffset"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_method_index_), "dexMethodIndex"));
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, method_index_), "methodIndex"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, native_method_), "nativeMethod"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, vmap_table_), "vmapTable"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, quick_core_spill_mask_), "quickCoreSpillMask"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, quick_fp_spill_mask_), "quickFpSpillMask"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, quick_frame_size_in_bytes_), "quickFrameSizeInBytes"));
};
};
@@ -762,10 +765,10 @@ TEST_F(ClassLinkerTest, ValidateObjectArrayElementsOffset) {
mirror::Class* array_class = class_linker_->FindSystemClass("[Ljava/lang/String;");
mirror::ObjectArray<mirror::String>* array =
mirror::ObjectArray<mirror::String>::Alloc(soa.Self(), array_class, 0);
- uint32_t array_offset = reinterpret_cast<uint32_t>(array);
- uint32_t data_offset =
- array_offset + mirror::ObjectArray<mirror::String>::DataOffset(sizeof(mirror::String*)).Uint32Value();
- if (sizeof(mirror::String*) == sizeof(int32_t)) {
+ uintptr_t data_offset =
+ reinterpret_cast<uintptr_t>(array->GetRawData(sizeof(mirror::HeapReference<mirror::String>),
+ 0));
+ if (sizeof(mirror::HeapReference<mirror::String>) == sizeof(int32_t)) {
EXPECT_TRUE(IsAligned<4>(data_offset)); // Check 4 byte alignment.
} else {
EXPECT_TRUE(IsAligned<8>(data_offset)); // Check 8 byte alignment.
diff --git a/runtime/common_test.h b/runtime/common_test.h
index fce3f3f..ddaf52a 100644
--- a/runtime/common_test.h
+++ b/runtime/common_test.h
@@ -48,6 +48,7 @@
#include "scoped_thread_state_change.h"
#include "ScopedLocalRef.h"
#include "thread.h"
+#include "utils.h"
#include "UniquePtr.h"
#include "verifier/method_verifier.h"
#include "verifier/method_verifier-inl.h"
@@ -262,11 +263,6 @@ static InstructionSetFeatures ParseFeatureList(std::string str) {
class CommonTest : public testing::Test {
public:
- static void MakeExecutable(const mirror::ByteArray* code_array) {
- CHECK(code_array != NULL);
- MakeExecutable(code_array->GetData(), code_array->GetLength());
- }
-
static void MakeExecutable(const std::vector<uint8_t>& code) {
CHECK_NE(code.size(), 0U);
MakeExecutable(&code[0], code.size());
@@ -280,31 +276,39 @@ class CommonTest : public testing::Test {
const uint8_t* mapping_table,
const uint8_t* vmap_table,
const uint8_t* gc_map) {
- return OatFile::OatMethod(NULL,
- reinterpret_cast<uint32_t>(code),
- frame_size_in_bytes,
- core_spill_mask,
- fp_spill_mask,
- reinterpret_cast<uint32_t>(mapping_table),
- reinterpret_cast<uint32_t>(vmap_table),
- reinterpret_cast<uint32_t>(gc_map));
+ const byte* base = nullptr; // Base of data in oat file, ie 0.
+ uint32_t code_offset = PointerToLowMemUInt32(code);
+ uint32_t mapping_table_offset = PointerToLowMemUInt32(mapping_table);
+ uint32_t vmap_table_offset = PointerToLowMemUInt32(vmap_table);
+ uint32_t gc_map_offset = PointerToLowMemUInt32(gc_map);
+ return OatFile::OatMethod(base,
+ code_offset,
+ frame_size_in_bytes,
+ core_spill_mask,
+ fp_spill_mask,
+ mapping_table_offset,
+ vmap_table_offset,
+ gc_map_offset);
}
void MakeExecutable(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- CHECK(method != NULL);
+ CHECK(method != nullptr);
- const CompiledMethod* compiled_method = NULL;
+ const CompiledMethod* compiled_method = nullptr;
if (!method->IsAbstract()) {
- const mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
+ mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
const DexFile& dex_file = *dex_cache->GetDexFile();
compiled_method =
compiler_driver_->GetCompiledMethod(MethodReference(&dex_file,
method->GetDexMethodIndex()));
}
- if (compiled_method != NULL) {
- const std::vector<uint8_t>& code = compiled_method->GetCode();
- MakeExecutable(code);
- const void* method_code = CompiledMethod::CodePointer(&code[0],
+ if (compiled_method != nullptr) {
+ const std::vector<uint8_t>* code = compiled_method->GetQuickCode();
+ if (code == nullptr) {
+ code = compiled_method->GetPortableCode();
+ }
+ MakeExecutable(*code);
+ const void* method_code = CompiledMethod::CodePointer(&(*code)[0],
compiled_method->GetInstructionSet());
LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code;
OatFile::OatMethod oat_method = CreateOatMethod(method_code,
@@ -317,9 +321,9 @@ class CommonTest : public testing::Test {
oat_method.LinkMethod(method);
method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
} else {
- const void* method_code;
// No code? You must mean to go into the interpreter.
- method_code = GetCompiledCodeToInterpreterBridge();
+ const void* method_code = kUsePortableCompiler ? GetPortableToInterpreterBridge()
+ : GetQuickToInterpreterBridge();
OatFile::OatMethod oat_method = CreateOatMethod(method_code,
kStackAlignment,
0,
@@ -330,6 +334,14 @@ class CommonTest : public testing::Test {
oat_method.LinkMethod(method);
method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterBridge);
}
+ // Create bridges to transition between different kinds of compiled bridge.
+ if (method->GetEntryPointFromPortableCompiledCode() == nullptr) {
+ method->SetEntryPointFromPortableCompiledCode(GetPortableToQuickBridge());
+ } else {
+ CHECK(method->GetEntryPointFromQuickCompiledCode() == nullptr);
+ method->SetEntryPointFromQuickCompiledCode(GetQuickToPortableBridge());
+ method->SetIsPortableCompiled();
+ }
}
static void MakeExecutable(const void* code_start, size_t code_length) {
@@ -415,11 +427,7 @@ class CommonTest : public testing::Test {
std::string max_heap_string(StringPrintf("-Xmx%zdm", gc::Heap::kDefaultMaximumSize / MB));
// TODO: make selectable
-#if defined(ART_USE_PORTABLE_COMPILER)
- CompilerBackend compiler_backend = kPortable;
-#else
- CompilerBackend compiler_backend = kQuick;
-#endif
+ CompilerBackend compiler_backend = kUsePortableCompiler ? kPortable : kQuick;
verification_results_.reset(new VerificationResults);
method_inliner_map_.reset(compiler_backend == kQuick ? new DexFileToMethodInlinerMap : nullptr);
@@ -460,6 +468,8 @@ class CommonTest : public testing::Test {
instruction_set = kMips;
#elif defined(__i386__)
instruction_set = kX86;
+#elif defined(__x86_64__)
+ instruction_set = kX86_64;
#endif
for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
@@ -640,7 +650,9 @@ class CommonTest : public testing::Test {
image_reservation_.reset(MemMap::MapAnonymous("image reservation",
reinterpret_cast<byte*>(ART_BASE_ADDRESS),
(size_t)100 * 1024 * 1024, // 100MB
- PROT_NONE, &error_msg));
+ PROT_NONE,
+ false /* no need for 4gb flag with fixed mmap*/,
+ &error_msg));
CHECK(image_reservation_.get() != nullptr) << error_msg;
}
@@ -733,11 +745,12 @@ class CheckJniAbortCatcher {
// MCLinker link LLVM ELF output because we no longer just have code
// blobs in memory. We'll need to dlopen to load and relocate
// temporary output to resurrect these tests.
-#if defined(ART_USE_PORTABLE_COMPILER)
-#define TEST_DISABLED_FOR_PORTABLE() printf("WARNING: TEST DISABLED FOR PORTABLE\n"); return
-#else
-#define TEST_DISABLED_FOR_PORTABLE()
-#endif
+#define TEST_DISABLED_FOR_PORTABLE() \
+ if (kUsePortableCompiler) { \
+ printf("WARNING: TEST DISABLED FOR PORTABLE\n"); \
+ return; \
+ }
+
} // namespace art
namespace std {
diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc
index dd832df..24d16c4 100644
--- a/runtime/common_throws.cc
+++ b/runtime/common_throws.cc
@@ -33,7 +33,7 @@
namespace art {
-static void AddReferrerLocation(std::ostream& os, const mirror::Class* referrer)
+static void AddReferrerLocation(std::ostream& os, mirror::Class* referrer)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (referrer != NULL) {
ClassHelper kh(referrer);
@@ -46,7 +46,7 @@ static void AddReferrerLocation(std::ostream& os, const mirror::Class* referrer)
}
static void ThrowException(const ThrowLocation* throw_location, const char* exception_descriptor,
- const mirror::Class* referrer, const char* fmt, va_list* args = NULL)
+ mirror::Class* referrer, const char* fmt, va_list* args = NULL)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
std::ostringstream msg;
if (args != NULL) {
@@ -68,7 +68,7 @@ static void ThrowException(const ThrowLocation* throw_location, const char* exce
// AbstractMethodError
-void ThrowAbstractMethodError(const mirror::ArtMethod* method) {
+void ThrowAbstractMethodError(mirror::ArtMethod* method) {
ThrowException(NULL, "Ljava/lang/AbstractMethodError;", NULL,
StringPrintf("abstract method \"%s\"",
PrettyMethod(method).c_str()).c_str());
@@ -89,8 +89,7 @@ void ThrowArrayIndexOutOfBoundsException(int index, int length) {
// ArrayStoreException
-void ThrowArrayStoreException(const mirror::Class* element_class,
- const mirror::Class* array_class) {
+void ThrowArrayStoreException(mirror::Class* element_class, mirror::Class* array_class) {
ThrowException(NULL, "Ljava/lang/ArrayStoreException;", NULL,
StringPrintf("%s cannot be stored in an array of type %s",
PrettyDescriptor(element_class).c_str(),
@@ -99,7 +98,7 @@ void ThrowArrayStoreException(const mirror::Class* element_class,
// ClassCastException
-void ThrowClassCastException(const mirror::Class* dest_type, const mirror::Class* src_type) {
+void ThrowClassCastException(mirror::Class* dest_type, mirror::Class* src_type) {
ThrowException(NULL, "Ljava/lang/ClassCastException;", NULL,
StringPrintf("%s cannot be cast to %s",
PrettyDescriptor(src_type).c_str(),
@@ -120,7 +119,7 @@ void ThrowClassCircularityError(mirror::Class* c) {
// ClassFormatError
-void ThrowClassFormatError(const mirror::Class* referrer, const char* fmt, ...) {
+void ThrowClassFormatError(mirror::Class* referrer, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
ThrowException(NULL, "Ljava/lang/ClassFormatError;", referrer, fmt, &args);
@@ -136,7 +135,7 @@ void ThrowIllegalAccessErrorClass(mirror::Class* referrer, mirror::Class* access
}
void ThrowIllegalAccessErrorClassForMethodDispatch(mirror::Class* referrer, mirror::Class* accessed,
- const mirror::ArtMethod* called,
+ mirror::ArtMethod* called,
InvokeType type) {
std::ostringstream msg;
msg << "Illegal class access ('" << PrettyDescriptor(referrer) << "' attempting to access '"
@@ -159,7 +158,7 @@ void ThrowIllegalAccessErrorField(mirror::Class* referrer, mirror::ArtField* acc
ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
}
-void ThrowIllegalAccessErrorFinalField(const mirror::ArtMethod* referrer,
+void ThrowIllegalAccessErrorFinalField(mirror::ArtMethod* referrer,
mirror::ArtField* accessed) {
std::ostringstream msg;
msg << "Final field '" << PrettyField(accessed, false) << "' cannot be written to by method '"
@@ -187,7 +186,7 @@ void ThrowIllegalArgumentException(const ThrowLocation* throw_location, const ch
void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType found_type,
mirror::ArtMethod* method,
- const mirror::ArtMethod* referrer) {
+ mirror::ArtMethod* referrer) {
std::ostringstream msg;
msg << "The method '" << PrettyMethod(method) << "' was expected to be of type "
<< expected_type << " but instead was found to be of type " << found_type;
@@ -196,9 +195,9 @@ void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType foun
msg.str().c_str());
}
-void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(const mirror::ArtMethod* interface_method,
+void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(mirror::ArtMethod* interface_method,
mirror::Object* this_object,
- const mirror::ArtMethod* referrer) {
+ mirror::ArtMethod* referrer) {
// Referrer is calling interface_method on this_object, however, the interface_method isn't
// implemented by this_object.
CHECK(this_object != NULL);
@@ -212,8 +211,8 @@ void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(const mirror::Ar
msg.str().c_str());
}
-void ThrowIncompatibleClassChangeErrorField(const mirror::ArtField* resolved_field, bool is_static,
- const mirror::ArtMethod* referrer) {
+void ThrowIncompatibleClassChangeErrorField(mirror::ArtField* resolved_field, bool is_static,
+ mirror::ArtMethod* referrer) {
std::ostringstream msg;
msg << "Expected '" << PrettyField(resolved_field) << "' to be a "
<< (is_static ? "static" : "instance") << " field" << " rather than a "
@@ -222,7 +221,7 @@ void ThrowIncompatibleClassChangeErrorField(const mirror::ArtField* resolved_fie
msg.str().c_str());
}
-void ThrowIncompatibleClassChangeError(const mirror::Class* referrer, const char* fmt, ...) {
+void ThrowIncompatibleClassChangeError(mirror::Class* referrer, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;", referrer, fmt, &args);
@@ -240,7 +239,7 @@ void ThrowIOException(const char* fmt, ...) {
// LinkageError
-void ThrowLinkageError(const mirror::Class* referrer, const char* fmt, ...) {
+void ThrowLinkageError(mirror::Class* referrer, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
ThrowException(NULL, "Ljava/lang/LinkageError;", referrer, fmt, &args);
@@ -486,7 +485,7 @@ void ThrowRuntimeException(const char* fmt, ...) {
// VerifyError
-void ThrowVerifyError(const mirror::Class* referrer, const char* fmt, ...) {
+void ThrowVerifyError(mirror::Class* referrer, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
ThrowException(NULL, "Ljava/lang/VerifyError;", referrer, fmt, &args);
diff --git a/runtime/common_throws.h b/runtime/common_throws.h
index 7f13891..792cdef 100644
--- a/runtime/common_throws.h
+++ b/runtime/common_throws.h
@@ -33,7 +33,7 @@ class ThrowLocation;
// AbstractMethodError
-void ThrowAbstractMethodError(const mirror::ArtMethod* method)
+void ThrowAbstractMethodError(mirror::ArtMethod* method)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
// ArithmeticException
@@ -47,8 +47,7 @@ void ThrowArrayIndexOutOfBoundsException(int index, int length)
// ArrayStoreException
-void ThrowArrayStoreException(const mirror::Class* element_class,
- const mirror::Class* array_class)
+void ThrowArrayStoreException(mirror::Class* element_class, mirror::Class* array_class)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
// ClassCircularityError
@@ -58,7 +57,7 @@ void ThrowClassCircularityError(mirror::Class* c)
// ClassCastException
-void ThrowClassCastException(const mirror::Class* dest_type, const mirror::Class* src_type)
+void ThrowClassCastException(mirror::Class* dest_type, mirror::Class* src_type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
void ThrowClassCastException(const ThrowLocation* throw_location, const char* msg)
@@ -66,7 +65,7 @@ void ThrowClassCastException(const ThrowLocation* throw_location, const char* ms
// ClassFormatError
-void ThrowClassFormatError(const mirror::Class* referrer, const char* fmt, ...)
+void ThrowClassFormatError(mirror::Class* referrer, const char* fmt, ...)
__attribute__((__format__(__printf__, 2, 3)))
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
@@ -76,7 +75,7 @@ void ThrowIllegalAccessErrorClass(mirror::Class* referrer, mirror::Class* access
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
void ThrowIllegalAccessErrorClassForMethodDispatch(mirror::Class* referrer, mirror::Class* accessed,
- const mirror::ArtMethod* called,
+ mirror::ArtMethod* called,
InvokeType type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
@@ -86,8 +85,7 @@ void ThrowIllegalAccessErrorMethod(mirror::Class* referrer, mirror::ArtMethod* a
void ThrowIllegalAccessErrorField(mirror::Class* referrer, mirror::ArtField* accessed)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
-void ThrowIllegalAccessErrorFinalField(const mirror::ArtMethod* referrer,
- mirror::ArtField* accessed)
+void ThrowIllegalAccessErrorFinalField(mirror::ArtMethod* referrer, mirror::ArtField* accessed)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
void ThrowIllegalAccessError(mirror::Class* referrer, const char* fmt, ...)
@@ -102,20 +100,19 @@ void ThrowIllegalArgumentException(const ThrowLocation* throw_location, const ch
// IncompatibleClassChangeError
void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType found_type,
- mirror::ArtMethod* method,
- const mirror::ArtMethod* referrer)
+ mirror::ArtMethod* method, mirror::ArtMethod* referrer)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
-void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(const mirror::ArtMethod* interface_method,
+void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(mirror::ArtMethod* interface_method,
mirror::Object* this_object,
- const mirror::ArtMethod* referrer)
+ mirror::ArtMethod* referrer)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
-void ThrowIncompatibleClassChangeErrorField(const mirror::ArtField* resolved_field, bool is_static,
- const mirror::ArtMethod* referrer)
+void ThrowIncompatibleClassChangeErrorField(mirror::ArtField* resolved_field, bool is_static,
+ mirror::ArtMethod* referrer)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
-void ThrowIncompatibleClassChangeError(const mirror::Class* referrer, const char* fmt, ...)
+void ThrowIncompatibleClassChangeError(mirror::Class* referrer, const char* fmt, ...)
__attribute__((__format__(__printf__, 2, 3)))
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
@@ -126,7 +123,7 @@ void ThrowIOException(const char* fmt, ...) __attribute__((__format__(__printf__
// LinkageError
-void ThrowLinkageError(const mirror::Class* referrer, const char* fmt, ...)
+void ThrowLinkageError(mirror::Class* referrer, const char* fmt, ...)
__attribute__((__format__(__printf__, 2, 3)))
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
@@ -185,7 +182,7 @@ void ThrowRuntimeException(const char* fmt, ...)
// VerifyError
-void ThrowVerifyError(const mirror::Class* referrer, const char* fmt, ...)
+void ThrowVerifyError(mirror::Class* referrer, const char* fmt, ...)
__attribute__((__format__(__printf__, 2, 3)))
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 2141997..9cc7cb4 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -101,7 +101,7 @@ class DebugInstrumentationListener : public instrumentation::InstrumentationList
virtual ~DebugInstrumentationListener() {}
virtual void MethodEntered(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc)
+ mirror::ArtMethod* method, uint32_t dex_pc)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (method->IsNative()) {
// TODO: post location events is a suspension point and native method entry stubs aren't.
@@ -111,7 +111,7 @@ class DebugInstrumentationListener : public instrumentation::InstrumentationList
}
virtual void MethodExited(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method,
+ mirror::ArtMethod* method,
uint32_t dex_pc, const JValue& return_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (method->IsNative()) {
@@ -122,7 +122,7 @@ class DebugInstrumentationListener : public instrumentation::InstrumentationList
}
virtual void MethodUnwind(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc)
+ mirror::ArtMethod* method, uint32_t dex_pc)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// We're not recorded to listen to this kind of event, so complain.
LOG(ERROR) << "Unexpected method unwind event in debugger " << PrettyMethod(method)
@@ -130,7 +130,7 @@ class DebugInstrumentationListener : public instrumentation::InstrumentationList
}
virtual void DexPcMoved(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t new_dex_pc)
+ mirror::ArtMethod* method, uint32_t new_dex_pc)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Dbg::UpdateDebugger(thread, this_object, method, new_dex_pc);
}
@@ -303,7 +303,7 @@ static JDWP::JdwpTag TagFromClass(mirror::Class* c)
*
* Null objects are tagged JT_OBJECT.
*/
-static JDWP::JdwpTag TagFromObject(const mirror::Object* o)
+static JDWP::JdwpTag TagFromObject(mirror::Object* o)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (o == NULL) ? JDWP::JT_OBJECT : TagFromClass(o->GetClass());
}
@@ -1054,16 +1054,16 @@ JDWP::JdwpError Dbg::OutputArray(JDWP::ObjectId array_id, int offset, int count,
size_t width = GetTagWidth(tag);
uint8_t* dst = expandBufAddSpace(pReply, count * width);
if (width == 8) {
- const uint64_t* src8 = reinterpret_cast<uint64_t*>(a->GetRawData(sizeof(uint64_t)));
+ const uint64_t* src8 = reinterpret_cast<uint64_t*>(a->GetRawData(sizeof(uint64_t), 0));
for (int i = 0; i < count; ++i) JDWP::Write8BE(&dst, src8[offset + i]);
} else if (width == 4) {
- const uint32_t* src4 = reinterpret_cast<uint32_t*>(a->GetRawData(sizeof(uint32_t)));
+ const uint32_t* src4 = reinterpret_cast<uint32_t*>(a->GetRawData(sizeof(uint32_t), 0));
for (int i = 0; i < count; ++i) JDWP::Write4BE(&dst, src4[offset + i]);
} else if (width == 2) {
- const uint16_t* src2 = reinterpret_cast<uint16_t*>(a->GetRawData(sizeof(uint16_t)));
+ const uint16_t* src2 = reinterpret_cast<uint16_t*>(a->GetRawData(sizeof(uint16_t), 0));
for (int i = 0; i < count; ++i) JDWP::Write2BE(&dst, src2[offset + i]);
} else {
- const uint8_t* src = reinterpret_cast<uint8_t*>(a->GetRawData(sizeof(uint8_t)));
+ const uint8_t* src = reinterpret_cast<uint8_t*>(a->GetRawData(sizeof(uint8_t), 0));
memcpy(dst, &src[offset * width], count * width);
}
} else {
@@ -1079,10 +1079,13 @@ JDWP::JdwpError Dbg::OutputArray(JDWP::ObjectId array_id, int offset, int count,
return JDWP::ERR_NONE;
}
-template <typename T> void CopyArrayData(mirror::Array* a, JDWP::Request& src, int offset, int count) {
+template <typename T>
+static void CopyArrayData(mirror::Array* a, JDWP::Request& src, int offset, int count)
+ NO_THREAD_SAFETY_ANALYSIS {
+ // TODO: fix when annotalysis correctly handles non-member functions.
DCHECK(a->GetClass()->IsPrimitiveArray());
- T* dst = &(reinterpret_cast<T*>(a->GetRawData(sizeof(T)))[offset * sizeof(T)]);
+ T* dst = reinterpret_cast<T*>(a->GetRawData(sizeof(T), offset));
for (int i = 0; i < count; ++i) {
*dst++ = src.ReadValue(sizeof(T));
}
@@ -1926,7 +1929,7 @@ JDWP::JdwpError Dbg::GetThreadFrames(JDWP::ObjectId thread_id, size_t start_fram
JDWP::FrameId frame_id(GetFrameId());
JDWP::JdwpLocation location;
SetLocation(location, GetMethod(), GetDexPc());
- VLOG(jdwp) << StringPrintf(" Frame %3zd: id=%3lld ", depth_, frame_id) << location;
+ VLOG(jdwp) << StringPrintf(" Frame %3zd: id=%3" PRIu64 " ", depth_, frame_id) << location;
expandBufAdd8BE(buf_, frame_id);
expandBufAddLocation(buf_, location);
}
@@ -2283,7 +2286,7 @@ void Dbg::SetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, int sl
visitor.WalkStack();
}
-void Dbg::PostLocationEvent(const mirror::ArtMethod* m, int dex_pc, mirror::Object* this_object,
+void Dbg::PostLocationEvent(mirror::ArtMethod* m, int dex_pc, mirror::Object* this_object,
int event_flags, const JValue* return_value) {
mirror::Class* c = m->GetDeclaringClass();
@@ -2338,7 +2341,7 @@ void Dbg::PostClassPrepare(mirror::Class* c) {
}
void Dbg::UpdateDebugger(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* m, uint32_t dex_pc) {
+ mirror::ArtMethod* m, uint32_t dex_pc) {
if (!IsDebuggerActive() || dex_pc == static_cast<uint32_t>(-2) /* fake method exit */) {
return;
}
@@ -2630,7 +2633,7 @@ JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize
if (!m->IsRuntimeMethod()) {
++single_step_control_->stack_depth;
if (single_step_control_->method == NULL) {
- const mirror::DexCache* dex_cache = m->GetDeclaringClass()->GetDexCache();
+ mirror::DexCache* dex_cache = m->GetDeclaringClass()->GetDexCache();
single_step_control_->method = m;
*line_number_ = -1;
if (dex_cache != NULL) {
@@ -2699,7 +2702,7 @@ JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize
uint32_t last_pc;
};
single_step_control->dex_pcs.clear();
- const mirror::ArtMethod* m = single_step_control->method;
+ mirror::ArtMethod* m = single_step_control->method;
if (!m->IsNative()) {
DebugCallbackContext context(single_step_control, line_number);
MethodHelper mh(m);
@@ -3062,7 +3065,7 @@ bool Dbg::DdmHandlePacket(JDWP::Request& request, uint8_t** pReplyBuf, int* pRep
// Run through and find all chunks. [Currently just find the first.]
ScopedByteArrayRO contents(env, dataArray.get());
if (length != request_length) {
- LOG(WARNING) << StringPrintf("bad chunk found (len=%u pktLen=%d)", length, request_length);
+ LOG(WARNING) << StringPrintf("bad chunk found (len=%u pktLen=%zd)", length, request_length);
return false;
}
@@ -3454,7 +3457,7 @@ class HeapChunkContext {
Flush();
}
}
- const mirror::Object* obj = reinterpret_cast<const mirror::Object*>(start);
+ mirror::Object* obj = reinterpret_cast<mirror::Object*>(start);
// Determine the type of this chunk.
// OLD-TODO: if context.merge, see if this chunk is different from the last chunk.
@@ -3497,8 +3500,8 @@ class HeapChunkContext {
*p_++ = length - 1;
}
- uint8_t ExamineObject(const mirror::Object* o, bool is_native_heap)
- SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) {
+ uint8_t ExamineObject(mirror::Object* o, bool is_native_heap)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_) {
if (o == NULL) {
return HPSG_STATE(SOLIDITY_FREE, 0);
}
@@ -3751,7 +3754,7 @@ void Dbg::DumpRecentAllocations() {
<< PrettyClass(record->type);
for (size_t stack_frame = 0; stack_frame < kMaxAllocRecordStackDepth; ++stack_frame) {
- const mirror::ArtMethod* m = record->stack[stack_frame].method;
+ mirror::ArtMethod* m = record->stack[stack_frame].method;
if (m == NULL) {
break;
}
diff --git a/runtime/debugger.h b/runtime/debugger.h
index a3f8b9c..328c9cd 100644
--- a/runtime/debugger.h
+++ b/runtime/debugger.h
@@ -366,7 +366,7 @@ class Dbg {
kMethodEntry = 0x04,
kMethodExit = 0x08,
};
- static void PostLocationEvent(const mirror::ArtMethod* method, int pcOffset,
+ static void PostLocationEvent(mirror::ArtMethod* method, int pcOffset,
mirror::Object* thisPtr, int eventFlags,
const JValue* return_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -382,7 +382,7 @@ class Dbg {
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static void UpdateDebugger(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t new_dex_pc)
+ mirror::ArtMethod* method, uint32_t new_dex_pc)
LOCKS_EXCLUDED(Locks::breakpoint_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/dex_file-inl.h b/runtime/dex_file-inl.h
index 3b2135c..a459308 100644
--- a/runtime/dex_file-inl.h
+++ b/runtime/dex_file-inl.h
@@ -44,7 +44,7 @@ inline const Signature DexFile::GetMethodSignature(const MethodId& method_id) co
inline const DexFile::TryItem* DexFile::GetTryItems(const CodeItem& code_item, uint32_t offset) {
const uint16_t* insns_end_ = &code_item.insns_[code_item.insns_size_in_code_units_];
return reinterpret_cast<const TryItem*>
- (RoundUp(reinterpret_cast<uint32_t>(insns_end_), 4)) + offset;
+ (RoundUp(reinterpret_cast<uintptr_t>(insns_end_), 4)) + offset;
}
static inline bool DexFileStringEquals(const DexFile* df1, uint32_t sidx1,
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index d28d986..eaba7eb 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -621,7 +621,7 @@ const Signature DexFile::CreateSignature(const StringPiece& signature) const {
return Signature(this, *proto_id);
}
-int32_t DexFile::GetLineNumFromPC(const mirror::ArtMethod* method, uint32_t rel_pc) const {
+int32_t DexFile::GetLineNumFromPC(mirror::ArtMethod* method, uint32_t rel_pc) const {
// For native method, lineno should be -2 to indicate it is native. Note that
// "line number == -2" is how libcore tells from StackTraceElement.
if (method->GetCodeItemOffset() == 0) {
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index bc2bfde..46df455 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -794,7 +794,7 @@ class DexFile {
// Returns -2 for native methods (as expected in exception traces).
//
// This is used by runtime; therefore use art::Method not art::DexFile::Method.
- int32_t GetLineNumFromPC(const mirror::ArtMethod* method, uint32_t rel_pc) const
+ int32_t GetLineNumFromPC(mirror::ArtMethod* method, uint32_t rel_pc) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void DecodeDebugInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx,
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index 2f7c38a..261c217 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -646,7 +646,8 @@ bool ElfFile::Load(bool executable, std::string* error_msg) {
reservation_name += file_->GetPath();
std::string error_msg;
UniquePtr<MemMap> reserve(MemMap::MapAnonymous(reservation_name.c_str(),
- NULL, GetLoadedSize(), PROT_NONE, &error_msg));
+ NULL, GetLoadedSize(), PROT_NONE, false,
+ &error_msg));
CHECK(reserve.get() != NULL) << file_->GetPath() << ": " << error_msg;
base_address_ = reserve->Begin();
segments_.push_back(reserve.release());
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index f478366..20532f4 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -282,7 +282,7 @@ enum FindFieldType {
};
template<FindFieldType type, bool access_check>
-static inline mirror::ArtField* FindFieldFromCode(uint32_t field_idx, const mirror::ArtMethod* referrer,
+static inline mirror::ArtField* FindFieldFromCode(uint32_t field_idx, mirror::ArtMethod* referrer,
Thread* self, size_t expected_size) {
bool is_primitive;
bool is_set;
@@ -321,8 +321,7 @@ static inline mirror::ArtField* FindFieldFromCode(uint32_t field_idx, const mirr
return nullptr; // Failure.
} else {
FieldHelper fh(resolved_field);
- if (UNLIKELY(fh.IsPrimitiveType() != is_primitive ||
- fh.FieldSize() != expected_size)) {
+ if (UNLIKELY(fh.IsPrimitiveType() != is_primitive || fh.FieldSize() != expected_size)) {
ThrowLocation throw_location = self->GetCurrentLocationForThrow();
DCHECK(throw_location.GetMethod() == referrer);
self->ThrowNewExceptionF(throw_location, "Ljava/lang/NoSuchFieldError;",
@@ -358,7 +357,7 @@ static inline mirror::ArtField* FindFieldFromCode(uint32_t field_idx, const mirr
#define EXPLICIT_FIND_FIELD_FROM_CODE_TEMPLATE_DECL(_type, _access_check) \
template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE \
mirror::ArtField* FindFieldFromCode<_type, _access_check>(uint32_t field_idx, \
- const mirror::ArtMethod* referrer, \
+ mirror::ArtMethod* referrer, \
Thread* self, size_t expected_size) \
#define EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(_type) \
@@ -496,7 +495,7 @@ EXPLICIT_FIND_METHOD_FROM_CODE_TYPED_TEMPLATE_DECL(kInterface);
// Fast path field resolution that can't initialize classes or throw exceptions.
static inline mirror::ArtField* FindFieldFast(uint32_t field_idx,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
FindFieldType type, size_t expected_size)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* resolved_field =
@@ -552,7 +551,7 @@ static inline mirror::ArtField* FindFieldFast(uint32_t field_idx,
// Fast path method resolution that can't throw exceptions.
static inline mirror::ArtMethod* FindMethodFast(uint32_t method_idx,
mirror::Object* this_object,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
bool access_check, InvokeType type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
bool is_direct = type == kStatic || type == kDirect;
@@ -593,7 +592,7 @@ static inline mirror::ArtMethod* FindMethodFast(uint32_t method_idx,
}
static inline mirror::Class* ResolveVerifyAndClinit(uint32_t type_idx,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
Thread* self, bool can_run_clinit,
bool verify_access)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -630,7 +629,7 @@ static inline mirror::Class* ResolveVerifyAndClinit(uint32_t type_idx,
extern void ThrowStackOverflowError(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-static inline mirror::String* ResolveStringFromCode(const mirror::ArtMethod* referrer,
+static inline mirror::String* ResolveStringFromCode(mirror::ArtMethod* referrer,
uint32_t string_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
@@ -719,21 +718,21 @@ static inline const void* GetPortableToInterpreterBridge() {
return reinterpret_cast<void*>(art_portable_to_interpreter_bridge);
}
+static inline const void* GetPortableToQuickBridge() {
+ // TODO: portable to quick bridge. Bug: 8196384
+ return GetPortableToInterpreterBridge();
+}
+
extern "C" void art_quick_to_interpreter_bridge(mirror::ArtMethod*);
static inline const void* GetQuickToInterpreterBridge() {
return reinterpret_cast<void*>(art_quick_to_interpreter_bridge);
}
-// Return address of interpreter stub.
-static inline const void* GetCompiledCodeToInterpreterBridge() {
-#if defined(ART_USE_PORTABLE_COMPILER)
- return GetPortableToInterpreterBridge();
-#else
+static inline const void* GetQuickToPortableBridge() {
+ // TODO: quick to portable bridge. Bug: 8196384
return GetQuickToInterpreterBridge();
-#endif
}
-
static inline const void* GetPortableResolutionTrampoline(ClassLinker* class_linker) {
return class_linker->GetPortableResolutionTrampoline();
}
@@ -742,15 +741,6 @@ static inline const void* GetQuickResolutionTrampoline(ClassLinker* class_linker
return class_linker->GetQuickResolutionTrampoline();
}
-// Return address of resolution trampoline stub for defined compiler.
-static inline const void* GetResolutionTrampoline(ClassLinker* class_linker) {
-#if defined(ART_USE_PORTABLE_COMPILER)
- return GetPortableResolutionTrampoline(class_linker);
-#else
- return GetQuickResolutionTrampoline(class_linker);
-#endif
-}
-
static inline const void* GetPortableImtConflictTrampoline(ClassLinker* class_linker) {
return class_linker->GetPortableImtConflictTrampoline();
}
@@ -759,15 +749,6 @@ static inline const void* GetQuickImtConflictTrampoline(ClassLinker* class_linke
return class_linker->GetQuickImtConflictTrampoline();
}
-// Return address of imt conflict trampoline stub for defined compiler.
-static inline const void* GetImtConflictTrampoline(ClassLinker* class_linker) {
-#if defined(ART_USE_PORTABLE_COMPILER)
- return GetPortableImtConflictTrampoline(class_linker);
-#else
- return GetQuickImtConflictTrampoline(class_linker);
-#endif
-}
-
extern "C" void art_portable_proxy_invoke_handler();
static inline const void* GetPortableProxyInvokeHandler() {
return reinterpret_cast<void*>(art_portable_proxy_invoke_handler);
@@ -778,14 +759,6 @@ static inline const void* GetQuickProxyInvokeHandler() {
return reinterpret_cast<void*>(art_quick_proxy_invoke_handler);
}
-static inline const void* GetProxyInvokeHandler() {
-#if defined(ART_USE_PORTABLE_COMPILER)
- return GetPortableProxyInvokeHandler();
-#else
- return GetQuickProxyInvokeHandler();
-#endif
-}
-
extern "C" void* art_jni_dlsym_lookup_stub(JNIEnv*, jobject);
static inline void* GetJniDlsymLookupStub() {
return reinterpret_cast<void*>(art_jni_dlsym_lookup_stub);
diff --git a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
index 0df00c2..8a2ce51 100644
--- a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
+++ b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
@@ -45,15 +45,15 @@ extern "C" void artInterpreterToCompiledCodeBridge(Thread* self, MethodHelper& m
}
}
uint16_t arg_offset = (code_item == NULL) ? 0 : code_item->registers_size_ - code_item->ins_size_;
-#if defined(ART_USE_PORTABLE_COMPILER)
- ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
- arg_array.BuildArgArrayFromFrame(shadow_frame, arg_offset);
- method->Invoke(self, arg_array.GetArray(), arg_array.GetNumBytes(), result, mh.GetShorty()[0]);
-#else
- method->Invoke(self, shadow_frame->GetVRegArgs(arg_offset),
- (shadow_frame->NumberOfVRegs() - arg_offset) * sizeof(uint32_t),
- result, mh.GetShorty()[0]);
-#endif
+ if (kUsePortableCompiler) {
+ ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
+ arg_array.BuildArgArrayFromFrame(shadow_frame, arg_offset);
+ method->Invoke(self, arg_array.GetArray(), arg_array.GetNumBytes(), result, mh.GetShorty()[0]);
+ } else {
+ method->Invoke(self, shadow_frame->GetVRegArgs(arg_offset),
+ (shadow_frame->NumberOfVRegs() - arg_offset) * sizeof(uint32_t),
+ result, mh.GetShorty()[0]);
+ }
}
} // namespace art
diff --git a/runtime/entrypoints/portable/portable_cast_entrypoints.cc b/runtime/entrypoints/portable/portable_cast_entrypoints.cc
index d343c5d..a553a22 100644
--- a/runtime/entrypoints/portable/portable_cast_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_cast_entrypoints.cc
@@ -20,16 +20,16 @@
namespace art {
-extern "C" int32_t art_portable_is_assignable_from_code(const mirror::Class* dest_type,
- const mirror::Class* src_type)
+extern "C" int32_t art_portable_is_assignable_from_code(mirror::Class* dest_type,
+ mirror::Class* src_type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(dest_type != NULL);
DCHECK(src_type != NULL);
return dest_type->IsAssignableFrom(src_type) ? 1 : 0;
}
-extern "C" void art_portable_check_cast_from_code(const mirror::Class* dest_type,
- const mirror::Class* src_type)
+extern "C" void art_portable_check_cast_from_code(mirror::Class* dest_type,
+ mirror::Class* src_type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(dest_type->IsClass()) << PrettyClass(dest_type);
DCHECK(src_type->IsClass()) << PrettyClass(src_type);
@@ -38,8 +38,8 @@ extern "C" void art_portable_check_cast_from_code(const mirror::Class* dest_type
}
}
-extern "C" void art_portable_check_put_array_element_from_code(const mirror::Object* element,
- const mirror::Object* array)
+extern "C" void art_portable_check_put_array_element_from_code(mirror::Object* element,
+ mirror::Object* array)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (element == NULL) {
return;
diff --git a/runtime/entrypoints/portable/portable_field_entrypoints.cc b/runtime/entrypoints/portable/portable_field_entrypoints.cc
index 095e99e..0b54b9c 100644
--- a/runtime/entrypoints/portable/portable_field_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_field_entrypoints.cc
@@ -65,13 +65,13 @@ extern "C" int32_t art_portable_set_obj_static_from_code(uint32_t field_idx,
mirror::Object* new_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticObjectWrite,
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
field->SetObj(field->GetDeclaringClass(), new_value);
return 0;
}
field = FindFieldFromCode<StaticObjectWrite, true>(field_idx, referrer, Thread::Current(),
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
field->SetObj(field->GetDeclaringClass(), new_value);
return 0;
@@ -113,12 +113,12 @@ extern "C" mirror::Object* art_portable_get_obj_static_from_code(uint32_t field_
mirror::ArtMethod* referrer)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticObjectRead,
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
return field->GetObj(field->GetDeclaringClass());
}
field = FindFieldFromCode<StaticObjectRead, true>(field_idx, referrer, Thread::Current(),
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
return field->GetObj(field->GetDeclaringClass());
}
@@ -167,13 +167,13 @@ extern "C" int32_t art_portable_set_obj_instance_from_code(uint32_t field_idx,
mirror::Object* new_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite,
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
field->SetObj(obj, new_value);
return 0;
}
field = FindFieldFromCode<InstanceObjectWrite, true>(field_idx, referrer, Thread::Current(),
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
field->SetObj(obj, new_value);
return 0;
@@ -218,12 +218,12 @@ extern "C" mirror::Object* art_portable_get_obj_instance_from_code(uint32_t fiel
mirror::Object* obj)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectRead,
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
return field->GetObj(obj);
}
field = FindFieldFromCode<InstanceObjectRead, true>(field_idx, referrer, Thread::Current(),
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
return field->GetObj(obj);
}
diff --git a/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc b/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc
index 8cf4eed..1005d0e 100644
--- a/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc
@@ -44,7 +44,7 @@ extern "C" void art_portable_fill_array_data_from_code(mirror::ArtMethod* method
return; // Error
}
uint32_t size_in_bytes = payload->element_count * payload->element_width;
- memcpy(array->GetRawData(payload->element_width), payload->data, size_in_bytes);
+ memcpy(array->GetRawData(payload->element_width, 0), payload->data, size_in_bytes);
}
} // namespace art
diff --git a/runtime/entrypoints/portable/portable_invoke_entrypoints.cc b/runtime/entrypoints/portable/portable_invoke_entrypoints.cc
index 47ccbb1..d34b097 100644
--- a/runtime/entrypoints/portable/portable_invoke_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_invoke_entrypoints.cc
@@ -34,7 +34,7 @@ mirror::ArtMethod* FindMethodHelper(uint32_t method_idx, mirror::Object* this_ob
}
}
DCHECK(!thread->IsExceptionPending());
- const void* code = method->GetEntryPointFromCompiledCode();
+ const void* code = method->GetEntryPointFromPortableCompiledCode();
// When we return, the caller will branch to this address, so it had better not be 0!
if (UNLIKELY(code == NULL)) {
diff --git a/runtime/entrypoints/portable/portable_throw_entrypoints.cc b/runtime/entrypoints/portable/portable_throw_entrypoints.cc
index 2a0df9b..1fdb832 100644
--- a/runtime/entrypoints/portable/portable_throw_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_throw_entrypoints.cc
@@ -75,7 +75,7 @@ extern "C" int32_t art_portable_find_catch_block_from_code(mirror::ArtMethod* cu
ThrowLocation throw_location;
mirror::Throwable* exception = self->GetException(&throw_location);
// Check for special deoptimization exception.
- if (UNLIKELY(reinterpret_cast<int32_t>(exception) == -1)) {
+ if (UNLIKELY(reinterpret_cast<intptr_t>(exception) == -1)) {
return -1;
}
mirror::Class* exception_type = exception->GetClass();
diff --git a/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc b/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc
index 2162dcc..55fd301 100644
--- a/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc
@@ -47,6 +47,11 @@ class PortableArgumentVisitor {
#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 0
#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 0
#define PORTABLE_STACK_ARG_SKIP 4
+#elif defined(__x86_64__)
+// TODO: implement and check these.
+#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 16
+#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 96
+#define PORTABLE_STACK_ARG_SKIP 0
#else
#error "Unsupported architecture"
#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 0
@@ -387,43 +392,42 @@ extern "C" const void* artPortableResolutionTrampoline(mirror::ArtMethod* called
// Incompatible class change should have been handled in resolve method.
CHECK(!called->CheckIncompatibleClassChange(invoke_type));
}
- const void* code = NULL;
+ const void* code = nullptr;
if (LIKELY(!thread->IsExceptionPending())) {
// Ensure that the called method's class is initialized.
SirtRef<mirror::Class> called_class(thread, called->GetDeclaringClass());
linker->EnsureInitialized(called_class, true, true);
if (LIKELY(called_class->IsInitialized())) {
- code = called->GetEntryPointFromCompiledCode();
+ code = called->GetEntryPointFromPortableCompiledCode();
// TODO: remove this after we solve the link issue.
- { // for lazy link.
- if (code == NULL) {
- code = linker->GetOatCodeFor(called);
- }
+ if (code == nullptr) {
+ bool have_portable_code;
+ code = linker->GetPortableOatCodeFor(called, &have_portable_code);
}
} else if (called_class->IsInitializing()) {
if (invoke_type == kStatic) {
// Class is still initializing, go to oat and grab code (trampoline must be left in place
// until class is initialized to stop races between threads).
- code = linker->GetOatCodeFor(called);
+ bool have_portable_code;
+ code = linker->GetPortableOatCodeFor(called, &have_portable_code);
} else {
// No trampoline for non-static methods.
- code = called->GetEntryPointFromCompiledCode();
+ code = called->GetEntryPointFromPortableCompiledCode();
// TODO: remove this after we solve the link issue.
- { // for lazy link.
- if (code == NULL) {
- code = linker->GetOatCodeFor(called);
- }
+ if (code == nullptr) {
+ bool have_portable_code;
+ code = linker->GetPortableOatCodeFor(called, &have_portable_code);
}
}
} else {
DCHECK(called_class->IsErroneous());
}
}
- if (LIKELY(code != NULL)) {
+ if (LIKELY(code != nullptr)) {
// Expect class to at least be initializing.
DCHECK(called->GetDeclaringClass()->IsInitializing());
// Don't want infinite recursion.
- DCHECK(code != GetResolutionTrampoline(linker));
+ DCHECK(code != GetPortableResolutionTrampoline(linker));
// Set up entry into main method
*called_addr = called;
}
diff --git a/runtime/entrypoints/quick/quick_cast_entrypoints.cc b/runtime/entrypoints/quick/quick_cast_entrypoints.cc
index ae53d6c..a6ab69b 100644
--- a/runtime/entrypoints/quick/quick_cast_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_cast_entrypoints.cc
@@ -20,8 +20,7 @@
namespace art {
// Assignable test for code, won't throw. Null and equality tests already performed
-extern "C" uint32_t artIsAssignableFromCode(const mirror::Class* klass,
- const mirror::Class* ref_class)
+extern "C" uint32_t artIsAssignableFromCode(mirror::Class* klass, mirror::Class* ref_class)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(klass != NULL);
DCHECK(ref_class != NULL);
diff --git a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
index 003047a..ab428a5 100644
--- a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
@@ -26,7 +26,7 @@
namespace art {
extern "C" mirror::Class* artInitializeStaticStorageFromCode(uint32_t type_idx,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
Thread* self,
mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -38,7 +38,7 @@ extern "C" mirror::Class* artInitializeStaticStorageFromCode(uint32_t type_idx,
}
extern "C" mirror::Class* artInitializeTypeFromCode(uint32_t type_idx,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
Thread* self, mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Called when method->dex_cache_resolved_types_[] misses.
@@ -47,7 +47,7 @@ extern "C" mirror::Class* artInitializeTypeFromCode(uint32_t type_idx,
}
extern "C" mirror::Class* artInitializeTypeAndVerifyAccessFromCode(uint32_t type_idx,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
Thread* self,
mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
diff --git a/runtime/entrypoints/quick/quick_field_entrypoints.cc b/runtime/entrypoints/quick/quick_field_entrypoints.cc
index 0a533bd..93ff7aa 100644
--- a/runtime/entrypoints/quick/quick_field_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_field_entrypoints.cc
@@ -26,7 +26,7 @@
namespace art {
extern "C" uint32_t artGet32StaticFromCode(uint32_t field_idx,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
Thread* self, mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead,
@@ -43,7 +43,7 @@ extern "C" uint32_t artGet32StaticFromCode(uint32_t field_idx,
}
extern "C" uint64_t artGet64StaticFromCode(uint32_t field_idx,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
Thread* self, mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead,
@@ -60,17 +60,17 @@ extern "C" uint64_t artGet64StaticFromCode(uint32_t field_idx,
}
extern "C" mirror::Object* artGetObjStaticFromCode(uint32_t field_idx,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
Thread* self, mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticObjectRead,
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
return field->GetObj(field->GetDeclaringClass());
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode<StaticObjectRead, true>(field_idx, referrer, self,
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
return field->GetObj(field->GetDeclaringClass());
}
@@ -78,7 +78,7 @@ extern "C" mirror::Object* artGetObjStaticFromCode(uint32_t field_idx,
}
extern "C" uint32_t artGet32InstanceFromCode(uint32_t field_idx, mirror::Object* obj,
- const mirror::ArtMethod* referrer, Thread* self,
+ mirror::ArtMethod* referrer, Thread* self,
mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead,
@@ -101,7 +101,7 @@ extern "C" uint32_t artGet32InstanceFromCode(uint32_t field_idx, mirror::Object*
}
extern "C" uint64_t artGet64InstanceFromCode(uint32_t field_idx, mirror::Object* obj,
- const mirror::ArtMethod* referrer, Thread* self,
+ mirror::ArtMethod* referrer, Thread* self,
mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead,
@@ -124,18 +124,18 @@ extern "C" uint64_t artGet64InstanceFromCode(uint32_t field_idx, mirror::Object*
}
extern "C" mirror::Object* artGetObjInstanceFromCode(uint32_t field_idx, mirror::Object* obj,
- const mirror::ArtMethod* referrer,
+ mirror::ArtMethod* referrer,
Thread* self,
mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectRead,
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL && obj != NULL)) {
return field->GetObj(obj);
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode<InstanceObjectRead, true>(field_idx, referrer, self,
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
if (UNLIKELY(obj == NULL)) {
ThrowLocation throw_location = self->GetCurrentLocationForThrow();
@@ -148,7 +148,7 @@ extern "C" mirror::Object* artGetObjInstanceFromCode(uint32_t field_idx, mirror:
}
extern "C" int artSet32StaticFromCode(uint32_t field_idx, uint32_t new_value,
- const mirror::ArtMethod* referrer, Thread* self,
+ mirror::ArtMethod* referrer, Thread* self,
mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite,
@@ -166,7 +166,7 @@ extern "C" int artSet32StaticFromCode(uint32_t field_idx, uint32_t new_value,
return -1; // failure
}
-extern "C" int artSet64StaticFromCode(uint32_t field_idx, const mirror::ArtMethod* referrer,
+extern "C" int artSet64StaticFromCode(uint32_t field_idx, mirror::ArtMethod* referrer,
uint64_t new_value, Thread* self, mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite,
@@ -185,11 +185,11 @@ extern "C" int artSet64StaticFromCode(uint32_t field_idx, const mirror::ArtMetho
}
extern "C" int artSetObjStaticFromCode(uint32_t field_idx, mirror::Object* new_value,
- const mirror::ArtMethod* referrer, Thread* self,
+ mirror::ArtMethod* referrer, Thread* self,
mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticObjectWrite,
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
if (LIKELY(!FieldHelper(field).IsPrimitiveType())) {
field->SetObj(field->GetDeclaringClass(), new_value);
@@ -198,7 +198,7 @@ extern "C" int artSetObjStaticFromCode(uint32_t field_idx, mirror::Object* new_v
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode<StaticObjectWrite, true>(field_idx, referrer, self,
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
field->SetObj(field->GetDeclaringClass(), new_value);
return 0; // success
@@ -207,7 +207,7 @@ extern "C" int artSetObjStaticFromCode(uint32_t field_idx, mirror::Object* new_v
}
extern "C" int artSet32InstanceFromCode(uint32_t field_idx, mirror::Object* obj, uint32_t new_value,
- const mirror::ArtMethod* referrer, Thread* self,
+ mirror::ArtMethod* referrer, Thread* self,
mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite,
@@ -261,18 +261,18 @@ extern "C" int artSet64InstanceFromCode(uint32_t field_idx, mirror::Object* obj,
extern "C" int artSetObjInstanceFromCode(uint32_t field_idx, mirror::Object* obj,
mirror::Object* new_value,
- const mirror::ArtMethod* referrer, Thread* self,
+ mirror::ArtMethod* referrer, Thread* self,
mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite,
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL && obj != NULL)) {
field->SetObj(obj, new_value);
return 0; // success
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode<InstanceObjectWrite, true>(field_idx, referrer, self,
- sizeof(mirror::Object*));
+ sizeof(mirror::HeapReference<mirror::Object>));
if (LIKELY(field != NULL)) {
if (UNLIKELY(obj == NULL)) {
ThrowLocation throw_location = self->GetCurrentLocationForThrow();
diff --git a/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc b/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
index ca0c92e..8dac750 100644
--- a/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
@@ -56,7 +56,7 @@ extern "C" int artHandleFillArrayDataFromCode(mirror::Array* array,
return -1; // Error
}
uint32_t size_in_bytes = payload->element_count * payload->element_width;
- memcpy(array->GetRawData(payload->element_width), payload->data, size_in_bytes);
+ memcpy(array->GetRawData(payload->element_width, 0), payload->data, size_in_bytes);
return 0; // Success
}
diff --git a/runtime/entrypoints/quick/quick_invoke_entrypoints.cc b/runtime/entrypoints/quick/quick_invoke_entrypoints.cc
index 5a1b3e8..c081768 100644
--- a/runtime/entrypoints/quick/quick_invoke_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_invoke_entrypoints.cc
@@ -124,21 +124,23 @@ extern "C" uint64_t artInvokeInterfaceTrampoline(mirror::ArtMethod* interface_me
return 0; // Failure.
}
}
- const void* code = method->GetEntryPointFromCompiledCode();
+ const void* code = method->GetEntryPointFromQuickCompiledCode();
-#ifndef NDEBUG
// When we return, the caller will branch to this address, so it had better not be 0!
- if (UNLIKELY(code == NULL)) {
+ if (kIsDebugBuild && UNLIKELY(code == nullptr)) {
MethodHelper mh(method);
LOG(FATAL) << "Code was NULL in method: " << PrettyMethod(method)
<< " location: " << mh.GetDexFile().GetLocation();
}
-#endif
-
+#ifdef __LP64__
+ UNIMPLEMENTED(FATAL);
+ return 0;
+#else
uint32_t method_uint = reinterpret_cast<uint32_t>(method);
uint64_t code_uint = reinterpret_cast<uint32_t>(code);
uint64_t result = ((code_uint << 32) | method_uint);
return result;
+#endif
}
template<InvokeType type, bool access_check>
@@ -156,21 +158,23 @@ uint64_t artInvokeCommon(uint32_t method_idx, mirror::Object* this_object,
}
}
DCHECK(!self->IsExceptionPending());
- const void* code = method->GetEntryPointFromCompiledCode();
+ const void* code = method->GetEntryPointFromQuickCompiledCode();
-#ifndef NDEBUG
// When we return, the caller will branch to this address, so it had better not be 0!
- if (UNLIKELY(code == NULL)) {
+ if (kIsDebugBuild && UNLIKELY(code == NULL)) {
MethodHelper mh(method);
LOG(FATAL) << "Code was NULL in method: " << PrettyMethod(method)
<< " location: " << mh.GetDexFile().GetLocation();
}
-#endif
-
+#ifdef __LP64__
+ UNIMPLEMENTED(FATAL);
+ return 0;
+#else
uint32_t method_uint = reinterpret_cast<uint32_t>(method);
uint64_t code_uint = reinterpret_cast<uint32_t>(code);
uint64_t result = ((code_uint << 32) | method_uint);
return result;
+#endif
}
// Explicit template declarations of artInvokeCommon for all invoke types.
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index b589384..9f30190 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -97,6 +97,12 @@ class QuickArgumentVisitor {
#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__LR_OFFSET 28
#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 32
#define QUICK_STACK_ARG_SKIP 16
+#elif defined(__x86_64__)
+// TODO: implement and check these.
+#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 8
+#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__LR_OFFSET 56
+#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 64
+#define QUICK_STACK_ARG_SKIP 32
#else
#error "Unsupported architecture"
#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 0
@@ -567,15 +573,15 @@ extern "C" const void* artQuickResolutionTrampoline(mirror::ArtMethod* called,
SirtRef<mirror::Class> called_class(soa.Self(), called->GetDeclaringClass());
linker->EnsureInitialized(called_class, true, true);
if (LIKELY(called_class->IsInitialized())) {
- code = called->GetEntryPointFromCompiledCode();
+ code = called->GetEntryPointFromQuickCompiledCode();
} else if (called_class->IsInitializing()) {
if (invoke_type == kStatic) {
// Class is still initializing, go to oat and grab code (trampoline must be left in place
// until class is initialized to stop races between threads).
- code = linker->GetOatCodeFor(called);
+ code = linker->GetQuickOatCodeFor(called);
} else {
// No trampoline for non-static methods.
- code = called->GetEntryPointFromCompiledCode();
+ code = called->GetEntryPointFromQuickCompiledCode();
}
} else {
DCHECK(called_class->IsErroneous());
diff --git a/runtime/exception_test.cc b/runtime/exception_test.cc
index 978faeb..f7b621f 100644
--- a/runtime/exception_test.cc
+++ b/runtime/exception_test.cc
@@ -76,7 +76,7 @@ class ExceptionTest : public CommonTest {
method_f_ = my_klass_->FindVirtualMethod("f", "()I");
ASSERT_TRUE(method_f_ != NULL);
method_f_->SetFrameSizeInBytes(kStackAlignment);
- method_f_->SetEntryPointFromCompiledCode(CompiledMethod::CodePointer(&fake_code_[sizeof(code_size)], kThumb2));
+ method_f_->SetEntryPointFromQuickCompiledCode(CompiledMethod::CodePointer(&fake_code_[sizeof(code_size)], kThumb2));
method_f_->SetMappingTable(&fake_mapping_data_.GetData()[0]);
method_f_->SetVmapTable(&fake_vmap_table_data_.GetData()[0]);
method_f_->SetNativeGcMap(&fake_gc_map_[0]);
@@ -84,7 +84,7 @@ class ExceptionTest : public CommonTest {
method_g_ = my_klass_->FindVirtualMethod("g", "(I)V");
ASSERT_TRUE(method_g_ != NULL);
method_g_->SetFrameSizeInBytes(kStackAlignment);
- method_g_->SetEntryPointFromCompiledCode(CompiledMethod::CodePointer(&fake_code_[sizeof(code_size)], kThumb2));
+ method_g_->SetEntryPointFromQuickCompiledCode(CompiledMethod::CodePointer(&fake_code_[sizeof(code_size)], kThumb2));
method_g_->SetMappingTable(&fake_mapping_data_.GetData()[0]);
method_g_->SetVmapTable(&fake_vmap_table_data_.GetData()[0]);
method_g_->SetNativeGcMap(&fake_gc_map_[0]);
@@ -105,6 +105,7 @@ class ExceptionTest : public CommonTest {
};
TEST_F(ExceptionTest, FindCatchHandler) {
+ ScopedObjectAccess soa(Thread::Current());
const DexFile::CodeItem* code_item = dex_->GetCodeItem(method_f_->GetCodeItemOffset());
ASSERT_TRUE(code_item != NULL);
@@ -151,51 +152,51 @@ TEST_F(ExceptionTest, StackTraceElement) {
ASSERT_EQ(kStackAlignment, 16U);
ASSERT_EQ(sizeof(uintptr_t), sizeof(uint32_t));
-#if !defined(ART_USE_PORTABLE_COMPILER)
- // Create two fake stack frames with mapping data created in SetUp. We map offset 3 in the code
- // to dex pc 3.
- const uint32_t dex_pc = 3;
-
- // Create/push fake 16byte stack frame for method g
- fake_stack.push_back(reinterpret_cast<uintptr_t>(method_g_));
- fake_stack.push_back(0);
- fake_stack.push_back(0);
- fake_stack.push_back(method_f_->ToNativePc(dex_pc)); // return pc
-
- // Create/push fake 16byte stack frame for method f
- fake_stack.push_back(reinterpret_cast<uintptr_t>(method_f_));
- fake_stack.push_back(0);
- fake_stack.push_back(0);
- fake_stack.push_back(0xEBAD6070); // return pc
-
- // Pull Method* of NULL to terminate the trace
- fake_stack.push_back(0);
-
- // Push null values which will become null incoming arguments.
- fake_stack.push_back(0);
- fake_stack.push_back(0);
- fake_stack.push_back(0);
-
- // Set up thread to appear as if we called out of method_g_ at pc dex 3
- thread->SetTopOfStack(&fake_stack[0], method_g_->ToNativePc(dex_pc)); // return pc
-#else
- // Create/push fake 20-byte shadow frame for method g
- fake_stack.push_back(0);
- fake_stack.push_back(0);
- fake_stack.push_back(reinterpret_cast<uintptr_t>(method_g_));
- fake_stack.push_back(3);
- fake_stack.push_back(0);
-
- // Create/push fake 20-byte shadow frame for method f
- fake_stack.push_back(0);
- fake_stack.push_back(0);
- fake_stack.push_back(reinterpret_cast<uintptr_t>(method_f_));
- fake_stack.push_back(3);
- fake_stack.push_back(0);
-
- thread->PushShadowFrame(reinterpret_cast<ShadowFrame*>(&fake_stack[5]));
- thread->PushShadowFrame(reinterpret_cast<ShadowFrame*>(&fake_stack[0]));
-#endif
+ if (!kUsePortableCompiler) {
+ // Create two fake stack frames with mapping data created in SetUp. We map offset 3 in the code
+ // to dex pc 3.
+ const uint32_t dex_pc = 3;
+
+ // Create/push fake 16byte stack frame for method g
+ fake_stack.push_back(reinterpret_cast<uintptr_t>(method_g_));
+ fake_stack.push_back(0);
+ fake_stack.push_back(0);
+ fake_stack.push_back(method_f_->ToNativePc(dex_pc)); // return pc
+
+ // Create/push fake 16byte stack frame for method f
+ fake_stack.push_back(reinterpret_cast<uintptr_t>(method_f_));
+ fake_stack.push_back(0);
+ fake_stack.push_back(0);
+ fake_stack.push_back(0xEBAD6070); // return pc
+
+ // Pull Method* of NULL to terminate the trace
+ fake_stack.push_back(0);
+
+ // Push null values which will become null incoming arguments.
+ fake_stack.push_back(0);
+ fake_stack.push_back(0);
+ fake_stack.push_back(0);
+
+ // Set up thread to appear as if we called out of method_g_ at pc dex 3
+ thread->SetTopOfStack(&fake_stack[0], method_g_->ToNativePc(dex_pc)); // return pc
+ } else {
+ // Create/push fake 20-byte shadow frame for method g
+ fake_stack.push_back(0);
+ fake_stack.push_back(0);
+ fake_stack.push_back(reinterpret_cast<uintptr_t>(method_g_));
+ fake_stack.push_back(3);
+ fake_stack.push_back(0);
+
+ // Create/push fake 20-byte shadow frame for method f
+ fake_stack.push_back(0);
+ fake_stack.push_back(0);
+ fake_stack.push_back(reinterpret_cast<uintptr_t>(method_f_));
+ fake_stack.push_back(3);
+ fake_stack.push_back(0);
+
+ thread->PushShadowFrame(reinterpret_cast<ShadowFrame*>(&fake_stack[5]));
+ thread->PushShadowFrame(reinterpret_cast<ShadowFrame*>(&fake_stack[0]));
+ }
jobject internal = thread->CreateInternalStackTrace(soa);
ASSERT_TRUE(internal != NULL);
diff --git a/runtime/gc/accounting/atomic_stack.h b/runtime/gc/accounting/atomic_stack.h
index 02e01b8..ea8f89c 100644
--- a/runtime/gc/accounting/atomic_stack.h
+++ b/runtime/gc/accounting/atomic_stack.h
@@ -19,7 +19,7 @@
#include <string>
-#include "atomic_integer.h"
+#include "atomic.h"
#include "base/logging.h"
#include "base/macros.h"
#include "UniquePtr.h"
@@ -165,7 +165,7 @@ class AtomicStack {
void Init() {
std::string error_msg;
mem_map_.reset(MemMap::MapAnonymous(name_.c_str(), NULL, capacity_ * sizeof(T),
- PROT_READ | PROT_WRITE, &error_msg));
+ PROT_READ | PROT_WRITE, false, &error_msg));
CHECK(mem_map_.get() != NULL) << "couldn't allocate mark stack.\n" << error_msg;
byte* addr = mem_map_->Begin();
CHECK(addr != NULL);
diff --git a/runtime/gc/accounting/card_table.cc b/runtime/gc/accounting/card_table.cc
index e099137..714e6f7 100644
--- a/runtime/gc/accounting/card_table.cc
+++ b/runtime/gc/accounting/card_table.cc
@@ -57,7 +57,7 @@ CardTable* CardTable::Create(const byte* heap_begin, size_t heap_capacity) {
std::string error_msg;
UniquePtr<MemMap> mem_map(MemMap::MapAnonymous("card table", NULL,
capacity + 256, PROT_READ | PROT_WRITE,
- &error_msg));
+ false, &error_msg));
CHECK(mem_map.get() != NULL) << "couldn't allocate card table: " << error_msg;
// All zeros is the correct initial value; all clean. Anonymous mmaps are initialized to zero, we
// don't clear the card table to avoid unnecessary pages being allocated
@@ -72,11 +72,11 @@ CardTable* CardTable::Create(const byte* heap_begin, size_t heap_capacity) {
byte* biased_begin = reinterpret_cast<byte*>(reinterpret_cast<uintptr_t>(cardtable_begin) -
(reinterpret_cast<uintptr_t>(heap_begin) >> kCardShift));
if (((uintptr_t)biased_begin & 0xff) != kCardDirty) {
- int delta = kCardDirty - (reinterpret_cast<int>(biased_begin) & 0xff);
+ int delta = kCardDirty - (reinterpret_cast<uintptr_t>(biased_begin) & 0xff);
offset = delta + (delta < 0 ? 0x100 : 0);
biased_begin += offset;
}
- CHECK_EQ(reinterpret_cast<int>(biased_begin) & 0xff, kCardDirty);
+ CHECK_EQ(reinterpret_cast<uintptr_t>(biased_begin) & 0xff, kCardDirty);
return new CardTable(mem_map.release(), biased_begin, offset);
}
diff --git a/runtime/gc/accounting/mod_union_table.cc b/runtime/gc/accounting/mod_union_table.cc
index 6d9dde7..0225f29 100644
--- a/runtime/gc/accounting/mod_union_table.cc
+++ b/runtime/gc/accounting/mod_union_table.cc
@@ -82,9 +82,9 @@ class ModUnionUpdateObjectReferencesVisitor {
if (ref != nullptr) {
Object* new_ref = visitor_(ref, arg_);
if (new_ref != ref) {
- // Use SetFieldPtr to avoid card mark as an optimization which reduces dirtied pages and
- // improves performance.
- obj->SetFieldPtr(offset, new_ref, true);
+ // Use SetFieldObjectWithoutWriteBarrier to avoid card mark as an optimization which
+ // reduces dirtied pages and improves performance.
+ obj->SetFieldObjectWithoutWriteBarrier(offset, new_ref, true);
}
}
}
@@ -122,9 +122,8 @@ void ModUnionTableReferenceCache::ClearCards() {
class AddToReferenceArrayVisitor {
public:
explicit AddToReferenceArrayVisitor(ModUnionTableReferenceCache* mod_union_table,
- std::vector<Object**>* references)
- : mod_union_table_(mod_union_table),
- references_(references) {
+ std::vector<mirror::HeapReference<Object>*>* references)
+ : mod_union_table_(mod_union_table), references_(references) {
}
// Extra parameters are required since we use this same visitor signature for checking objects.
@@ -133,19 +132,19 @@ class AddToReferenceArrayVisitor {
// Only add the reference if it is non null and fits our criteria.
if (ref != nullptr && mod_union_table_->AddReference(obj, ref)) {
// Push the adddress of the reference.
- references_->push_back(obj->GetFieldObjectAddr(offset));
+ references_->push_back(obj->GetFieldObjectReferenceAddr(offset));
}
}
private:
ModUnionTableReferenceCache* const mod_union_table_;
- std::vector<Object**>* const references_;
+ std::vector<mirror::HeapReference<Object>*>* const references_;
};
class ModUnionReferenceVisitor {
public:
explicit ModUnionReferenceVisitor(ModUnionTableReferenceCache* const mod_union_table,
- std::vector<Object**>* references)
+ std::vector<mirror::HeapReference<Object>*>* references)
: mod_union_table_(mod_union_table),
references_(references) {
}
@@ -160,7 +159,7 @@ class ModUnionReferenceVisitor {
}
private:
ModUnionTableReferenceCache* const mod_union_table_;
- std::vector<Object**>* const references_;
+ std::vector<mirror::HeapReference<Object>*>* const references_;
};
class CheckReferenceVisitor {
@@ -173,7 +172,7 @@ class CheckReferenceVisitor {
// Extra parameters are required since we use this same visitor signature for checking objects.
// TODO: Fixme when anotatalysis works with visitors.
- void operator()(const Object* obj, const Object* ref,
+ void operator()(Object* obj, Object* ref,
const MemberOffset& /* offset */, bool /* is_static */) const
SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
Heap* heap = mod_union_table_->GetHeap();
@@ -219,8 +218,8 @@ class ModUnionCheckReferences {
void ModUnionTableReferenceCache::Verify() {
// Start by checking that everything in the mod union table is marked.
for (const auto& ref_pair : references_) {
- for (Object** ref : ref_pair.second) {
- CHECK(heap_->IsLiveObjectLocked(*ref));
+ for (mirror::HeapReference<Object>* ref : ref_pair.second) {
+ CHECK(heap_->IsLiveObjectLocked(ref->AsMirrorPtr()));
}
}
@@ -231,8 +230,8 @@ void ModUnionTableReferenceCache::Verify() {
const byte* card = ref_pair.first;
if (*card == CardTable::kCardClean) {
std::set<const Object*> reference_set;
- for (Object** obj_ptr : ref_pair.second) {
- reference_set.insert(*obj_ptr);
+ for (mirror::HeapReference<Object>* obj_ptr : ref_pair.second) {
+ reference_set.insert(obj_ptr->AsMirrorPtr());
}
ModUnionCheckReferences visitor(this, reference_set);
uintptr_t start = reinterpret_cast<uintptr_t>(card_table->AddrFromCard(card));
@@ -255,8 +254,8 @@ void ModUnionTableReferenceCache::Dump(std::ostream& os) {
uintptr_t start = reinterpret_cast<uintptr_t>(card_table->AddrFromCard(card_addr));
uintptr_t end = start + CardTable::kCardSize;
os << reinterpret_cast<void*>(start) << "-" << reinterpret_cast<void*>(end) << "->{";
- for (Object** ref : ref_pair.second) {
- os << reinterpret_cast<const void*>(*ref) << ",";
+ for (mirror::HeapReference<Object>* ref : ref_pair.second) {
+ os << reinterpret_cast<const void*>(ref->AsMirrorPtr()) << ",";
}
os << "},";
}
@@ -266,7 +265,7 @@ void ModUnionTableReferenceCache::UpdateAndMarkReferences(RootVisitor visitor, v
Heap* heap = GetHeap();
CardTable* card_table = heap->GetCardTable();
- std::vector<Object**> cards_references;
+ std::vector<mirror::HeapReference<Object>*> cards_references;
ModUnionReferenceVisitor add_visitor(this, &cards_references);
for (const auto& card : cleared_cards_) {
@@ -294,13 +293,13 @@ void ModUnionTableReferenceCache::UpdateAndMarkReferences(RootVisitor visitor, v
cleared_cards_.clear();
size_t count = 0;
for (const auto& ref : references_) {
- for (const auto& obj_ptr : ref.second) {
- Object* obj = *obj_ptr;
+ for (mirror::HeapReference<Object>* obj_ptr : ref.second) {
+ Object* obj = obj_ptr->AsMirrorPtr();
if (obj != nullptr) {
Object* new_obj = visitor(obj, arg);
// Avoid dirtying pages in the image unless necessary.
if (new_obj != obj) {
- *obj_ptr = new_obj;
+ obj_ptr->Assign(new_obj);
}
}
}
diff --git a/runtime/gc/accounting/mod_union_table.h b/runtime/gc/accounting/mod_union_table.h
index 5a99f1b..a89dbd1 100644
--- a/runtime/gc/accounting/mod_union_table.h
+++ b/runtime/gc/accounting/mod_union_table.h
@@ -112,20 +112,23 @@ class ModUnionTableReferenceCache : public ModUnionTable {
// Exclusive lock is required since verify uses SpaceBitmap::VisitMarkedRange and
// VisitMarkedRange can't know if the callback will modify the bitmap or not.
- void Verify() EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
+ void Verify()
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
// Function that tells whether or not to add a reference to the table.
virtual bool AddReference(const mirror::Object* obj, const mirror::Object* ref) = 0;
- void Dump(std::ostream& os);
+ void Dump(std::ostream& os) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
protected:
// Cleared card array, used to update the mod-union table.
ModUnionTable::CardSet cleared_cards_;
// Maps from dirty cards to their corresponding alloc space references.
- SafeMap<const byte*, std::vector<mirror::Object**>, std::less<const byte*>,
- GcAllocator<std::pair<const byte*, std::vector<mirror::Object**> > > > references_;
+ SafeMap<const byte*, std::vector<mirror::HeapReference<mirror::Object>*>, std::less<const byte*>,
+ GcAllocator<std::pair<const byte*, std::vector<mirror::HeapReference<mirror::Object>*> > > >
+ references_;
};
// Card caching implementation. Keeps track of which cards we cleared and only this information.
diff --git a/runtime/gc/accounting/space_bitmap-inl.h b/runtime/gc/accounting/space_bitmap-inl.h
index 01c70fa..d6d1b3e 100644
--- a/runtime/gc/accounting/space_bitmap-inl.h
+++ b/runtime/gc/accounting/space_bitmap-inl.h
@@ -37,9 +37,11 @@ inline bool SpaceBitmap::AtomicTestAndSet(const mirror::Object* obj) {
old_word = *address;
// Fast path: The bit is already set.
if ((old_word & mask) != 0) {
+ DCHECK(Test(obj));
return true;
}
} while (!__sync_bool_compare_and_swap(address, old_word, old_word | mask));
+ DCHECK(Test(obj));
return false;
}
@@ -56,6 +58,15 @@ template <typename Visitor>
void SpaceBitmap::VisitMarkedRange(uintptr_t visit_begin, uintptr_t visit_end,
const Visitor& visitor) const {
DCHECK_LT(visit_begin, visit_end);
+#ifdef __LP64__
+ // TODO: make the optimized code below work in the 64bit case.
+ for (uintptr_t i = visit_begin; i < visit_end; i += kAlignment) {
+ mirror::Object* obj = reinterpret_cast<mirror::Object*>(i);
+ if (Test(obj)) {
+ visitor(obj);
+ }
+ }
+#else
const size_t bit_index_start = (visit_begin - heap_begin_) / kAlignment;
const size_t bit_index_end = (visit_end - heap_begin_ - 1) / kAlignment;
@@ -114,6 +125,7 @@ void SpaceBitmap::VisitMarkedRange(uintptr_t visit_begin, uintptr_t visit_end,
visitor(obj);
edge_word ^= static_cast<size_t>(kWordHighBitMask) >> shift;
}
+#endif
}
inline bool SpaceBitmap::Modify(const mirror::Object* obj, bool do_set) {
@@ -130,6 +142,7 @@ inline bool SpaceBitmap::Modify(const mirror::Object* obj, bool do_set) {
} else {
*address = old_word & ~mask;
}
+ DCHECK_EQ(Test(obj), do_set);
return (old_word & mask) != 0;
}
diff --git a/runtime/gc/accounting/space_bitmap.cc b/runtime/gc/accounting/space_bitmap.cc
index b831843..a080bee 100644
--- a/runtime/gc/accounting/space_bitmap.cc
+++ b/runtime/gc/accounting/space_bitmap.cc
@@ -64,7 +64,7 @@ SpaceBitmap* SpaceBitmap::Create(const std::string& name, byte* heap_begin, size
size_t bitmap_size = OffsetToIndex(RoundUp(heap_capacity, kAlignment * kBitsPerWord)) * kWordSize;
std::string error_msg;
UniquePtr<MemMap> mem_map(MemMap::MapAnonymous(name.c_str(), NULL, bitmap_size,
- PROT_READ | PROT_WRITE, &error_msg));
+ PROT_READ | PROT_WRITE, false, &error_msg));
if (UNLIKELY(mem_map.get() == nullptr)) {
LOG(ERROR) << "Failed to allocate bitmap " << name << ": " << error_msg;
return NULL;
diff --git a/runtime/gc/accounting/space_bitmap.h b/runtime/gc/accounting/space_bitmap.h
index 2d6cde5..aa074eb 100644
--- a/runtime/gc/accounting/space_bitmap.h
+++ b/runtime/gc/accounting/space_bitmap.h
@@ -72,8 +72,8 @@ class SpaceBitmap {
}
// Pack the bits in backwards so they come out in address order when using CLZ.
- static word OffsetToMask(uintptr_t offset_) {
- return static_cast<uintptr_t>(kWordHighBitMask) >> ((offset_ / kAlignment) % kBitsPerWord);
+ static word OffsetToMask(uintptr_t offset) {
+ return static_cast<uintptr_t>(kWordHighBitMask) >> ((offset / kAlignment) % kBitsPerWord);
}
inline bool Set(const mirror::Object* obj) {
diff --git a/runtime/gc/collector/mark_sweep-inl.h b/runtime/gc/collector/mark_sweep-inl.h
index 9c1c5dc..d148ae5 100644
--- a/runtime/gc/collector/mark_sweep-inl.h
+++ b/runtime/gc/collector/mark_sweep-inl.h
@@ -118,7 +118,7 @@ inline void MarkSweep::VisitFieldsReferences(mirror::Object* obj, uint32_t ref_o
while (ref_offsets != 0) {
size_t right_shift = CLZ(ref_offsets);
MemberOffset field_offset = CLASS_OFFSET_FROM_CLZ(right_shift);
- mirror::Object* ref = obj->GetFieldObject<mirror::Object*>(field_offset, false);
+ mirror::Object* ref = obj->GetFieldObject<mirror::Object>(field_offset, false);
visitor(obj, ref, field_offset, is_static);
ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift);
}
@@ -127,17 +127,17 @@ inline void MarkSweep::VisitFieldsReferences(mirror::Object* obj, uint32_t ref_o
// walk up the class inheritance hierarchy and find reference
// offsets the hard way. In the static case, just consider this
// class.
- for (const mirror::Class* klass = is_static ? obj->AsClass() : obj->GetClass();
- klass != NULL;
- klass = is_static ? NULL : klass->GetSuperClass()) {
+ for (mirror::Class* klass = is_static ? obj->AsClass() : obj->GetClass();
+ klass != nullptr;
+ klass = is_static ? nullptr : klass->GetSuperClass()) {
size_t num_reference_fields = (is_static
? klass->NumReferenceStaticFields()
: klass->NumReferenceInstanceFields());
for (size_t i = 0; i < num_reference_fields; ++i) {
mirror::ArtField* field = (is_static ? klass->GetStaticField(i)
- : klass->GetInstanceField(i));
+ : klass->GetInstanceField(i));
MemberOffset field_offset = field->GetOffset();
- mirror::Object* ref = obj->GetFieldObject<mirror::Object*>(field_offset, false);
+ mirror::Object* ref = obj->GetFieldObject<mirror::Object>(field_offset, false);
visitor(obj, ref, field_offset, is_static);
}
}
@@ -150,7 +150,7 @@ inline void MarkSweep::VisitObjectArrayReferences(mirror::ObjectArray<mirror::Ob
const size_t length = static_cast<size_t>(array->GetLength());
for (size_t i = 0; i < length; ++i) {
mirror::Object* element = array->GetWithoutChecks(static_cast<int32_t>(i));
- const size_t width = sizeof(mirror::Object*);
+ const size_t width = sizeof(mirror::HeapReference<mirror::Object>);
MemberOffset offset(i * width + mirror::Array::DataOffset(width).Int32Value());
visitor(array, element, offset, false);
}
diff --git a/runtime/gc/collector/mark_sweep.h b/runtime/gc/collector/mark_sweep.h
index 0c27a3b..bfedac7 100644
--- a/runtime/gc/collector/mark_sweep.h
+++ b/runtime/gc/collector/mark_sweep.h
@@ -17,7 +17,7 @@
#ifndef ART_RUNTIME_GC_COLLECTOR_MARK_SWEEP_H_
#define ART_RUNTIME_GC_COLLECTOR_MARK_SWEEP_H_
-#include "atomic_integer.h"
+#include "atomic.h"
#include "barrier.h"
#include "base/macros.h"
#include "base/mutex.h"
diff --git a/runtime/gc/collector/semi_space.cc b/runtime/gc/collector/semi_space.cc
index 3fb78b0..03307f5 100644
--- a/runtime/gc/collector/semi_space.cc
+++ b/runtime/gc/collector/semi_space.cc
@@ -600,9 +600,9 @@ void SemiSpace::ScanObject(Object* obj) {
if (new_address != ref) {
DCHECK(new_address != nullptr);
// Don't need to mark the card since we updating the object address and not changing the
- // actual objects its pointing to. Using SetFieldPtr is better in this case since it does not
- // dirty cards and use additional memory.
- obj->SetFieldPtr(offset, new_address, false);
+ // actual objects its pointing to. Using SetFieldObjectWithoutWriteBarrier is better in this
+ // case since it does not dirty cards and use additional memory.
+ obj->SetFieldObjectWithoutWriteBarrier(offset, new_address, false);
}
}, kMovingClasses);
mirror::Class* klass = obj->GetClass();
diff --git a/runtime/gc/collector/semi_space.h b/runtime/gc/collector/semi_space.h
index f81a7c2..685b33c 100644
--- a/runtime/gc/collector/semi_space.h
+++ b/runtime/gc/collector/semi_space.h
@@ -17,7 +17,7 @@
#ifndef ART_RUNTIME_GC_COLLECTOR_SEMI_SPACE_H_
#define ART_RUNTIME_GC_COLLECTOR_SEMI_SPACE_H_
-#include "atomic_integer.h"
+#include "atomic.h"
#include "barrier.h"
#include "base/macros.h"
#include "base/mutex.h"
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 309adb7..b1bbfc6 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -231,7 +231,7 @@ Heap::Heap(size_t initial_size, size_t growth_limit, size_t min_free, size_t max
std::string error_str;
post_zygote_non_moving_space_mem_map_.reset(
MemMap::MapAnonymous("post zygote non-moving space", nullptr, 64 * MB,
- PROT_READ | PROT_WRITE, &error_str));
+ PROT_READ | PROT_WRITE, true, &error_str));
CHECK(post_zygote_non_moving_space_mem_map_.get() != nullptr) << error_str;
heap_begin = std::min(post_zygote_non_moving_space_mem_map_->Begin(), heap_begin);
heap_end = std::max(post_zygote_non_moving_space_mem_map_->End(), heap_end);
@@ -653,15 +653,15 @@ void Heap::ProcessReferences(TimingLogger& timings, bool clear_soft,
bool Heap::IsEnqueued(mirror::Object* ref) const {
// Since the references are stored as cyclic lists it means that once enqueued, the pending next
// will always be non-null.
- return ref->GetFieldObject<mirror::Object*>(GetReferencePendingNextOffset(), false) != nullptr;
+ return ref->GetFieldObject<mirror::Object>(GetReferencePendingNextOffset(), false) != nullptr;
}
-bool Heap::IsEnqueuable(const mirror::Object* ref) const {
+bool Heap::IsEnqueuable(mirror::Object* ref) const {
DCHECK(ref != nullptr);
const mirror::Object* queue =
- ref->GetFieldObject<mirror::Object*>(GetReferenceQueueOffset(), false);
+ ref->GetFieldObject<mirror::Object>(GetReferenceQueueOffset(), false);
const mirror::Object* queue_next =
- ref->GetFieldObject<mirror::Object*>(GetReferenceQueueNextOffset(), false);
+ ref->GetFieldObject<mirror::Object>(GetReferenceQueueNextOffset(), false);
return queue != nullptr && queue_next == nullptr;
}
@@ -720,7 +720,7 @@ static void MSpaceChunkCallback(void* start, void* end, size_t used_bytes, void*
void Heap::ThrowOutOfMemoryError(Thread* self, size_t byte_count, bool large_object_allocation) {
std::ostringstream oss;
- int64_t total_bytes_free = GetFreeMemory();
+ size_t total_bytes_free = GetFreeMemory();
oss << "Failed to allocate a " << byte_count << " byte allocation with " << total_bytes_free
<< " free bytes";
// If the allocation failed due to fragmentation, print out the largest continuous allocation.
@@ -805,7 +805,7 @@ bool Heap::IsHeapAddress(const mirror::Object* obj) const {
return FindSpaceFromObject(obj, true) != nullptr;
}
-bool Heap::IsLiveObjectLocked(const mirror::Object* obj, bool search_allocation_stack,
+bool Heap::IsLiveObjectLocked(mirror::Object* obj, bool search_allocation_stack,
bool search_live_stack, bool sorted) {
if (UNLIKELY(!IsAligned<kObjectAlignment>(obj))) {
return false;
@@ -874,7 +874,7 @@ bool Heap::IsLiveObjectLocked(const mirror::Object* obj, bool search_allocation_
return false;
}
-void Heap::VerifyObjectImpl(const mirror::Object* obj) {
+void Heap::VerifyObjectImpl(mirror::Object* obj) {
if (Thread::Current() == NULL ||
Runtime::Current()->GetThreadList()->GetLockOwner() == Thread::Current()->GetTid()) {
return;
@@ -887,9 +887,9 @@ bool Heap::VerifyClassClass(const mirror::Class* c) const {
// to run
const byte* raw_addr =
reinterpret_cast<const byte*>(c) + mirror::Object::ClassOffset().Int32Value();
- const mirror::Class* c_c = *reinterpret_cast<mirror::Class* const *>(raw_addr);
+ mirror::Class* c_c = reinterpret_cast<mirror::HeapReference<mirror::Class> const *>(raw_addr)->AsMirrorPtr();
raw_addr = reinterpret_cast<const byte*>(c_c) + mirror::Object::ClassOffset().Int32Value();
- const mirror::Class* c_c_c = *reinterpret_cast<mirror::Class* const *>(raw_addr);
+ mirror::Class* c_c_c = reinterpret_cast<mirror::HeapReference<mirror::Class> const *>(raw_addr)->AsMirrorPtr();
return c_c == c_c_c;
}
@@ -910,7 +910,7 @@ void Heap::DumpSpaces(std::ostream& stream) {
}
}
-void Heap::VerifyObjectBody(const mirror::Object* obj) {
+void Heap::VerifyObjectBody(mirror::Object* obj) {
CHECK(IsAligned<kObjectAlignment>(obj)) << "Object isn't aligned: " << obj;
// Ignore early dawn of the universe verifications.
if (UNLIKELY(static_cast<size_t>(num_bytes_allocated_.Load()) < 10 * KB)) {
@@ -918,7 +918,7 @@ void Heap::VerifyObjectBody(const mirror::Object* obj) {
}
const byte* raw_addr = reinterpret_cast<const byte*>(obj) +
mirror::Object::ClassOffset().Int32Value();
- const mirror::Class* c = *reinterpret_cast<mirror::Class* const *>(raw_addr);
+ mirror::Class* c = reinterpret_cast<mirror::HeapReference<mirror::Class> const *>(raw_addr)->AsMirrorPtr();
if (UNLIKELY(c == NULL)) {
LOG(FATAL) << "Null class in object: " << obj;
} else if (UNLIKELY(!IsAligned<kObjectAlignment>(c))) {
@@ -949,7 +949,7 @@ void Heap::VerifyHeap() {
GetLiveBitmap()->Walk(Heap::VerificationCallback, this);
}
-void Heap::RecordFree(int64_t freed_objects, int64_t freed_bytes) {
+void Heap::RecordFree(size_t freed_objects, size_t freed_bytes) {
DCHECK_LE(freed_bytes, num_bytes_allocated_.Load());
num_bytes_allocated_.FetchAndSub(freed_bytes);
if (Runtime::Current()->HasStatsEnabled()) {
@@ -1059,9 +1059,9 @@ class InstanceCounter {
: classes_(classes), use_is_assignable_from_(use_is_assignable_from), counts_(counts) {
}
- void operator()(const mirror::Object* o) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ void operator()(mirror::Object* o) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
for (size_t i = 0; i < classes_.size(); ++i) {
- const mirror::Class* instance_class = o->GetClass();
+ mirror::Class* instance_class = o->GetClass();
if (use_is_assignable_from_) {
if (instance_class != NULL && classes_[i]->IsAssignableFrom(instance_class)) {
++counts_[i];
@@ -1103,11 +1103,11 @@ class InstanceCollector {
: class_(c), max_count_(max_count), instances_(instances) {
}
- void operator()(const mirror::Object* o) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- const mirror::Class* instance_class = o->GetClass();
+ void operator()(mirror::Object* o) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ mirror::Class* instance_class = o->GetClass();
if (instance_class == class_) {
if (max_count_ == 0 || instances_.size() < max_count_) {
- instances_.push_back(const_cast<mirror::Object*>(o));
+ instances_.push_back(o);
}
}
}
@@ -1190,8 +1190,8 @@ void Heap::TransitionCollector(CollectorType collector_type) {
return;
}
uint64_t start_time = NanoTime();
- int32_t before_size = GetTotalMemory();
- int32_t before_allocated = num_bytes_allocated_.Load();
+ uint32_t before_size = GetTotalMemory();
+ uint32_t before_allocated = num_bytes_allocated_.Load();
ThreadList* tl = Runtime::Current()->GetThreadList();
Thread* self = Thread::Current();
ScopedThreadStateChange tsc(self, kWaitingPerformingGc);
@@ -1718,7 +1718,7 @@ class VerifyReferenceVisitor {
// TODO: Fix lock analysis to not use NO_THREAD_SAFETY_ANALYSIS, requires support for smarter
// analysis on visitors.
- void operator()(const mirror::Object* obj, const mirror::Object* ref,
+ void operator()(mirror::Object* obj, mirror::Object* ref,
const MemberOffset& offset, bool /* is_static */) const
NO_THREAD_SAFETY_ANALYSIS {
if (ref == nullptr || IsLive(ref)) {
@@ -1813,7 +1813,7 @@ class VerifyReferenceVisitor {
}
}
- bool IsLive(const mirror::Object* obj) const NO_THREAD_SAFETY_ANALYSIS {
+ bool IsLive(mirror::Object* obj) const NO_THREAD_SAFETY_ANALYSIS {
return heap_->IsLiveObjectLocked(obj, true, false, true);
}
@@ -1898,7 +1898,7 @@ class VerifyReferenceCardVisitor {
// TODO: Fix lock analysis to not use NO_THREAD_SAFETY_ANALYSIS, requires support for
// annotalysis on visitors.
- void operator()(const mirror::Object* obj, const mirror::Object* ref, const MemberOffset& offset,
+ void operator()(mirror::Object* obj, mirror::Object* ref, const MemberOffset& offset,
bool is_static) const NO_THREAD_SAFETY_ANALYSIS {
// Filter out class references since changing an object's class does not mark the card as dirty.
// Also handles large objects, since the only reference they hold is a class reference.
@@ -1926,13 +1926,13 @@ class VerifyReferenceCardVisitor {
// Print which field of the object is dead.
if (!obj->IsObjectArray()) {
- const mirror::Class* klass = is_static ? obj->AsClass() : obj->GetClass();
+ mirror::Class* klass = is_static ? obj->AsClass() : obj->GetClass();
CHECK(klass != NULL);
- const mirror::ObjectArray<mirror::ArtField>* fields = is_static ? klass->GetSFields()
- : klass->GetIFields();
+ mirror::ObjectArray<mirror::ArtField>* fields = is_static ? klass->GetSFields()
+ : klass->GetIFields();
CHECK(fields != NULL);
for (int32_t i = 0; i < fields->GetLength(); ++i) {
- const mirror::ArtField* cur = fields->Get(i);
+ mirror::ArtField* cur = fields->Get(i);
if (cur->GetOffset().Int32Value() == offset.Int32Value()) {
LOG(ERROR) << (is_static ? "Static " : "") << "field in the live stack is "
<< PrettyField(cur);
@@ -1940,7 +1940,7 @@ class VerifyReferenceCardVisitor {
}
}
} else {
- const mirror::ObjectArray<mirror::Object>* object_array =
+ mirror::ObjectArray<mirror::Object>* object_array =
obj->AsObjectArray<mirror::Object>();
for (int32_t i = 0; i < object_array->GetLength(); ++i) {
if (object_array->Get(i) == ref) {
@@ -2278,14 +2278,14 @@ void Heap::SetReferenceReferent(mirror::Object* reference, mirror::Object* refer
mirror::Object* Heap::GetReferenceReferent(mirror::Object* reference) {
DCHECK(reference != NULL);
DCHECK_NE(reference_referent_offset_.Uint32Value(), 0U);
- return reference->GetFieldObject<mirror::Object*>(reference_referent_offset_, true);
+ return reference->GetFieldObject<mirror::Object>(reference_referent_offset_, true);
}
void Heap::AddFinalizerReference(Thread* self, mirror::Object* object) {
ScopedObjectAccess soa(self);
JValue result;
ArgArray arg_array(NULL, 0);
- arg_array.Append(reinterpret_cast<uint32_t>(object));
+ arg_array.Append(object);
soa.DecodeMethod(WellKnownClasses::java_lang_ref_FinalizerReference_add)->Invoke(self,
arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'V');
}
@@ -2299,7 +2299,7 @@ void Heap::EnqueueClearedReferences() {
ScopedObjectAccess soa(self);
JValue result;
ArgArray arg_array(NULL, 0);
- arg_array.Append(reinterpret_cast<uint32_t>(cleared_references_.GetList()));
+ arg_array.Append(cleared_references_.GetList());
soa.DecodeMethod(WellKnownClasses::java_lang_ref_ReferenceQueue_add)->Invoke(soa.Self(),
arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'V');
}
@@ -2477,8 +2477,8 @@ void Heap::RegisterNativeFree(JNIEnv* env, int bytes) {
} while (!native_bytes_allocated_.CompareAndSwap(expected_size, new_size));
}
-int64_t Heap::GetTotalMemory() const {
- int64_t ret = 0;
+size_t Heap::GetTotalMemory() const {
+ size_t ret = 0;
for (const auto& space : continuous_spaces_) {
// Currently don't include the image space.
if (!space->IsImageSpace()) {
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 26d67a1..499d27c 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -21,7 +21,7 @@
#include <string>
#include <vector>
-#include "atomic_integer.h"
+#include "atomic.h"
#include "base/timing_logger.h"
#include "gc/accounting/atomic_stack.h"
#include "gc/accounting/card_table.h"
@@ -204,14 +204,14 @@ class Heap {
void ChangeCollector(CollectorType collector_type);
// The given reference is believed to be to an object in the Java heap, check the soundness of it.
- void VerifyObjectImpl(const mirror::Object* o);
- void VerifyObject(const mirror::Object* o) {
+ void VerifyObjectImpl(mirror::Object* o);
+ void VerifyObject(mirror::Object* o) {
if (o != nullptr && this != nullptr && verify_object_mode_ > kNoHeapVerification) {
VerifyObjectImpl(o);
}
}
// Check that c.getClass() == c.getClass().getClass().
- bool VerifyClassClass(const mirror::Class* c) const;
+ bool VerifyClassClass(const mirror::Class* c) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Check sanity of all live references.
void VerifyHeap() LOCKS_EXCLUDED(Locks::heap_bitmap_lock_);
@@ -232,9 +232,9 @@ class Heap {
// Returns true if 'obj' is a live heap object, false otherwise (including for invalid addresses).
// Requires the heap lock to be held.
- bool IsLiveObjectLocked(const mirror::Object* obj, bool search_allocation_stack = true,
+ bool IsLiveObjectLocked(mirror::Object* obj, bool search_allocation_stack = true,
bool search_live_stack = true, bool sorted = false)
- SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
+ SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
// Returns true if there is any chance that the object (obj) will move.
bool IsMovableObject(const mirror::Object* obj) const;
@@ -358,7 +358,7 @@ class Heap {
// Freed bytes can be negative in cases where we copy objects from a compacted space to a
// free-list backed space.
- void RecordFree(int64_t freed_objects, int64_t freed_bytes);
+ void RecordFree(size_t freed_objects, size_t freed_bytes);
// Must be called if a field of an Object in the heap changes, and before any GC safe-point.
// The call is not needed if NULL is stored in the field.
@@ -411,16 +411,16 @@ class Heap {
// consume. For a regular VM this would relate to the -Xmx option and would return -1 if no Xmx
// were specified. Android apps start with a growth limit (small heap size) which is
// cleared/extended for large apps.
- int64_t GetMaxMemory() const {
+ size_t GetMaxMemory() const {
return growth_limit_;
}
// Implements java.lang.Runtime.totalMemory, returning the amount of memory consumed by an
// application.
- int64_t GetTotalMemory() const;
+ size_t GetTotalMemory() const;
// Implements java.lang.Runtime.freeMemory.
- int64_t GetFreeMemory() const {
+ size_t GetFreeMemory() const {
return GetTotalMemory() - num_bytes_allocated_;
}
@@ -550,7 +550,8 @@ class Heap {
static bool IsCompactingGC(CollectorType collector_type) {
return collector_type == kCollectorTypeSS || collector_type == kCollectorTypeGSS;
}
- bool ShouldAllocLargeObject(mirror::Class* c, size_t byte_count) const;
+ bool ShouldAllocLargeObject(mirror::Class* c, size_t byte_count) const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
ALWAYS_INLINE void CheckConcurrentGC(Thread* self, size_t new_num_bytes_allocated,
mirror::Object* obj);
@@ -596,8 +597,8 @@ class Heap {
}
void EnqueueClearedReferences();
// Returns true if the reference object has not yet been enqueued.
- bool IsEnqueuable(const mirror::Object* ref) const;
- bool IsEnqueued(mirror::Object* ref) const;
+ bool IsEnqueuable(mirror::Object* ref) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool IsEnqueued(mirror::Object* ref) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void DelayReferenceReferent(mirror::Class* klass, mirror::Object* obj, RootVisitor mark_visitor,
void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -644,7 +645,7 @@ class Heap {
// No thread saftey analysis since we call this everywhere and it is impossible to find a proper
// lock ordering for it.
- void VerifyObjectBody(const mirror::Object *obj) NO_THREAD_SAFETY_ANALYSIS;
+ void VerifyObjectBody(mirror::Object *obj) NO_THREAD_SAFETY_ANALYSIS;
static void VerificationCallback(mirror::Object* obj, void* arg)
SHARED_LOCKS_REQUIRED(GlobalSychronization::heap_bitmap_lock_);
@@ -781,13 +782,13 @@ class Heap {
size_t total_objects_freed_ever_;
// Number of bytes allocated. Adjusted after each allocation and free.
- AtomicInteger num_bytes_allocated_;
+ Atomic<size_t> num_bytes_allocated_;
// Bytes which are allocated and managed by native code but still need to be accounted for.
- AtomicInteger native_bytes_allocated_;
+ Atomic<size_t> native_bytes_allocated_;
// Data structure GC overhead.
- AtomicInteger gc_memory_overhead_;
+ Atomic<size_t> gc_memory_overhead_;
// Heap verification flags.
const bool verify_missing_card_marks_;
diff --git a/runtime/gc/reference_queue.cc b/runtime/gc/reference_queue.cc
index d006349..2d73a71 100644
--- a/runtime/gc/reference_queue.cc
+++ b/runtime/gc/reference_queue.cc
@@ -52,8 +52,7 @@ void ReferenceQueue::EnqueuePendingReference(mirror::Object* ref) {
ref->SetFieldObject(pending_next_offset, ref, false);
list_ = ref;
} else {
- mirror::Object* head =
- list_->GetFieldObject<mirror::Object*>(pending_next_offset, false);
+ mirror::Object* head = list_->GetFieldObject<mirror::Object>(pending_next_offset, false);
ref->SetFieldObject(pending_next_offset, head, false);
list_->SetFieldObject(pending_next_offset, ref, false);
}
@@ -62,7 +61,7 @@ void ReferenceQueue::EnqueuePendingReference(mirror::Object* ref) {
mirror::Object* ReferenceQueue::DequeuePendingReference() {
DCHECK(!IsEmpty());
MemberOffset pending_next_offset = heap_->GetReferencePendingNextOffset();
- mirror::Object* head = list_->GetFieldObject<mirror::Object*>(pending_next_offset, false);
+ mirror::Object* head = list_->GetFieldObject<mirror::Object>(pending_next_offset, false);
DCHECK(head != nullptr);
mirror::Object* ref;
// Note: the following code is thread-safe because it is only called from ProcessReferences which
@@ -71,7 +70,7 @@ mirror::Object* ReferenceQueue::DequeuePendingReference() {
ref = list_;
list_ = nullptr;
} else {
- mirror::Object* next = head->GetFieldObject<mirror::Object*>(pending_next_offset, false);
+ mirror::Object* next = head->GetFieldObject<mirror::Object>(pending_next_offset, false);
list_->SetFieldObject(pending_next_offset, next, false);
ref = head;
}
@@ -84,11 +83,11 @@ void ReferenceQueue::Dump(std::ostream& os) const {
os << "Reference starting at list_=" << list_ << "\n";
while (cur != nullptr) {
mirror::Object* pending_next =
- cur->GetFieldObject<mirror::Object*>(heap_->GetReferencePendingNextOffset(), false);
+ cur->GetFieldObject<mirror::Object>(heap_->GetReferencePendingNextOffset(), false);
os << "PendingNext=" << pending_next;
if (cur->GetClass()->IsFinalizerReferenceClass()) {
os << " Zombie=" <<
- cur->GetFieldObject<mirror::Object*>(heap_->GetFinalizerReferenceZombieOffset(), false);
+ cur->GetFieldObject<mirror::Object>(heap_->GetFinalizerReferenceZombieOffset(), false);
}
os << "\n";
cur = pending_next;
diff --git a/runtime/gc/reference_queue.h b/runtime/gc/reference_queue.h
index 89589c3..3f3069e 100644
--- a/runtime/gc/reference_queue.h
+++ b/runtime/gc/reference_queue.h
@@ -21,7 +21,7 @@
#include <string>
#include <vector>
-#include "atomic_integer.h"
+#include "atomic.h"
#include "base/timing_logger.h"
#include "globals.h"
#include "gtest/gtest.h"
@@ -83,7 +83,7 @@ class ReferenceQueue {
private:
// Lock, used for parallel GC reference enqueuing. It allows for multiple threads simultaneously
// calling AtomicEnqueueIfNotEnqueued.
- Mutex lock_;
+ Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
// The heap contains the reference offsets.
Heap* const heap_;
// The actual reference list. Not a root since it will be nullptr when the GC is not running.
diff --git a/runtime/gc/space/bump_pointer_space.cc b/runtime/gc/space/bump_pointer_space.cc
index 4dc17df..a314d74 100644
--- a/runtime/gc/space/bump_pointer_space.cc
+++ b/runtime/gc/space/bump_pointer_space.cc
@@ -29,7 +29,7 @@ BumpPointerSpace* BumpPointerSpace::Create(const std::string& name, size_t capac
capacity = RoundUp(capacity, kPageSize);
std::string error_msg;
UniquePtr<MemMap> mem_map(MemMap::MapAnonymous(name.c_str(), requested_begin, capacity,
- PROT_READ | PROT_WRITE, &error_msg));
+ PROT_READ | PROT_WRITE, true, &error_msg));
if (mem_map.get() == nullptr) {
LOG(ERROR) << "Failed to allocate pages for alloc space (" << name << ") of size "
<< PrettySize(capacity) << " with message " << error_msg;
@@ -69,7 +69,7 @@ mirror::Object* BumpPointerSpace::Alloc(Thread*, size_t num_bytes, size_t* bytes
return ret;
}
-size_t BumpPointerSpace::AllocationSize(const mirror::Object* obj) {
+size_t BumpPointerSpace::AllocationSize(mirror::Object* obj) {
return AllocationSizeNonvirtual(obj);
}
diff --git a/runtime/gc/space/bump_pointer_space.h b/runtime/gc/space/bump_pointer_space.h
index 3e25b6b..d73fe3b 100644
--- a/runtime/gc/space/bump_pointer_space.h
+++ b/runtime/gc/space/bump_pointer_space.h
@@ -49,8 +49,7 @@ class BumpPointerSpace : public ContinuousMemMapAllocSpace {
mirror::Object* AllocNonvirtualWithoutAccounting(size_t num_bytes);
// Return the storage space required by obj.
- virtual size_t AllocationSize(const mirror::Object* obj)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ virtual size_t AllocationSize(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// NOPS unless we support free lists.
virtual size_t Free(Thread*, mirror::Object*) {
@@ -60,7 +59,7 @@ class BumpPointerSpace : public ContinuousMemMapAllocSpace {
return 0;
}
- size_t AllocationSizeNonvirtual(const mirror::Object* obj)
+ size_t AllocationSizeNonvirtual(mirror::Object* obj)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return obj->SizeOf();
}
@@ -135,7 +134,6 @@ class BumpPointerSpace : public ContinuousMemMapAllocSpace {
byte* AllocBlock(size_t bytes) EXCLUSIVE_LOCKS_REQUIRED(block_lock_);
void RevokeThreadLocalBuffersLocked(Thread* thread) EXCLUSIVE_LOCKS_REQUIRED(block_lock_);
- size_t InternalAllocationSize(const mirror::Object* obj);
mirror::Object* AllocWithoutGrowthLocked(size_t num_bytes, size_t* bytes_allocated)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
diff --git a/runtime/gc/space/dlmalloc_space.cc b/runtime/gc/space/dlmalloc_space.cc
index 9ae6a33..931ed21 100644
--- a/runtime/gc/space/dlmalloc_space.cc
+++ b/runtime/gc/space/dlmalloc_space.cc
@@ -228,7 +228,7 @@ extern "C" void* art_heap_morecore(void* mspace, intptr_t increment) {
return dlmalloc_space->MoreCore(increment);
}
-size_t DlMallocSpace::AllocationSize(const mirror::Object* obj) {
+size_t DlMallocSpace::AllocationSize(mirror::Object* obj) {
return AllocationSizeNonvirtual(obj);
}
diff --git a/runtime/gc/space/dlmalloc_space.h b/runtime/gc/space/dlmalloc_space.h
index 24308f7..4507c36 100644
--- a/runtime/gc/space/dlmalloc_space.h
+++ b/runtime/gc/space/dlmalloc_space.h
@@ -48,13 +48,15 @@ class DlMallocSpace : public MallocSpace {
virtual mirror::Object* AllocWithGrowth(Thread* self, size_t num_bytes,
size_t* bytes_allocated) LOCKS_EXCLUDED(lock_);
virtual mirror::Object* Alloc(Thread* self, size_t num_bytes, size_t* bytes_allocated);
- virtual size_t AllocationSize(const mirror::Object* obj);
- virtual size_t Free(Thread* self, mirror::Object* ptr);
- virtual size_t FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs);
+ virtual size_t AllocationSize(mirror::Object* obj);
+ virtual size_t Free(Thread* self, mirror::Object* ptr)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ virtual size_t FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
mirror::Object* AllocNonvirtual(Thread* self, size_t num_bytes, size_t* bytes_allocated);
- size_t AllocationSizeNonvirtual(const mirror::Object* obj) {
+ size_t AllocationSizeNonvirtual(mirror::Object* obj) {
void* obj_ptr = const_cast<void*>(reinterpret_cast<const void*>(obj));
return mspace_usable_size(obj_ptr) + kChunkOverhead;
}
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 4777cc6..ebad8dd 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -35,7 +35,7 @@ namespace art {
namespace gc {
namespace space {
-AtomicInteger ImageSpace::bitmap_index_(0);
+Atomic<uint32_t> ImageSpace::bitmap_index_(0);
ImageSpace::ImageSpace(const std::string& name, MemMap* mem_map,
accounting::SpaceBitmap* live_bitmap)
@@ -171,7 +171,7 @@ void ImageSpace::VerifyImageAllocations() {
byte* current = Begin() + RoundUp(sizeof(ImageHeader), kObjectAlignment);
while (current < End()) {
DCHECK_ALIGNED(current, kObjectAlignment);
- const mirror::Object* obj = reinterpret_cast<const mirror::Object*>(current);
+ mirror::Object* obj = reinterpret_cast<mirror::Object*>(current);
CHECK(live_bitmap_->Test(obj));
CHECK(obj->GetClass() != nullptr) << "Image object at address " << obj << " has null class";
current += RoundUp(obj->SizeOf(), kObjectAlignment);
@@ -227,7 +227,7 @@ ImageSpace* ImageSpace::Init(const char* image_file_name, bool validate_oat_file
*error_msg = StringPrintf("Failed to map image bitmap: %s", error_msg->c_str());
return nullptr;
}
- size_t bitmap_index = bitmap_index_.FetchAndAdd(1);
+ uint32_t bitmap_index = bitmap_index_.FetchAndAdd(1);
std::string bitmap_name(StringPrintf("imagespace %s live-bitmap %u", image_file_name,
bitmap_index));
UniquePtr<accounting::SpaceBitmap> bitmap(
diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h
index c3f0ae6..9e19774 100644
--- a/runtime/gc/space/image_space.h
+++ b/runtime/gc/space/image_space.h
@@ -94,7 +94,7 @@ class ImageSpace : public MemMapSpace {
friend class Space;
- static AtomicInteger bitmap_index_;
+ static Atomic<uint32_t> bitmap_index_;
UniquePtr<accounting::SpaceBitmap> live_bitmap_;
diff --git a/runtime/gc/space/large_object_space.cc b/runtime/gc/space/large_object_space.cc
index 7fcfed4..987a655 100644
--- a/runtime/gc/space/large_object_space.cc
+++ b/runtime/gc/space/large_object_space.cc
@@ -60,7 +60,7 @@ mirror::Object* LargeObjectMapSpace::Alloc(Thread* self, size_t num_bytes,
size_t* bytes_allocated) {
std::string error_msg;
MemMap* mem_map = MemMap::MapAnonymous("large object space allocation", NULL, num_bytes,
- PROT_READ | PROT_WRITE, &error_msg);
+ PROT_READ | PROT_WRITE, true, &error_msg);
if (UNLIKELY(mem_map == NULL)) {
LOG(WARNING) << "Large object allocation failed: " << error_msg;
return NULL;
@@ -92,9 +92,9 @@ size_t LargeObjectMapSpace::Free(Thread* self, mirror::Object* ptr) {
return allocation_size;
}
-size_t LargeObjectMapSpace::AllocationSize(const mirror::Object* obj) {
+size_t LargeObjectMapSpace::AllocationSize(mirror::Object* obj) {
MutexLock mu(Thread::Current(), lock_);
- MemMaps::iterator found = mem_maps_.find(const_cast<mirror::Object*>(obj));
+ MemMaps::iterator found = mem_maps_.find(obj);
CHECK(found != mem_maps_.end()) << "Attempted to get size of a large object which is not live";
return found->second->Size();
}
@@ -134,7 +134,7 @@ FreeListSpace* FreeListSpace::Create(const std::string& name, byte* requested_be
CHECK_EQ(size % kAlignment, 0U);
std::string error_msg;
MemMap* mem_map = MemMap::MapAnonymous(name.c_str(), requested_begin, size,
- PROT_READ | PROT_WRITE, &error_msg);
+ PROT_READ | PROT_WRITE, true, &error_msg);
CHECK(mem_map != NULL) << "Failed to allocate large object space mem map: " << error_msg;
return new FreeListSpace(name, mem_map, mem_map->Begin(), mem_map->End());
}
@@ -244,7 +244,7 @@ bool FreeListSpace::Contains(const mirror::Object* obj) const {
return mem_map_->HasAddress(obj);
}
-size_t FreeListSpace::AllocationSize(const mirror::Object* obj) {
+size_t FreeListSpace::AllocationSize(mirror::Object* obj) {
AllocationHeader* header = GetAllocationHeader(obj);
DCHECK(Contains(obj));
DCHECK(!header->IsFree());
diff --git a/runtime/gc/space/large_object_space.h b/runtime/gc/space/large_object_space.h
index cd7c383..5274c8d 100644
--- a/runtime/gc/space/large_object_space.h
+++ b/runtime/gc/space/large_object_space.h
@@ -92,7 +92,7 @@ class LargeObjectMapSpace : public LargeObjectSpace {
static LargeObjectMapSpace* Create(const std::string& name);
// Return the storage space required by obj.
- size_t AllocationSize(const mirror::Object* obj);
+ size_t AllocationSize(mirror::Object* obj);
mirror::Object* Alloc(Thread* self, size_t num_bytes, size_t* bytes_allocated);
size_t Free(Thread* self, mirror::Object* ptr);
void Walk(DlMallocSpace::WalkCallback, void* arg) LOCKS_EXCLUDED(lock_);
@@ -118,8 +118,7 @@ class FreeListSpace : public LargeObjectSpace {
virtual ~FreeListSpace();
static FreeListSpace* Create(const std::string& name, byte* requested_begin, size_t capacity);
- size_t AllocationSize(const mirror::Object* obj)
- EXCLUSIVE_LOCKS_REQUIRED(lock_);
+ size_t AllocationSize(mirror::Object* obj) EXCLUSIVE_LOCKS_REQUIRED(lock_);
mirror::Object* Alloc(Thread* self, size_t num_bytes, size_t* bytes_allocated);
size_t Free(Thread* self, mirror::Object* obj);
bool Contains(const mirror::Object* obj) const;
diff --git a/runtime/gc/space/malloc_space.cc b/runtime/gc/space/malloc_space.cc
index 6c6cb97..f90e6c7 100644
--- a/runtime/gc/space/malloc_space.cc
+++ b/runtime/gc/space/malloc_space.cc
@@ -87,7 +87,7 @@ MemMap* MallocSpace::CreateMemMap(const std::string& name, size_t starting_size,
std::string error_msg;
MemMap* mem_map = MemMap::MapAnonymous(name.c_str(), requested_begin, *capacity,
- PROT_READ | PROT_WRITE, &error_msg);
+ PROT_READ | PROT_WRITE, true, &error_msg);
if (mem_map == nullptr) {
LOG(ERROR) << "Failed to allocate pages for alloc space (" << name << ") of size "
<< PrettySize(*capacity) << ": " << error_msg;
diff --git a/runtime/gc/space/malloc_space.h b/runtime/gc/space/malloc_space.h
index 9a42e2c..f17bcd2 100644
--- a/runtime/gc/space/malloc_space.h
+++ b/runtime/gc/space/malloc_space.h
@@ -58,9 +58,11 @@ class MallocSpace : public ContinuousMemMapAllocSpace {
// Allocate num_bytes allowing the underlying space to grow.
virtual mirror::Object* Alloc(Thread* self, size_t num_bytes, size_t* bytes_allocated) = 0;
// Return the storage space required by obj.
- virtual size_t AllocationSize(const mirror::Object* obj) = 0;
- virtual size_t Free(Thread* self, mirror::Object* ptr) = 0;
- virtual size_t FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs) = 0;
+ virtual size_t AllocationSize(mirror::Object* obj) = 0;
+ virtual size_t Free(Thread* self, mirror::Object* ptr)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
+ virtual size_t FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
#ifndef NDEBUG
virtual void CheckMoreCoreForPrecondition() {} // to be overridden in the debug build.
@@ -136,7 +138,9 @@ class MallocSpace : public ContinuousMemMapAllocSpace {
virtual void* CreateAllocator(void* base, size_t morecore_start, size_t initial_size,
bool low_memory_mode) = 0;
- void RegisterRecentFree(mirror::Object* ptr) EXCLUSIVE_LOCKS_REQUIRED(lock_);
+ void RegisterRecentFree(mirror::Object* ptr)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ EXCLUSIVE_LOCKS_REQUIRED(lock_);
virtual accounting::SpaceBitmap::SweepCallback* GetSweepCallback() {
return &SweepCallback;
@@ -163,7 +167,8 @@ class MallocSpace : public ContinuousMemMapAllocSpace {
size_t growth_limit_;
private:
- static void SweepCallback(size_t num_ptrs, mirror::Object** ptrs, void* arg);
+ static void SweepCallback(size_t num_ptrs, mirror::Object** ptrs, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
DISALLOW_COPY_AND_ASSIGN(MallocSpace);
};
@@ -204,13 +209,14 @@ class ValgrindMallocSpace : public BaseMallocSpaceType {
return result;
}
- virtual size_t AllocationSize(const mirror::Object* obj) {
- size_t result = BaseMallocSpaceType::AllocationSize(reinterpret_cast<const mirror::Object*>(
- reinterpret_cast<const byte*>(obj) - kValgrindRedZoneBytes));
+ virtual size_t AllocationSize(mirror::Object* obj) {
+ size_t result = BaseMallocSpaceType::AllocationSize(reinterpret_cast<mirror::Object*>(
+ reinterpret_cast<byte*>(obj) - kValgrindRedZoneBytes));
return result - 2 * kValgrindRedZoneBytes;
}
- virtual size_t Free(Thread* self, mirror::Object* ptr) {
+ virtual size_t Free(Thread* self, mirror::Object* ptr)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
void* obj_after_rdz = reinterpret_cast<void*>(ptr);
void* obj_with_rdz = reinterpret_cast<byte*>(obj_after_rdz) - kValgrindRedZoneBytes;
// Make redzones undefined.
@@ -221,7 +227,8 @@ class ValgrindMallocSpace : public BaseMallocSpaceType {
return freed - 2 * kValgrindRedZoneBytes;
}
- virtual size_t FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs) {
+ virtual size_t FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
size_t freed = 0;
for (size_t i = 0; i < num_ptrs; i++) {
freed += Free(self, ptrs[i]);
diff --git a/runtime/gc/space/rosalloc_space.cc b/runtime/gc/space/rosalloc_space.cc
index 177e38e..86e441e 100644
--- a/runtime/gc/space/rosalloc_space.cc
+++ b/runtime/gc/space/rosalloc_space.cc
@@ -220,7 +220,7 @@ extern "C" void* art_heap_rosalloc_morecore(allocator::RosAlloc* rosalloc, intpt
return rosalloc_space->MoreCore(increment);
}
-size_t RosAllocSpace::AllocationSize(const mirror::Object* obj) {
+size_t RosAllocSpace::AllocationSize(mirror::Object* obj) {
return AllocationSizeNonvirtual(obj);
}
diff --git a/runtime/gc/space/rosalloc_space.h b/runtime/gc/space/rosalloc_space.h
index 555eb3c..4cd5a6d 100644
--- a/runtime/gc/space/rosalloc_space.h
+++ b/runtime/gc/space/rosalloc_space.h
@@ -47,13 +47,15 @@ class RosAllocSpace : public MallocSpace {
virtual mirror::Object* AllocWithGrowth(Thread* self, size_t num_bytes,
size_t* bytes_allocated) LOCKS_EXCLUDED(lock_);
virtual mirror::Object* Alloc(Thread* self, size_t num_bytes, size_t* bytes_allocated);
- virtual size_t AllocationSize(const mirror::Object* obj);
- virtual size_t Free(Thread* self, mirror::Object* ptr);
- virtual size_t FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs);
+ virtual size_t AllocationSize(mirror::Object* obj);
+ virtual size_t Free(Thread* self, mirror::Object* ptr)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ virtual size_t FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
mirror::Object* AllocNonvirtual(Thread* self, size_t num_bytes, size_t* bytes_allocated);
- size_t AllocationSizeNonvirtual(const mirror::Object* obj)
+ size_t AllocationSizeNonvirtual(mirror::Object* obj)
NO_THREAD_SAFETY_ANALYSIS {
// TODO: NO_THREAD_SAFETY_ANALYSIS because SizeOf() requires that mutator_lock is held.
void* obj_ptr = const_cast<void*>(reinterpret_cast<const void*>(obj));
diff --git a/runtime/gc/space/space.h b/runtime/gc/space/space.h
index 95a79ec..98e6f65 100644
--- a/runtime/gc/space/space.h
+++ b/runtime/gc/space/space.h
@@ -223,7 +223,7 @@ class AllocSpace {
virtual mirror::Object* Alloc(Thread* self, size_t num_bytes, size_t* bytes_allocated) = 0;
// Return the storage space required by obj.
- virtual size_t AllocationSize(const mirror::Object* obj) = 0;
+ virtual size_t AllocationSize(mirror::Object* obj) = 0;
// Returns how many bytes were freed.
virtual size_t Free(Thread* self, mirror::Object* ptr) = 0;
diff --git a/runtime/gc/space/space_test.cc b/runtime/gc/space/space_test.cc
index 427d547..9989ffe 100644
--- a/runtime/gc/space/space_test.cc
+++ b/runtime/gc/space/space_test.cc
@@ -163,6 +163,7 @@ void SpaceTest::ZygoteSpaceTestBody(CreateSpaceFn create_space) {
EXPECT_TRUE(ptr5 == NULL);
// Release some memory.
+ ScopedObjectAccess soa(self);
size_t free3 = space->AllocationSize(ptr3);
EXPECT_EQ(free3, ptr3_bytes_allocated);
EXPECT_EQ(free3, space->Free(self, ptr3));
@@ -257,6 +258,7 @@ void SpaceTest::AllocAndFreeTestBody(CreateSpaceFn create_space) {
EXPECT_TRUE(ptr5 == NULL);
// Release some memory.
+ ScopedObjectAccess soa(self);
size_t free3 = space->AllocationSize(ptr3);
EXPECT_EQ(free3, ptr3_bytes_allocated);
space->Free(self, ptr3);
@@ -354,30 +356,36 @@ void SpaceTest::AllocAndFreeListTestBody(CreateSpaceFn create_space) {
for (size_t i = 0; i < arraysize(lots_of_objects); i++) {
size_t allocation_size = 0;
lots_of_objects[i] = space->Alloc(self, 16, &allocation_size);
- EXPECT_TRUE(lots_of_objects[i] != NULL);
+ EXPECT_TRUE(lots_of_objects[i] != nullptr);
InstallClass(lots_of_objects[i], 16);
EXPECT_EQ(allocation_size, space->AllocationSize(lots_of_objects[i]));
}
- // Release memory and check pointers are NULL
- space->FreeList(self, arraysize(lots_of_objects), lots_of_objects);
- for (size_t i = 0; i < arraysize(lots_of_objects); i++) {
- EXPECT_TRUE(lots_of_objects[i] == NULL);
+ // Release memory and check pointers are NULL.
+ {
+ ScopedObjectAccess soa(self);
+ space->FreeList(self, arraysize(lots_of_objects), lots_of_objects);
+ for (size_t i = 0; i < arraysize(lots_of_objects); i++) {
+ EXPECT_TRUE(lots_of_objects[i] == nullptr);
+ }
}
// Succeeds, fits by adjusting the max allowed footprint.
for (size_t i = 0; i < arraysize(lots_of_objects); i++) {
size_t allocation_size = 0;
lots_of_objects[i] = space->AllocWithGrowth(self, 1024, &allocation_size);
- EXPECT_TRUE(lots_of_objects[i] != NULL);
+ EXPECT_TRUE(lots_of_objects[i] != nullptr);
InstallClass(lots_of_objects[i], 1024);
EXPECT_EQ(allocation_size, space->AllocationSize(lots_of_objects[i]));
}
// Release memory and check pointers are NULL
- space->FreeList(self, arraysize(lots_of_objects), lots_of_objects);
- for (size_t i = 0; i < arraysize(lots_of_objects); i++) {
- EXPECT_TRUE(lots_of_objects[i] == NULL);
+ {
+ ScopedObjectAccess soa(self);
+ space->FreeList(self, arraysize(lots_of_objects), lots_of_objects);
+ for (size_t i = 0; i < arraysize(lots_of_objects); i++) {
+ EXPECT_TRUE(lots_of_objects[i] == nullptr);
+ }
}
}
@@ -491,28 +499,30 @@ void SpaceTest::SizeFootPrintGrowthLimitAndTrimBody(MallocSpace* space, intptr_t
break;
}
- // Free some objects
- for (size_t i = 0; i < last_object; i += free_increment) {
- mirror::Object* object = lots_of_objects.get()[i];
- if (object == NULL) {
- continue;
- }
- size_t allocation_size = space->AllocationSize(object);
- if (object_size > 0) {
- EXPECT_GE(allocation_size, static_cast<size_t>(object_size));
- } else {
- EXPECT_GE(allocation_size, 8u);
+ {
+ // Free some objects
+ ScopedObjectAccess soa(self);
+ for (size_t i = 0; i < last_object; i += free_increment) {
+ mirror::Object* object = lots_of_objects.get()[i];
+ if (object == NULL) {
+ continue;
+ }
+ size_t allocation_size = space->AllocationSize(object);
+ if (object_size > 0) {
+ EXPECT_GE(allocation_size, static_cast<size_t>(object_size));
+ } else {
+ EXPECT_GE(allocation_size, 8u);
+ }
+ space->Free(self, object);
+ lots_of_objects.get()[i] = NULL;
+ amount_allocated -= allocation_size;
+ footprint = space->GetFootprint();
+ EXPECT_GE(space->Size(), footprint); // invariant
}
- space->Free(self, object);
- lots_of_objects.get()[i] = NULL;
- amount_allocated -= allocation_size;
- footprint = space->GetFootprint();
- EXPECT_GE(space->Size(), footprint); // invariant
- }
- free_increment >>= 1;
+ free_increment >>= 1;
+ }
}
-
// The space has become empty here before allocating a large object
// below. For RosAlloc, revoke thread-local runs, which are kept
// even when empty for a performance reason, so that they won't
@@ -540,8 +550,10 @@ void SpaceTest::SizeFootPrintGrowthLimitAndTrimBody(MallocSpace* space, intptr_t
EXPECT_LE(space->Size(), growth_limit);
// Clean up
- space->Free(self, large_object);
-
+ {
+ ScopedObjectAccess soa(self);
+ space->Free(self, large_object);
+ }
// Sanity check footprint
footprint = space->GetFootprint();
EXPECT_LE(footprint, growth_limit);
diff --git a/runtime/gc/space/zygote_space.h b/runtime/gc/space/zygote_space.h
index 10a5492..e0035b3 100644
--- a/runtime/gc/space/zygote_space.h
+++ b/runtime/gc/space/zygote_space.h
@@ -54,7 +54,7 @@ class ZygoteSpace : public ContinuousMemMapAllocSpace {
LOG(FATAL) << "Unimplemented";
return nullptr;
}
- virtual size_t AllocationSize(const mirror::Object* obj) {
+ virtual size_t AllocationSize(mirror::Object* obj) {
LOG(FATAL) << "Unimplemented";
return 0;
}
diff --git a/runtime/globals.h b/runtime/globals.h
index b1ccbdc..8c3ae56 100644
--- a/runtime/globals.h
+++ b/runtime/globals.h
@@ -36,7 +36,7 @@ static constexpr size_t kPointerSize = sizeof(void*);
static constexpr size_t kBitsPerByte = 8;
static constexpr size_t kBitsPerByteLog2 = 3;
static constexpr int kBitsPerWord = kWordSize * kBitsPerByte;
-static constexpr size_t kWordHighBitMask = 1 << (kBitsPerWord - 1);
+static constexpr size_t kWordHighBitMask = static_cast<size_t>(1) << (kBitsPerWord - 1);
// Required stack alignment
static constexpr size_t kStackAlignment = 16;
diff --git a/runtime/hprof/hprof.cc b/runtime/hprof/hprof.cc
index 9f899e8..24d403d 100644
--- a/runtime/hprof/hprof.cc
+++ b/runtime/hprof/hprof.cc
@@ -167,14 +167,8 @@ enum HprofBasicType {
hprof_basic_long = 11,
};
-typedef uint32_t HprofId;
-typedef HprofId HprofStringId;
-typedef HprofId HprofObjectId;
-typedef HprofId HprofClassObjectId;
-typedef std::set<mirror::Class*> ClassSet;
-typedef std::set<mirror::Class*>::iterator ClassSetIterator;
-typedef SafeMap<std::string, size_t> StringMap;
-typedef SafeMap<std::string, size_t>::iterator StringMapIterator;
+typedef uint32_t HprofStringId;
+typedef uint32_t HprofClassObjectId;
// Represents a top-level hprof record, whose serialized format is:
// U1 TAG: denoting the type of the record
@@ -183,11 +177,8 @@ typedef SafeMap<std::string, size_t>::iterator StringMapIterator;
// U1* BODY: as many bytes as specified in the above uint32_t field
class HprofRecord {
public:
- HprofRecord() {
- dirty_ = false;
- alloc_length_ = 128;
+ HprofRecord() : alloc_length_(128), fp_(nullptr), tag_(0), time_(0), length_(0), dirty_(false) {
body_ = reinterpret_cast<unsigned char*>(malloc(alloc_length_));
- fp_ = NULL;
}
~HprofRecord() {
@@ -233,7 +224,7 @@ class HprofRecord {
int AddU1(uint8_t value) {
int err = GuaranteeRecordAppend(1);
- if (err != 0) {
+ if (UNLIKELY(err != 0)) {
return err;
}
@@ -253,13 +244,30 @@ class HprofRecord {
return AddU8List(&value, 1);
}
- int AddId(HprofObjectId value) {
- return AddU4((uint32_t) value);
+ int AddObjectId(const mirror::Object* value) {
+ return AddU4(PointerToLowMemUInt32(value));
+ }
+
+ // The ID for the synthetic object generated to account for class static overhead.
+ int AddClassStaticsId(const mirror::Class* value) {
+ return AddU4(1 | PointerToLowMemUInt32(value));
+ }
+
+ int AddJniGlobalRefId(jobject value) {
+ return AddU4(PointerToLowMemUInt32(value));
+ }
+
+ int AddClassId(HprofClassObjectId value) {
+ return AddU4(value);
+ }
+
+ int AddStringId(HprofStringId value) {
+ return AddU4(value);
}
int AddU1List(const uint8_t* values, size_t numValues) {
int err = GuaranteeRecordAppend(numValues);
- if (err != 0) {
+ if (UNLIKELY(err != 0)) {
return err;
}
@@ -270,7 +278,7 @@ class HprofRecord {
int AddU2List(const uint16_t* values, size_t numValues) {
int err = GuaranteeRecordAppend(numValues * 2);
- if (err != 0) {
+ if (UNLIKELY(err != 0)) {
return err;
}
@@ -285,7 +293,7 @@ class HprofRecord {
int AddU4List(const uint32_t* values, size_t numValues) {
int err = GuaranteeRecordAppend(numValues * 4);
- if (err != 0) {
+ if (UNLIKELY(err != 0)) {
return err;
}
@@ -317,8 +325,16 @@ class HprofRecord {
return 0;
}
- int AddIdList(const HprofObjectId* values, size_t numValues) {
- return AddU4List((const uint32_t*) values, numValues);
+ int AddIdList(mirror::ObjectArray<mirror::Object>* values)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ int32_t length = values->GetLength();
+ for (int32_t i = 0; i < length; ++i) {
+ int err = AddObjectId(values->GetWithoutChecks(i));
+ if (UNLIKELY(err != 0)) {
+ return err;
+ }
+ }
+ return 0;
}
int AddUtf8String(const char* str) {
@@ -510,12 +526,11 @@ class Hprof {
HprofRecord* rec = &current_record_;
uint32_t nextSerialNumber = 1;
- for (ClassSetIterator it = classes_.begin(); it != classes_.end(); ++it) {
- const mirror::Class* c = *it;
- CHECK(c != NULL);
+ for (mirror::Class* c : classes_) {
+ CHECK(c != nullptr);
int err = current_record_.StartNewRecord(header_fp_, HPROF_TAG_LOAD_CLASS, HPROF_TIME);
- if (err != 0) {
+ if (UNLIKELY(err != 0)) {
return err;
}
@@ -525,9 +540,9 @@ class Hprof {
// U4: stack trace serial number
// ID: class name string ID
rec->AddU4(nextSerialNumber++);
- rec->AddId((HprofClassObjectId) c);
+ rec->AddObjectId(c);
rec->AddU4(HPROF_NULL_STACK_TRACE);
- rec->AddId(LookupClassNameId(c));
+ rec->AddStringId(LookupClassNameId(c));
}
return 0;
@@ -536,9 +551,9 @@ class Hprof {
int WriteStringTable() {
HprofRecord* rec = &current_record_;
- for (StringMapIterator it = strings_.begin(); it != strings_.end(); ++it) {
- const std::string& string = (*it).first;
- size_t id = (*it).second;
+ for (std::pair<std::string, HprofStringId> p : strings_) {
+ const std::string& string = p.first;
+ size_t id = p.second;
int err = current_record_.StartNewRecord(header_fp_, HPROF_TAG_STRING, HPROF_TIME);
if (err != 0) {
@@ -573,24 +588,26 @@ class Hprof {
int MarkRootObject(const mirror::Object* obj, jobject jniObj);
- HprofClassObjectId LookupClassId(mirror::Class* c)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (c == NULL) {
- // c is the superclass of java.lang.Object or a primitive
- return (HprofClassObjectId)0;
+ HprofClassObjectId LookupClassId(mirror::Class* c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ if (c == nullptr) {
+ // c is the superclass of java.lang.Object or a primitive.
+ return 0;
}
- std::pair<ClassSetIterator, bool> result = classes_.insert(c);
- const mirror::Class* present = *result.first;
+ {
+ auto result = classes_.insert(c);
+ const mirror::Class* present = *result.first;
+ CHECK_EQ(present, c);
+ }
// Make sure that we've assigned a string ID for this class' name
LookupClassNameId(c);
- CHECK_EQ(present, c);
- return (HprofStringId) present;
+ HprofClassObjectId result = PointerToLowMemUInt32(c);
+ return result;
}
- HprofStringId LookupStringId(mirror::String* string) {
+ HprofStringId LookupStringId(mirror::String* string) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return LookupStringId(string->ToModifiedUtf8());
}
@@ -599,7 +616,7 @@ class Hprof {
}
HprofStringId LookupStringId(const std::string& string) {
- StringMapIterator it = strings_.find(string);
+ auto it = strings_.find(string);
if (it != strings_.end()) {
return it->second;
}
@@ -608,8 +625,7 @@ class Hprof {
return id;
}
- HprofStringId LookupClassNameId(const mirror::Class* c)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ HprofStringId LookupClassNameId(mirror::Class* c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return LookupStringId(PrettyDescriptor(c));
}
@@ -675,9 +691,9 @@ class Hprof {
char* body_data_ptr_;
size_t body_data_size_;
- ClassSet classes_;
- size_t next_string_id_;
- StringMap strings_;
+ std::set<mirror::Class*> classes_;
+ HprofStringId next_string_id_;
+ SafeMap<std::string, HprofStringId> strings_;
DISALLOW_COPY_AND_ASSIGN(Hprof);
};
@@ -685,11 +701,8 @@ class Hprof {
#define OBJECTS_PER_SEGMENT ((size_t)128)
#define BYTES_PER_SEGMENT ((size_t)4096)
-// The static field-name for the synthetic object generated to account
-// for class static overhead.
+// The static field-name for the synthetic object generated to account for class static overhead.
#define STATIC_OVERHEAD_NAME "$staticOverhead"
-// The ID for the synthetic object generated to account for class static overhead.
-#define CLASS_STATICS_ID(c) ((HprofObjectId)(((uint32_t)(c)) | 1))
static HprofBasicType SignatureToBasicTypeAndSize(const char* sig, size_t* sizeOut) {
char c = sig[0];
@@ -765,15 +778,15 @@ int Hprof::MarkRootObject(const mirror::Object* obj, jobject jniObj) {
case HPROF_ROOT_DEBUGGER:
case HPROF_ROOT_VM_INTERNAL:
rec->AddU1(heapTag);
- rec->AddId((HprofObjectId)obj);
+ rec->AddObjectId(obj);
break;
// ID: object ID
// ID: JNI global ref ID
case HPROF_ROOT_JNI_GLOBAL:
rec->AddU1(heapTag);
- rec->AddId((HprofObjectId)obj);
- rec->AddId((HprofId)jniObj);
+ rec->AddObjectId(obj);
+ rec->AddJniGlobalRefId(jniObj);
break;
// ID: object ID
@@ -783,7 +796,7 @@ int Hprof::MarkRootObject(const mirror::Object* obj, jobject jniObj) {
case HPROF_ROOT_JNI_MONITOR:
case HPROF_ROOT_JAVA_FRAME:
rec->AddU1(heapTag);
- rec->AddId((HprofObjectId)obj);
+ rec->AddObjectId(obj);
rec->AddU4(gc_thread_serial_number_);
rec->AddU4((uint32_t)-1);
break;
@@ -793,7 +806,7 @@ int Hprof::MarkRootObject(const mirror::Object* obj, jobject jniObj) {
case HPROF_ROOT_NATIVE_STACK:
case HPROF_ROOT_THREAD_BLOCK:
rec->AddU1(heapTag);
- rec->AddId((HprofObjectId)obj);
+ rec->AddObjectId(obj);
rec->AddU4(gc_thread_serial_number_);
break;
@@ -802,7 +815,7 @@ int Hprof::MarkRootObject(const mirror::Object* obj, jobject jniObj) {
// U4: stack trace serial number
case HPROF_ROOT_THREAD_OBJECT:
rec->AddU1(heapTag);
- rec->AddId((HprofObjectId)obj);
+ rec->AddObjectId(obj);
rec->AddU4(gc_thread_serial_number_);
rec->AddU4((uint32_t)-1); // xxx
break;
@@ -859,7 +872,7 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
nameId = LookupStringId("<ILLEGAL>");
break;
}
- rec->AddId(nameId);
+ rec->AddStringId(nameId);
current_heap_ = desiredHeap;
}
@@ -875,11 +888,11 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
// obj is a ClassObject.
size_t sFieldCount = thisClass->NumStaticFields();
if (sFieldCount != 0) {
- int byteLength = sFieldCount*sizeof(JValue); // TODO bogus; fields are packed
+ int byteLength = sFieldCount * sizeof(JValue); // TODO bogus; fields are packed
// Create a byte array to reflect the allocation of the
// StaticField array at the end of this class.
rec->AddU1(HPROF_PRIMITIVE_ARRAY_DUMP);
- rec->AddId(CLASS_STATICS_ID(obj));
+ rec->AddClassStaticsId(thisClass);
rec->AddU4(StackTraceSerialNumber(obj));
rec->AddU4(byteLength);
rec->AddU1(hprof_basic_byte);
@@ -889,14 +902,14 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
}
rec->AddU1(HPROF_CLASS_DUMP);
- rec->AddId(LookupClassId(thisClass));
+ rec->AddClassId(LookupClassId(thisClass));
rec->AddU4(StackTraceSerialNumber(thisClass));
- rec->AddId(LookupClassId(thisClass->GetSuperClass()));
- rec->AddId((HprofObjectId)thisClass->GetClassLoader());
- rec->AddId((HprofObjectId)0); // no signer
- rec->AddId((HprofObjectId)0); // no prot domain
- rec->AddId((HprofId)0); // reserved
- rec->AddId((HprofId)0); // reserved
+ rec->AddClassId(LookupClassId(thisClass->GetSuperClass()));
+ rec->AddObjectId(thisClass->GetClassLoader());
+ rec->AddObjectId(nullptr); // no signer
+ rec->AddObjectId(nullptr); // no prot domain
+ rec->AddObjectId(nullptr); // reserved
+ rec->AddObjectId(nullptr); // reserved
if (thisClass->IsClassClass()) {
// ClassObjects have their static fields appended, so aren't all the same size.
// But they're at least this size.
@@ -916,9 +929,9 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
rec->AddU2((uint16_t)0);
} else {
rec->AddU2((uint16_t)(sFieldCount+1));
- rec->AddId(LookupStringId(STATIC_OVERHEAD_NAME));
+ rec->AddStringId(LookupStringId(STATIC_OVERHEAD_NAME));
rec->AddU1(hprof_basic_object);
- rec->AddId(CLASS_STATICS_ID(obj));
+ rec->AddClassStaticsId(thisClass);
for (size_t i = 0; i < sFieldCount; ++i) {
mirror::ArtField* f = thisClass->GetStaticField(i);
@@ -926,7 +939,7 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
size_t size;
HprofBasicType t = SignatureToBasicTypeAndSize(fh.GetTypeDescriptor(), &size);
- rec->AddId(LookupStringId(fh.GetName()));
+ rec->AddStringId(LookupStringId(fh.GetName()));
rec->AddU1(t);
if (size == 1) {
rec->AddU1(static_cast<uint8_t>(f->Get32(thisClass)));
@@ -949,24 +962,24 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
mirror::ArtField* f = thisClass->GetInstanceField(i);
fh.ChangeField(f);
HprofBasicType t = SignatureToBasicTypeAndSize(fh.GetTypeDescriptor(), NULL);
- rec->AddId(LookupStringId(fh.GetName()));
+ rec->AddStringId(LookupStringId(fh.GetName()));
rec->AddU1(t);
}
} else if (c->IsArrayClass()) {
- const mirror::Array* aobj = obj->AsArray();
+ mirror::Array* aobj = obj->AsArray();
uint32_t length = aobj->GetLength();
if (obj->IsObjectArray()) {
// obj is an object array.
rec->AddU1(HPROF_OBJECT_ARRAY_DUMP);
- rec->AddId((HprofObjectId)obj);
+ rec->AddObjectId(obj);
rec->AddU4(StackTraceSerialNumber(obj));
rec->AddU4(length);
- rec->AddId(LookupClassId(c));
+ rec->AddClassId(LookupClassId(c));
// Dump the elements, which are always objects or NULL.
- rec->AddIdList((const HprofObjectId*)aobj->GetRawData(sizeof(mirror::Object*)), length);
+ rec->AddIdList(aobj->AsObjectArray<mirror::Object>());
} else {
size_t size;
HprofBasicType t = PrimitiveToBasicTypeAndSize(c->GetComponentType()->GetPrimitiveType(), &size);
@@ -974,28 +987,28 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
// obj is a primitive array.
rec->AddU1(HPROF_PRIMITIVE_ARRAY_DUMP);
- rec->AddId((HprofObjectId)obj);
+ rec->AddObjectId(obj);
rec->AddU4(StackTraceSerialNumber(obj));
rec->AddU4(length);
rec->AddU1(t);
// Dump the raw, packed element values.
if (size == 1) {
- rec->AddU1List((const uint8_t*)aobj->GetRawData(sizeof(uint8_t)), length);
+ rec->AddU1List((const uint8_t*)aobj->GetRawData(sizeof(uint8_t), 0), length);
} else if (size == 2) {
- rec->AddU2List((const uint16_t*)aobj->GetRawData(sizeof(uint16_t)), length);
+ rec->AddU2List((const uint16_t*)aobj->GetRawData(sizeof(uint16_t), 0), length);
} else if (size == 4) {
- rec->AddU4List((const uint32_t*)aobj->GetRawData(sizeof(uint32_t)), length);
+ rec->AddU4List((const uint32_t*)aobj->GetRawData(sizeof(uint32_t), 0), length);
} else if (size == 8) {
- rec->AddU8List((const uint64_t*)aobj->GetRawData(sizeof(uint64_t)), length);
+ rec->AddU8List((const uint64_t*)aobj->GetRawData(sizeof(uint64_t), 0), length);
}
}
} else {
// obj is an instance object.
rec->AddU1(HPROF_INSTANCE_DUMP);
- rec->AddId((HprofObjectId)obj);
+ rec->AddObjectId(obj);
rec->AddU4(StackTraceSerialNumber(obj));
- rec->AddId(LookupClassId(c));
+ rec->AddClassId(LookupClassId(c));
// Reserve some space for the length of the instance data, which we won't
// know until we're done writing it.
@@ -1004,7 +1017,7 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
// Write the instance data; fields for this class, followed by super class fields,
// and so on. Don't write the klass or monitor fields of Object.class.
- const mirror::Class* sclass = c;
+ mirror::Class* sclass = c;
FieldHelper fh;
while (!sclass->IsObjectClass()) {
int ifieldCount = sclass->NumInstanceFields();
@@ -1019,10 +1032,9 @@ int Hprof::DumpHeapObject(mirror::Object* obj) {
rec->AddU2(f->Get32(obj));
} else if (size == 4) {
rec->AddU4(f->Get32(obj));
- } else if (size == 8) {
- rec->AddU8(f->Get64(obj));
} else {
- CHECK(false);
+ CHECK_EQ(size, 8U);
+ rec->AddU8(f->Get64(obj));
}
}
diff --git a/runtime/instruction_set.h b/runtime/instruction_set.h
index aee7447..ac83601 100644
--- a/runtime/instruction_set.h
+++ b/runtime/instruction_set.h
@@ -29,6 +29,7 @@ enum InstructionSet {
kArm,
kThumb2,
kX86,
+ kX86_64,
kMips
};
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 0b11543..59ffdc1 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -18,7 +18,7 @@
#include <sys/uio.h>
-#include "atomic_integer.h"
+#include "atomic.h"
#include "base/unix_file/fd_file.h"
#include "class_linker.h"
#include "debugger.h"
@@ -68,10 +68,21 @@ bool Instrumentation::InstallStubsForClass(mirror::Class* klass) {
return true;
}
-static void UpdateEntrypoints(mirror::ArtMethod* method, const void* code) {
- method->SetEntryPointFromCompiledCode(code);
+static void UpdateEntrypoints(mirror::ArtMethod* method, const void* quick_code,
+ const void* portable_code, bool have_portable_code)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ method->SetEntryPointFromPortableCompiledCode(portable_code);
+ method->SetEntryPointFromQuickCompiledCode(quick_code);
+ bool portable_enabled = method->IsPortableCompiled();
+ if (have_portable_code && !portable_enabled) {
+ method->SetIsPortableCompiled();
+ } else if (portable_enabled) {
+ method->ClearIsPortableCompiled();
+ }
if (!method->IsResolutionMethod()) {
- if (code == GetCompiledCodeToInterpreterBridge()) {
+ if (quick_code == GetQuickToInterpreterBridge()) {
+ DCHECK(portable_code == GetPortableToInterpreterBridge());
+ DCHECK(!method->IsNative()) << PrettyMethod(method);
method->SetEntryPointFromInterpreter(art::interpreter::artInterpreterToInterpreterBridge);
} else {
method->SetEntryPointFromInterpreter(art::artInterpreterToCompiledCodeBridge);
@@ -84,37 +95,47 @@ void Instrumentation::InstallStubsForMethod(mirror::ArtMethod* method) {
// Do not change stubs for these methods.
return;
}
- const void* new_code;
+ const void* new_portable_code;
+ const void* new_quick_code;
bool uninstall = !entry_exit_stubs_installed_ && !interpreter_stubs_installed_;
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
bool is_class_initialized = method->GetDeclaringClass()->IsInitialized();
+ bool have_portable_code = false;
if (uninstall) {
if ((forced_interpret_only_ || IsDeoptimized(method)) && !method->IsNative()) {
- new_code = GetCompiledCodeToInterpreterBridge();
+ new_portable_code = GetPortableToInterpreterBridge();
+ new_quick_code = GetQuickToInterpreterBridge();
} else if (is_class_initialized || !method->IsStatic() || method->IsConstructor()) {
- new_code = class_linker->GetOatCodeFor(method);
+ new_portable_code = class_linker->GetPortableOatCodeFor(method, &have_portable_code);
+ new_quick_code = class_linker->GetQuickOatCodeFor(method);
} else {
- new_code = GetResolutionTrampoline(class_linker);
+ new_portable_code = GetPortableResolutionTrampoline(class_linker);
+ new_quick_code = GetQuickResolutionTrampoline(class_linker);
}
} else { // !uninstall
if ((interpreter_stubs_installed_ || IsDeoptimized(method)) && !method->IsNative()) {
- new_code = GetCompiledCodeToInterpreterBridge();
+ new_portable_code = GetPortableToInterpreterBridge();
+ new_quick_code = GetQuickToInterpreterBridge();
} else {
// Do not overwrite resolution trampoline. When the trampoline initializes the method's
// class, all its static methods code will be set to the instrumentation entry point.
// For more details, see ClassLinker::FixupStaticTrampolines.
if (is_class_initialized || !method->IsStatic() || method->IsConstructor()) {
// Do not overwrite interpreter to prevent from posting method entry/exit events twice.
- new_code = class_linker->GetOatCodeFor(method);
- if (entry_exit_stubs_installed_ && new_code != GetCompiledCodeToInterpreterBridge()) {
- new_code = GetQuickInstrumentationEntryPoint();
+ new_portable_code = class_linker->GetPortableOatCodeFor(method, &have_portable_code);
+ new_quick_code = class_linker->GetQuickOatCodeFor(method);
+ if (entry_exit_stubs_installed_ && new_quick_code != GetQuickToInterpreterBridge()) {
+ DCHECK(new_portable_code != GetPortableToInterpreterBridge());
+ new_portable_code = GetPortableToInterpreterBridge();
+ new_quick_code = GetQuickInstrumentationEntryPoint();
}
} else {
- new_code = GetResolutionTrampoline(class_linker);
+ new_portable_code = GetPortableResolutionTrampoline(class_linker);
+ new_quick_code = GetQuickResolutionTrampoline(class_linker);
}
}
}
- UpdateEntrypoints(method, new_code);
+ UpdateEntrypoints(method, new_quick_code, new_portable_code, have_portable_code);
}
// Places the instrumentation exit pc as the return PC for every quick frame. This also allows
@@ -470,23 +491,38 @@ void Instrumentation::ResetQuickAllocEntryPoints() {
}
}
-void Instrumentation::UpdateMethodsCode(mirror::ArtMethod* method, const void* code) const {
- const void* new_code;
+void Instrumentation::UpdateMethodsCode(mirror::ArtMethod* method, const void* quick_code,
+ const void* portable_code, bool have_portable_code) const {
+ const void* new_portable_code;
+ const void* new_quick_code;
+ bool new_have_portable_code;
if (LIKELY(!instrumentation_stubs_installed_)) {
- new_code = code;
+ new_portable_code = portable_code;
+ new_quick_code = quick_code;
+ new_have_portable_code = have_portable_code;
} else {
if ((interpreter_stubs_installed_ || IsDeoptimized(method)) && !method->IsNative()) {
- new_code = GetCompiledCodeToInterpreterBridge();
- } else if (code == GetResolutionTrampoline(Runtime::Current()->GetClassLinker()) ||
- code == GetCompiledCodeToInterpreterBridge()) {
- new_code = code;
+ new_portable_code = GetPortableToInterpreterBridge();
+ new_quick_code = GetQuickToInterpreterBridge();
+ new_have_portable_code = false;
+ } else if (quick_code == GetQuickResolutionTrampoline(Runtime::Current()->GetClassLinker()) ||
+ quick_code == GetQuickToInterpreterBridge()) {
+ DCHECK((portable_code == GetPortableResolutionTrampoline(Runtime::Current()->GetClassLinker())) ||
+ (portable_code == GetPortableToInterpreterBridge()));
+ new_portable_code = portable_code;
+ new_quick_code = quick_code;
+ new_have_portable_code = have_portable_code;
} else if (entry_exit_stubs_installed_) {
- new_code = GetQuickInstrumentationEntryPoint();
+ new_quick_code = GetQuickInstrumentationEntryPoint();
+ new_portable_code = GetPortableToInterpreterBridge();
+ new_have_portable_code = false;
} else {
- new_code = code;
+ new_portable_code = portable_code;
+ new_quick_code = quick_code;
+ new_have_portable_code = have_portable_code;
}
}
- UpdateEntrypoints(method, new_code);
+ UpdateEntrypoints(method, new_quick_code, new_portable_code, new_have_portable_code);
}
void Instrumentation::Deoptimize(mirror::ArtMethod* method) {
@@ -499,7 +535,8 @@ void Instrumentation::Deoptimize(mirror::ArtMethod* method) {
CHECK(!already_deoptimized) << "Method " << PrettyMethod(method) << " is already deoptimized";
if (!interpreter_stubs_installed_) {
- UpdateEntrypoints(method, GetCompiledCodeToInterpreterBridge());
+ UpdateEntrypoints(method, GetQuickToInterpreterBridge(), GetPortableToInterpreterBridge(),
+ false);
// Install instrumentation exit stub and instrumentation frames. We may already have installed
// these previously so it will only cover the newly created frames.
@@ -522,10 +559,15 @@ void Instrumentation::Undeoptimize(mirror::ArtMethod* method) {
if (!interpreter_stubs_installed_) {
// Restore its code or resolution trampoline.
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- if (method->IsStatic() && !method->IsConstructor() && !method->GetDeclaringClass()->IsInitialized()) {
- UpdateEntrypoints(method, GetResolutionTrampoline(class_linker));
+ if (method->IsStatic() && !method->IsConstructor() &&
+ !method->GetDeclaringClass()->IsInitialized()) {
+ UpdateEntrypoints(method, GetQuickResolutionTrampoline(class_linker),
+ GetPortableResolutionTrampoline(class_linker), false);
} else {
- UpdateEntrypoints(method, class_linker->GetOatCodeFor(method));
+ bool have_portable_code = false;
+ const void* quick_code = class_linker->GetQuickOatCodeFor(method);
+ const void* portable_code = class_linker->GetPortableOatCodeFor(method, &have_portable_code);
+ UpdateEntrypoints(method, quick_code, portable_code, have_portable_code);
}
// If there is no deoptimized method left, we can restore the stack of each thread.
@@ -582,21 +624,21 @@ void Instrumentation::DisableMethodTracing() {
ConfigureStubs(false, false);
}
-const void* Instrumentation::GetQuickCodeFor(const mirror::ArtMethod* method) const {
+const void* Instrumentation::GetQuickCodeFor(mirror::ArtMethod* method) const {
Runtime* runtime = Runtime::Current();
if (LIKELY(!instrumentation_stubs_installed_)) {
- const void* code = method->GetEntryPointFromCompiledCode();
+ const void* code = method->GetEntryPointFromQuickCompiledCode();
DCHECK(code != NULL);
if (LIKELY(code != GetQuickResolutionTrampoline(runtime->GetClassLinker()) &&
code != GetQuickToInterpreterBridge())) {
return code;
}
}
- return runtime->GetClassLinker()->GetOatCodeFor(method);
+ return runtime->GetClassLinker()->GetQuickOatCodeFor(method);
}
void Instrumentation::MethodEnterEventImpl(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method,
+ mirror::ArtMethod* method,
uint32_t dex_pc) const {
auto it = method_entry_listeners_.begin();
bool is_end = (it == method_entry_listeners_.end());
@@ -610,7 +652,7 @@ void Instrumentation::MethodEnterEventImpl(Thread* thread, mirror::Object* this_
}
void Instrumentation::MethodExitEventImpl(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method,
+ mirror::ArtMethod* method,
uint32_t dex_pc, const JValue& return_value) const {
auto it = method_exit_listeners_.begin();
bool is_end = (it == method_exit_listeners_.end());
@@ -624,7 +666,7 @@ void Instrumentation::MethodExitEventImpl(Thread* thread, mirror::Object* this_o
}
void Instrumentation::MethodUnwindEvent(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method,
+ mirror::ArtMethod* method,
uint32_t dex_pc) const {
if (have_method_unwind_listeners_) {
for (InstrumentationListener* listener : method_unwind_listeners_) {
@@ -634,7 +676,7 @@ void Instrumentation::MethodUnwindEvent(Thread* thread, mirror::Object* this_obj
}
void Instrumentation::DexPcMovedEventImpl(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method,
+ mirror::ArtMethod* method,
uint32_t dex_pc) const {
// TODO: STL copy-on-write collection? The copy below is due to the debug listener having an
// action where it can remove itself as a listener and break the iterator. The copy only works
diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h
index 41b545d..f01add1 100644
--- a/runtime/instrumentation.h
+++ b/runtime/instrumentation.h
@@ -17,7 +17,7 @@
#ifndef ART_RUNTIME_INSTRUMENTATION_H_
#define ART_RUNTIME_INSTRUMENTATION_H_
-#include "atomic_integer.h"
+#include "atomic.h"
#include "base/macros.h"
#include "locks.h"
@@ -55,26 +55,26 @@ struct InstrumentationListener {
// Call-back for when a method is entered.
virtual void MethodEntered(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method,
+ mirror::ArtMethod* method,
uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
// Call-back for when a method is exited.
// TODO: its likely passing the return value would be useful, however, we may need to get and
// parse the shorty to determine what kind of register holds the result.
virtual void MethodExited(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc,
+ mirror::ArtMethod* method, uint32_t dex_pc,
const JValue& return_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
// Call-back for when a method is popped due to an exception throw. A method will either cause a
// MethodExited call-back or a MethodUnwind call-back when its activation is removed.
virtual void MethodUnwind(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc)
+ mirror::ArtMethod* method, uint32_t dex_pc)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
// Call-back for when the dex pc moves in a method.
virtual void DexPcMoved(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t new_dex_pc)
+ mirror::ArtMethod* method, uint32_t new_dex_pc)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
// Call-back when an exception is caught.
@@ -171,13 +171,14 @@ class Instrumentation {
void ResetQuickAllocEntryPoints();
// Update the code of a method respecting any installed stubs.
- void UpdateMethodsCode(mirror::ArtMethod* method, const void* code) const
+ void UpdateMethodsCode(mirror::ArtMethod* method, const void* quick_code,
+ const void* portable_code, bool have_portable_code) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Get the quick code for the given method. More efficient than asking the class linker as it
// will short-cut to GetCode if instrumentation and static method resolution stubs aren't
// installed.
- const void* GetQuickCodeFor(const mirror::ArtMethod* method) const
+ const void* GetQuickCodeFor(mirror::ArtMethod* method) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void ForceInterpretOnly() {
@@ -218,7 +219,7 @@ class Instrumentation {
// Inform listeners that a method has been entered. A dex PC is provided as we may install
// listeners into executing code and get method enter events for methods already on the stack.
void MethodEnterEvent(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc) const
+ mirror::ArtMethod* method, uint32_t dex_pc) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (UNLIKELY(HasMethodEntryListeners())) {
MethodEnterEventImpl(thread, this_object, method, dex_pc);
@@ -227,7 +228,7 @@ class Instrumentation {
// Inform listeners that a method has been exited.
void MethodExitEvent(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc,
+ mirror::ArtMethod* method, uint32_t dex_pc,
const JValue& return_value) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (UNLIKELY(HasMethodExitListeners())) {
@@ -237,12 +238,12 @@ class Instrumentation {
// Inform listeners that a method has been exited due to an exception.
void MethodUnwindEvent(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc) const
+ mirror::ArtMethod* method, uint32_t dex_pc) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Inform listeners that the dex pc has moved (only supported by the interpreter).
void DexPcMovedEvent(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc) const
+ mirror::ArtMethod* method, uint32_t dex_pc) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (UNLIKELY(HasDexPcListeners())) {
DexPcMovedEventImpl(thread, this_object, method, dex_pc);
@@ -289,14 +290,14 @@ class Instrumentation {
}
void MethodEnterEventImpl(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc) const
+ mirror::ArtMethod* method, uint32_t dex_pc) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void MethodExitEventImpl(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method,
+ mirror::ArtMethod* method,
uint32_t dex_pc, const JValue& return_value) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void DexPcMovedEventImpl(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc) const
+ mirror::ArtMethod* method, uint32_t dex_pc) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Have we hijacked ArtMethod::code_ so that it calls instrumentation/interpreter code?
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index f574a0f..02a9aa6 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -356,7 +356,7 @@ void EnterInterpreterFromInvoke(Thread* self, ArtMethod* method, Object* receive
DCHECK_LT(shorty_pos + 1, mh.GetShortyLength());
switch (shorty[shorty_pos + 1]) {
case 'L': {
- Object* o = reinterpret_cast<Object*>(args[arg_pos]);
+ Object* o = reinterpret_cast<StackReference<Object>*>(&args[arg_pos])->AsMirrorPtr();
shadow_frame->SetVRegReference(cur_reg, o);
break;
}
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 0f94ccd..0b959fb 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -25,15 +25,16 @@ static void UnstartedRuntimeInvoke(Thread* self, MethodHelper& mh,
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Assign register 'src_reg' from shadow_frame to register 'dest_reg' into new_shadow_frame.
-static inline void AssignRegister(ShadowFrame& new_shadow_frame, const ShadowFrame& shadow_frame,
- size_t dest_reg, size_t src_reg) {
+static inline void AssignRegister(ShadowFrame* new_shadow_frame, const ShadowFrame& shadow_frame,
+ size_t dest_reg, size_t src_reg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// If both register locations contains the same value, the register probably holds a reference.
int32_t src_value = shadow_frame.GetVReg(src_reg);
mirror::Object* o = shadow_frame.GetVRegReference<false>(src_reg);
- if (src_value == reinterpret_cast<int32_t>(o)) {
- new_shadow_frame.SetVRegReference(dest_reg, o);
+ if (src_value == reinterpret_cast<intptr_t>(o)) {
+ new_shadow_frame->SetVRegReference(dest_reg, o);
} else {
- new_shadow_frame.SetVReg(dest_reg, src_value);
+ new_shadow_frame->SetVReg(dest_reg, src_value);
}
}
@@ -84,7 +85,7 @@ bool DoCall(ArtMethod* method, Thread* self, ShadowFrame& shadow_frame,
++dest_reg;
++arg_offset;
}
- for (size_t shorty_pos = 0; dest_reg < num_regs; ++shorty_pos, ++dest_reg, ++arg_offset) {
+ for (uint32_t shorty_pos = 0; dest_reg < num_regs; ++shorty_pos, ++dest_reg, ++arg_offset) {
DCHECK_LT(shorty_pos + 1, mh.GetShortyLength());
const size_t src_reg = (is_range) ? vregC + arg_offset : arg[arg_offset];
switch (shorty[shorty_pos + 1]) {
@@ -131,18 +132,18 @@ bool DoCall(ArtMethod* method, Thread* self, ShadowFrame& shadow_frame,
const uint16_t first_src_reg = inst->VRegC_3rc();
for (size_t src_reg = first_src_reg, dest_reg = first_dest_reg; dest_reg < num_regs;
++dest_reg, ++src_reg) {
- AssignRegister(*new_shadow_frame, shadow_frame, dest_reg, src_reg);
+ AssignRegister(new_shadow_frame, shadow_frame, dest_reg, src_reg);
}
} else {
DCHECK_LE(num_ins, 5U);
uint16_t regList = inst->Fetch16(2);
uint16_t count = num_ins;
if (count == 5) {
- AssignRegister(*new_shadow_frame, shadow_frame, first_dest_reg + 4U, (inst_data >> 8) & 0x0f);
+ AssignRegister(new_shadow_frame, shadow_frame, first_dest_reg + 4U, (inst_data >> 8) & 0x0f);
--count;
}
for (size_t arg_index = 0; arg_index < count; ++arg_index, regList >>= 4) {
- AssignRegister(*new_shadow_frame, shadow_frame, first_dest_reg + arg_index, regList & 0x0f);
+ AssignRegister(new_shadow_frame, shadow_frame, first_dest_reg + arg_index, regList & 0x0f);
}
}
}
@@ -289,7 +290,7 @@ static void UnstartedRuntimeInvoke(Thread* self, MethodHelper& mh,
CHECK(field.get() != NULL);
ArtMethod* c = jlr_Field->FindDeclaredDirectMethod("<init>", "(Ljava/lang/reflect/ArtField;)V");
uint32_t args[1];
- args[0] = reinterpret_cast<uint32_t>(found);
+ args[0] = StackReference<mirror::Object>::FromMirrorPtr(found).AsVRegValue();
EnterInterpreterFromInvoke(self, c, field.get(), args, NULL);
result->SetL(field.get());
} else if (name == "void java.lang.System.arraycopy(java.lang.Object, int, java.lang.Object, int, int)" ||
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index 4481210..768ca33 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -218,7 +218,7 @@ static inline bool DoIGetQuick(ShadowFrame& shadow_frame, const Instruction* ins
shadow_frame.SetVRegLong(vregA, static_cast<int64_t>(obj->GetField64(field_offset, is_volatile)));
break;
case Primitive::kPrimNot:
- shadow_frame.SetVRegReference(vregA, obj->GetFieldObject<mirror::Object*>(field_offset, is_volatile));
+ shadow_frame.SetVRegReference(vregA, obj->GetFieldObject<mirror::Object>(field_offset, is_volatile));
break;
default:
LOG(FATAL) << "Unreachable: " << field_type;
@@ -529,10 +529,10 @@ static inline void TraceExecution(const ShadowFrame& shadow_frame, const Instruc
oss << PrettyMethod(shadow_frame.GetMethod())
<< StringPrintf("\n0x%x: ", dex_pc)
<< inst->DumpString(&mh.GetDexFile()) << "\n";
- for (size_t i = 0; i < shadow_frame.NumberOfVRegs(); ++i) {
+ for (uint32_t i = 0; i < shadow_frame.NumberOfVRegs(); ++i) {
uint32_t raw_value = shadow_frame.GetVReg(i);
Object* ref_value = shadow_frame.GetVRegReference(i);
- oss << StringPrintf(" vreg%d=0x%08X", i, raw_value);
+ oss << StringPrintf(" vreg%u=0x%08X", i, raw_value);
if (ref_value != NULL) {
if (ref_value->GetClass()->IsStringClass() &&
ref_value->AsString()->GetCharArray() != NULL) {
diff --git a/runtime/interpreter/interpreter_goto_table_impl.cc b/runtime/interpreter/interpreter_goto_table_impl.cc
index ca03885..e8504b7 100644
--- a/runtime/interpreter/interpreter_goto_table_impl.cc
+++ b/runtime/interpreter/interpreter_goto_table_impl.cc
@@ -568,7 +568,7 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
HANDLE_PENDING_EXCEPTION();
} else {
uint32_t size_in_bytes = payload->element_count * payload->element_width;
- memcpy(array->GetRawData(payload->element_width), payload->data, size_in_bytes);
+ memcpy(array->GetRawData(payload->element_width, 0), payload->data, size_in_bytes);
ADVANCE(3);
}
}
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc
index 7631736..e5d15b1 100644
--- a/runtime/interpreter/interpreter_switch_impl.cc
+++ b/runtime/interpreter/interpreter_switch_impl.cc
@@ -483,7 +483,7 @@ JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem
break;
}
uint32_t size_in_bytes = payload->element_count * payload->element_width;
- memcpy(array->GetRawData(payload->element_width), payload->data, size_in_bytes);
+ memcpy(array->GetRawData(payload->element_width, 0), payload->data, size_in_bytes);
inst = inst->Next_3xx();
break;
}
diff --git a/runtime/invoke_arg_array_builder.h b/runtime/invoke_arg_array_builder.h
index f615e8e..6ecce40 100644
--- a/runtime/invoke_arg_array_builder.h
+++ b/runtime/invoke_arg_array_builder.h
@@ -78,6 +78,10 @@ class ArgArray {
num_bytes_ += 4;
}
+ void Append(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ Append(StackReference<mirror::Object>::FromMirrorPtr(obj).AsVRegValue());
+ }
+
void AppendWide(uint64_t value) {
// For ARM and MIPS portable, align wide values to 8 bytes (ArgArray starts at offset of 4).
#if defined(ART_USE_PORTABLE_COMPILER) && (defined(__arm__) || defined(__mips__))
@@ -93,8 +97,8 @@ class ArgArray {
void BuildArgArray(const ScopedObjectAccess& soa, mirror::Object* receiver, va_list ap)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Set receiver if non-null (method is not static)
- if (receiver != NULL) {
- Append(reinterpret_cast<int32_t>(receiver));
+ if (receiver != nullptr) {
+ Append(receiver);
}
for (size_t i = 1; i < shorty_len_; ++i) {
switch (shorty_[i]) {
@@ -112,7 +116,7 @@ class ArgArray {
break;
}
case 'L':
- Append(reinterpret_cast<int32_t>(soa.Decode<mirror::Object*>(va_arg(ap, jobject))));
+ Append(soa.Decode<mirror::Object*>(va_arg(ap, jobject)));
break;
case 'D': {
JValue value;
@@ -131,8 +135,8 @@ class ArgArray {
void BuildArgArray(const ScopedObjectAccess& soa, mirror::Object* receiver, jvalue* args)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Set receiver if non-null (method is not static)
- if (receiver != NULL) {
- Append(reinterpret_cast<int32_t>(receiver));
+ if (receiver != nullptr) {
+ Append(receiver);
}
for (size_t i = 1, args_offset = 0; i < shorty_len_; ++i, ++args_offset) {
switch (shorty_[i]) {
@@ -153,7 +157,7 @@ class ArgArray {
Append(args[args_offset].i);
break;
case 'L':
- Append(reinterpret_cast<int32_t>(soa.Decode<mirror::Object*>(args[args_offset].l)));
+ Append(soa.Decode<mirror::Object*>(args[args_offset].l));
break;
case 'D':
case 'J':
diff --git a/runtime/jdwp/jdwp.h b/runtime/jdwp/jdwp.h
index ebc844e..334dca4 100644
--- a/runtime/jdwp/jdwp.h
+++ b/runtime/jdwp/jdwp.h
@@ -17,7 +17,7 @@
#ifndef ART_RUNTIME_JDWP_JDWP_H_
#define ART_RUNTIME_JDWP_JDWP_H_
-#include "atomic_integer.h"
+#include "atomic.h"
#include "base/mutex.h"
#include "jdwp/jdwp_bits.h"
#include "jdwp/jdwp_constants.h"
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 5cd09c2..deea5f6 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -22,7 +22,7 @@
#include <utility>
#include <vector>
-#include "atomic_integer.h"
+#include "atomic.h"
#include "base/logging.h"
#include "base/mutex.h"
#include "base/stl_util.h"
@@ -590,7 +590,7 @@ class Libraries {
}
// See section 11.3 "Linking Native Methods" of the JNI spec.
- void* FindNativeMethod(const ArtMethod* m, std::string& detail)
+ void* FindNativeMethod(ArtMethod* m, std::string& detail)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
std::string jni_short_name(JniShortName(m));
std::string jni_long_name(JniLongName(m));
@@ -2215,7 +2215,7 @@ class JNI {
if (is_copy != nullptr) {
*is_copy = JNI_FALSE;
}
- return array->GetRawData(array->GetClass()->GetComponentSize());
+ return array->GetRawData(array->GetClass()->GetComponentSize(), 0);
}
static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* elements, jint mode) {
@@ -2518,10 +2518,10 @@ class JNI {
static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
if (capacity < 0) {
- JniAbortF("NewDirectByteBuffer", "negative buffer capacity: %lld", capacity);
+ JniAbortF("NewDirectByteBuffer", "negative buffer capacity: %" PRId64, capacity);
}
if (address == NULL && capacity != 0) {
- JniAbortF("NewDirectByteBuffer", "non-zero capacity for NULL pointer: %lld", capacity);
+ JniAbortF("NewDirectByteBuffer", "non-zero capacity for NULL pointer: %" PRId64, capacity);
}
// At the moment, the Java side is limited to 32 bits.
@@ -2644,7 +2644,7 @@ class JNI {
ScopedObjectAccess soa(env);
Array* array = soa.Decode<Array*>(java_array);
size_t component_size = array->GetClass()->GetComponentSize();
- void* array_data = array->GetRawData(component_size);
+ void* array_data = array->GetRawData(component_size, 0);
gc::Heap* heap = Runtime::Current()->GetHeap();
bool is_copy = array_data != reinterpret_cast<void*>(elements);
size_t bytes = array->GetLength() * component_size;
@@ -2944,10 +2944,6 @@ JNIEnvExt::JNIEnvExt(Thread* self, JavaVMExt* vm)
if (vm->check_jni) {
SetCheckJniEnabled(true);
}
- // The JniEnv local reference values must be at a consistent offset or else cross-compilation
- // errors will ensue.
- CHECK_EQ(JNIEnvExt::LocalRefCookieOffset().Int32Value(), 12);
- CHECK_EQ(JNIEnvExt::SegmentStateOffset().Int32Value(), 16);
}
JNIEnvExt::~JNIEnvExt() {
diff --git a/runtime/jni_internal_test.cc b/runtime/jni_internal_test.cc
index 9b278f8..fed734e 100644
--- a/runtime/jni_internal_test.cc
+++ b/runtime/jni_internal_test.cc
@@ -131,7 +131,7 @@ class JniInternalTest : public CommonTest {
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
}
method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'V');
@@ -148,11 +148,11 @@ class JniInternalTest : public CommonTest {
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
- arg_array.Append(0);
+ arg_array.Append(0U);
result.SetB(-1);
method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'B');
EXPECT_EQ(0, result.GetB());
@@ -184,11 +184,11 @@ class JniInternalTest : public CommonTest {
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
- arg_array.Append(0);
+ arg_array.Append(0U);
result.SetI(-1);
method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
EXPECT_EQ(0, result.GetI());
@@ -221,7 +221,7 @@ class JniInternalTest : public CommonTest {
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
@@ -264,12 +264,12 @@ class JniInternalTest : public CommonTest {
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
- arg_array.Append(0);
- arg_array.Append(0);
+ arg_array.Append(0U);
+ arg_array.Append(0U);
result.SetI(-1);
method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
EXPECT_EQ(0, result.GetI());
@@ -310,13 +310,13 @@ class JniInternalTest : public CommonTest {
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
- arg_array.Append(0);
- arg_array.Append(0);
- arg_array.Append(0);
+ arg_array.Append(0U);
+ arg_array.Append(0U);
+ arg_array.Append(0U);
result.SetI(-1);
method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
EXPECT_EQ(0, result.GetI());
@@ -361,14 +361,14 @@ class JniInternalTest : public CommonTest {
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
- arg_array.Append(0);
- arg_array.Append(0);
- arg_array.Append(0);
- arg_array.Append(0);
+ arg_array.Append(0U);
+ arg_array.Append(0U);
+ arg_array.Append(0U);
+ arg_array.Append(0U);
result.SetI(-1);
method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
EXPECT_EQ(0, result.GetI());
@@ -417,15 +417,15 @@ class JniInternalTest : public CommonTest {
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
- arg_array.Append(0);
- arg_array.Append(0);
- arg_array.Append(0);
- arg_array.Append(0);
- arg_array.Append(0);
+ arg_array.Append(0U);
+ arg_array.Append(0U);
+ arg_array.Append(0U);
+ arg_array.Append(0U);
+ arg_array.Append(0U);
result.SetI(-1.0);
method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
EXPECT_EQ(0, result.GetI());
@@ -480,7 +480,7 @@ class JniInternalTest : public CommonTest {
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
@@ -547,7 +547,7 @@ class JniInternalTest : public CommonTest {
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
@@ -603,7 +603,7 @@ class JniInternalTest : public CommonTest {
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
@@ -668,7 +668,7 @@ class JniInternalTest : public CommonTest {
JValue result;
if (!is_static) {
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
args++;
}
@@ -1492,8 +1492,8 @@ TEST_F(JniInternalTest, GetObjectArrayElement_SetObjectArrayElement) {
} while (false)
-#if !defined(ART_USE_PORTABLE_COMPILER)
TEST_F(JniInternalTest, GetPrimitiveField_SetPrimitiveField) {
+ TEST_DISABLED_FOR_PORTABLE();
Thread::Current()->TransitionFromSuspendedToRunnable();
LoadDex("AllFields");
bool started = runtime_->Start();
@@ -1524,6 +1524,7 @@ TEST_F(JniInternalTest, GetPrimitiveField_SetPrimitiveField) {
}
TEST_F(JniInternalTest, GetObjectField_SetObjectField) {
+ TEST_DISABLED_FOR_PORTABLE();
Thread::Current()->TransitionFromSuspendedToRunnable();
LoadDex("AllFields");
runtime_->Start();
@@ -1553,7 +1554,6 @@ TEST_F(JniInternalTest, GetObjectField_SetObjectField) {
env_->SetObjectField(o, i_fid, s2);
ASSERT_TRUE(env_->IsSameObject(s2, env_->GetObjectField(o, i_fid)));
}
-#endif
TEST_F(JniInternalTest, NewLocalRef_NULL) {
EXPECT_TRUE(env_->NewLocalRef(NULL) == NULL);
@@ -1756,7 +1756,7 @@ TEST_F(JniInternalTest, StaticMainMethod) {
ASSERT_TRUE(method != NULL);
ArgArray arg_array(NULL, 0);
- arg_array.Append(0);
+ arg_array.Append(0U);
JValue result;
// Start runtime.
diff --git a/runtime/lock_word-inl.h b/runtime/lock_word-inl.h
index 8b9a3cd..414b3bb 100644
--- a/runtime/lock_word-inl.h
+++ b/runtime/lock_word-inl.h
@@ -18,6 +18,7 @@
#define ART_RUNTIME_LOCK_WORD_INL_H_
#include "lock_word.h"
+#include "monitor_pool.h"
namespace art {
@@ -33,7 +34,8 @@ inline uint32_t LockWord::ThinLockCount() const {
inline Monitor* LockWord::FatLockMonitor() const {
DCHECK_EQ(GetState(), kFatLocked);
- return reinterpret_cast<Monitor*>(value_ << kStateSize);
+ MonitorId mon_id = static_cast<MonitorId>(value_ & ~(kStateMask << kStateShift));
+ return MonitorPool::MonitorFromMonitorId(mon_id);
}
inline size_t LockWord::ForwardingAddress() const {
@@ -46,8 +48,7 @@ inline LockWord::LockWord() : value_(0) {
}
inline LockWord::LockWord(Monitor* mon)
- : value_(((reinterpret_cast<uintptr_t>(mon) >> kStateSize) | (kStateFat << kStateShift)) &
- 0xFFFFFFFFU) {
+ : value_(mon->GetMonitorId() | (kStateFat << kStateShift)) {
DCHECK_EQ(FatLockMonitor(), mon);
}
diff --git a/runtime/lock_word.h b/runtime/lock_word.h
index d24a3bb..ab86eaa 100644
--- a/runtime/lock_word.h
+++ b/runtime/lock_word.h
@@ -42,7 +42,7 @@ class Monitor;
*
* |33|222222222211111111110000000000|
* |10|987654321098765432109876543210|
- * |01| Monitor* >> kStateSize |
+ * |01| MonitorId |
*
* When the lock word is in hash state and its bits are formatted as follows:
*
diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc
index 2795e1d..393ea68 100644
--- a/runtime/mem_map.cc
+++ b/runtime/mem_map.cc
@@ -79,7 +79,7 @@ static void CheckMapRequest(byte*, size_t) { }
#endif
MemMap* MemMap::MapAnonymous(const char* name, byte* addr, size_t byte_count, int prot,
- std::string* error_msg) {
+ bool low_4gb, std::string* error_msg) {
if (byte_count == 0) {
return new MemMap(name, NULL, 0, NULL, 0, prot);
}
@@ -101,7 +101,11 @@ MemMap* MemMap::MapAnonymous(const char* name, byte* addr, size_t byte_count, in
ScopedFd fd(-1);
int flags = MAP_PRIVATE | MAP_ANONYMOUS;
#endif
-
+#ifdef __LP64__
+ if (low_4gb) {
+ flags |= MAP_32BIT;
+ }
+#endif
byte* actual = reinterpret_cast<byte*>(mmap(addr, page_aligned_byte_count, prot, flags, fd.get(), 0));
if (actual == MAP_FAILED) {
std::string maps;
diff --git a/runtime/mem_map.h b/runtime/mem_map.h
index d2059b5..e39c10e 100644
--- a/runtime/mem_map.h
+++ b/runtime/mem_map.h
@@ -39,7 +39,7 @@ class MemMap {
//
// On success, returns returns a MemMap instance. On failure, returns a NULL;
static MemMap* MapAnonymous(const char* ashmem_name, byte* addr, size_t byte_count, int prot,
- std::string* error_msg);
+ bool low_4gb, std::string* error_msg);
// Map part of a file, taking care of non-page aligned offsets. The
// "start" offset is absolute, not relative.
diff --git a/runtime/mem_map_test.cc b/runtime/mem_map_test.cc
index cf2c9d0..6cb59b4 100644
--- a/runtime/mem_map_test.cc
+++ b/runtime/mem_map_test.cc
@@ -23,76 +23,111 @@ namespace art {
class MemMapTest : public testing::Test {
public:
- byte* BaseBegin(MemMap* mem_map) {
+ static byte* BaseBegin(MemMap* mem_map) {
return reinterpret_cast<byte*>(mem_map->base_begin_);
}
- size_t BaseSize(MemMap* mem_map) {
+ static size_t BaseSize(MemMap* mem_map) {
return mem_map->base_size_;
}
+
+ static void RemapAtEndTest(bool low_4gb) {
+ std::string error_msg;
+ // Cast the page size to size_t.
+ const size_t page_size = static_cast<size_t>(kPageSize);
+ // Map a two-page memory region.
+ MemMap* m0 = MemMap::MapAnonymous("MemMapTest_RemapAtEndTest_map0",
+ nullptr,
+ 2 * page_size,
+ PROT_READ | PROT_WRITE,
+ low_4gb,
+ &error_msg);
+ // Check its state and write to it.
+ byte* base0 = m0->Begin();
+ ASSERT_TRUE(base0 != nullptr) << error_msg;
+ size_t size0 = m0->Size();
+ EXPECT_EQ(m0->Size(), 2 * page_size);
+ EXPECT_EQ(BaseBegin(m0), base0);
+ EXPECT_EQ(BaseSize(m0), size0);
+ memset(base0, 42, 2 * page_size);
+ // Remap the latter half into a second MemMap.
+ MemMap* m1 = m0->RemapAtEnd(base0 + page_size,
+ "MemMapTest_RemapAtEndTest_map1",
+ PROT_READ | PROT_WRITE,
+ &error_msg);
+ // Check the states of the two maps.
+ EXPECT_EQ(m0->Begin(), base0) << error_msg;
+ EXPECT_EQ(m0->Size(), page_size);
+ EXPECT_EQ(BaseBegin(m0), base0);
+ EXPECT_EQ(BaseSize(m0), page_size);
+ byte* base1 = m1->Begin();
+ size_t size1 = m1->Size();
+ EXPECT_EQ(base1, base0 + page_size);
+ EXPECT_EQ(size1, page_size);
+ EXPECT_EQ(BaseBegin(m1), base1);
+ EXPECT_EQ(BaseSize(m1), size1);
+ // Write to the second region.
+ memset(base1, 43, page_size);
+ // Check the contents of the two regions.
+ for (size_t i = 0; i < page_size; ++i) {
+ EXPECT_EQ(base0[i], 42);
+ }
+ for (size_t i = 0; i < page_size; ++i) {
+ EXPECT_EQ(base1[i], 43);
+ }
+ // Unmap the first region.
+ delete m0;
+ // Make sure the second region is still accessible after the first
+ // region is unmapped.
+ for (size_t i = 0; i < page_size; ++i) {
+ EXPECT_EQ(base1[i], 43);
+ }
+ delete m1;
+ }
};
TEST_F(MemMapTest, MapAnonymousEmpty) {
std::string error_msg;
UniquePtr<MemMap> map(MemMap::MapAnonymous("MapAnonymousEmpty",
- NULL,
+ nullptr,
0,
PROT_READ,
+ false,
&error_msg));
- ASSERT_TRUE(map.get() != NULL) << error_msg;
+ ASSERT_TRUE(map.get() != nullptr) << error_msg;
+ ASSERT_TRUE(error_msg.empty());
+ map.reset(MemMap::MapAnonymous("MapAnonymousEmpty",
+ nullptr,
+ kPageSize,
+ PROT_READ | PROT_WRITE,
+ false,
+ &error_msg));
+ ASSERT_TRUE(map.get() != nullptr) << error_msg;
ASSERT_TRUE(error_msg.empty());
}
-TEST_F(MemMapTest, RemapAtEnd) {
+#ifdef __LP64__
+TEST_F(MemMapTest, MapAnonymousEmpty32bit) {
std::string error_msg;
- // Cast the page size to size_t.
- const size_t page_size = static_cast<size_t>(kPageSize);
- // Map a two-page memory region.
- MemMap* m0 = MemMap::MapAnonymous("MemMapTest_RemapAtEndTest_map0",
- NULL,
- 2 * page_size,
- PROT_READ | PROT_WRITE,
- &error_msg);
- // Check its state and write to it.
- byte* base0 = m0->Begin();
- ASSERT_TRUE(base0 != NULL) << error_msg;
- size_t size0 = m0->Size();
- EXPECT_EQ(m0->Size(), 2 * page_size);
- EXPECT_EQ(BaseBegin(m0), base0);
- EXPECT_EQ(BaseSize(m0), size0);
- memset(base0, 42, 2 * page_size);
- // Remap the latter half into a second MemMap.
- MemMap* m1 = m0->RemapAtEnd(base0 + page_size,
- "MemMapTest_RemapAtEndTest_map1",
- PROT_READ | PROT_WRITE,
- &error_msg);
- // Check the states of the two maps.
- EXPECT_EQ(m0->Begin(), base0) << error_msg;
- EXPECT_EQ(m0->Size(), page_size);
- EXPECT_EQ(BaseBegin(m0), base0);
- EXPECT_EQ(BaseSize(m0), page_size);
- byte* base1 = m1->Begin();
- size_t size1 = m1->Size();
- EXPECT_EQ(base1, base0 + page_size);
- EXPECT_EQ(size1, page_size);
- EXPECT_EQ(BaseBegin(m1), base1);
- EXPECT_EQ(BaseSize(m1), size1);
- // Write to the second region.
- memset(base1, 43, page_size);
- // Check the contents of the two regions.
- for (size_t i = 0; i < page_size; ++i) {
- EXPECT_EQ(base0[i], 42);
- }
- for (size_t i = 0; i < page_size; ++i) {
- EXPECT_EQ(base1[i], 43);
- }
- // Unmap the first region.
- delete m0;
- // Make sure the second region is still accessible after the first
- // region is unmapped.
- for (size_t i = 0; i < page_size; ++i) {
- EXPECT_EQ(base1[i], 43);
- }
- delete m1;
+ UniquePtr<MemMap> map(MemMap::MapAnonymous("MapAnonymousEmpty",
+ nullptr,
+ kPageSize,
+ PROT_READ | PROT_WRITE,
+ true,
+ &error_msg));
+ ASSERT_TRUE(map.get() != nullptr) << error_msg;
+ ASSERT_TRUE(error_msg.empty());
+ ASSERT_LT(reinterpret_cast<uintptr_t>(BaseBegin(map.get())), 1ULL << 32);
+}
+#endif
+
+TEST_F(MemMapTest, RemapAtEnd) {
+ RemapAtEndTest(false);
+}
+
+#ifdef __LP64__
+TEST_F(MemMapTest, RemapAtEnd32bit) {
+ RemapAtEndTest(true);
}
+#endif
} // namespace art
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index bd81bd5..b2725e5 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -27,7 +27,7 @@
namespace art {
namespace mirror {
-inline size_t Array::SizeOf() const {
+inline size_t Array::SizeOf() {
// This is safe from overflow because the array was already allocated, so we know it's sane.
size_t component_size = GetClass()->GetComponentSize();
int32_t component_count = GetLength();
@@ -64,9 +64,10 @@ class SetLengthVisitor {
explicit SetLengthVisitor(int32_t length) : length_(length) {
}
- void operator()(mirror::Object* obj) const {
- mirror::Array* array = obj->AsArray();
- DCHECK(array->IsArrayInstance());
+ void operator()(Object* obj) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ // Avoid AsArray as object is not yet in live bitmap or allocation stack.
+ Array* array = down_cast<Array*>(obj);
+ // DCHECK(array->IsArrayInstance());
array->SetLength(length_);
}
@@ -116,6 +117,114 @@ inline void PrimitiveArray<T>::VisitRoots(RootVisitor* visitor, void* arg) {
}
}
+// Similar to memmove except elements are of aligned appropriately for T, count is in T sized units
+// copies are guaranteed not to tear when T is less-than 64bit.
+template<typename T>
+static inline void ArrayBackwardCopy(T* d, const T* s, int32_t count) {
+ d += count;
+ s += count;
+ for (int32_t i = 0; i < count; ++i) {
+ d--;
+ s--;
+ *d = *s;
+ }
+}
+
+template<class T>
+void PrimitiveArray<T>::Memmove(int32_t dst_pos, PrimitiveArray<T>* src, int32_t src_pos,
+ int32_t count) {
+ if (UNLIKELY(count == 0)) {
+ return;
+ }
+ DCHECK_GE(dst_pos, 0);
+ DCHECK_GE(src_pos, 0);
+ DCHECK_GT(count, 0);
+ DCHECK(src != nullptr);
+ DCHECK_LT(dst_pos, GetLength());
+ DCHECK_LE(dst_pos, GetLength() - count);
+ DCHECK_LT(src_pos, src->GetLength());
+ DCHECK_LE(src_pos, src->GetLength() - count);
+
+ // Note for non-byte copies we can't rely on standard libc functions like memcpy(3) and memmove(3)
+ // in our implementation, because they may copy byte-by-byte.
+ if (LIKELY(src != this) || (dst_pos < src_pos) || (dst_pos - src_pos >= count)) {
+ // Forward copy ok.
+ Memcpy(dst_pos, src, src_pos, count);
+ } else {
+ // Backward copy necessary.
+ void* dst_raw = GetRawData(sizeof(T), dst_pos);
+ const void* src_raw = src->GetRawData(sizeof(T), src_pos);
+ if (sizeof(T) == sizeof(uint8_t)) {
+ // TUNING: use memmove here?
+ uint8_t* d = reinterpret_cast<uint8_t*>(dst_raw);
+ const uint8_t* s = reinterpret_cast<const uint8_t*>(src_raw);
+ ArrayBackwardCopy<uint8_t>(d, s, count);
+ } else if (sizeof(T) == sizeof(uint16_t)) {
+ uint16_t* d = reinterpret_cast<uint16_t*>(dst_raw);
+ const uint16_t* s = reinterpret_cast<const uint16_t*>(src_raw);
+ ArrayBackwardCopy<uint16_t>(d, s, count);
+ } else if (sizeof(T) == sizeof(uint32_t)) {
+ uint32_t* d = reinterpret_cast<uint32_t*>(dst_raw);
+ const uint32_t* s = reinterpret_cast<const uint32_t*>(src_raw);
+ ArrayBackwardCopy<uint32_t>(d, s, count);
+ } else {
+ DCHECK_EQ(sizeof(T), sizeof(uint64_t));
+ uint64_t* d = reinterpret_cast<uint64_t*>(dst_raw);
+ const uint64_t* s = reinterpret_cast<const uint64_t*>(src_raw);
+ ArrayBackwardCopy<uint64_t>(d, s, count);
+ }
+ }
+}
+
+// Similar to memcpy except elements are of aligned appropriately for T, count is in T sized units
+// copies are guaranteed not to tear when T is less-than 64bit.
+template<typename T>
+static inline void ArrayForwardCopy(T* d, const T* s, int32_t count) {
+ for (int32_t i = 0; i < count; ++i) {
+ *d = *s;
+ d++;
+ s++;
+ }
+}
+
+
+template<class T>
+void PrimitiveArray<T>::Memcpy(int32_t dst_pos, PrimitiveArray<T>* src, int32_t src_pos,
+ int32_t count) {
+ if (UNLIKELY(count == 0)) {
+ return;
+ }
+ DCHECK_GE(dst_pos, 0);
+ DCHECK_GE(src_pos, 0);
+ DCHECK_GT(count, 0);
+ DCHECK(src != nullptr);
+ DCHECK_LT(dst_pos, GetLength());
+ DCHECK_LE(dst_pos, GetLength() - count);
+ DCHECK_LT(src_pos, src->GetLength());
+ DCHECK_LE(src_pos, src->GetLength() - count);
+
+ // Note for non-byte copies we can't rely on standard libc functions like memcpy(3) and memmove(3)
+ // in our implementation, because they may copy byte-by-byte.
+ void* dst_raw = GetRawData(sizeof(T), dst_pos);
+ const void* src_raw = src->GetRawData(sizeof(T), src_pos);
+ if (sizeof(T) == sizeof(uint8_t)) {
+ memcpy(dst_raw, src_raw, count);
+ } else if (sizeof(T) == sizeof(uint16_t)) {
+ uint16_t* d = reinterpret_cast<uint16_t*>(dst_raw);
+ const uint16_t* s = reinterpret_cast<const uint16_t*>(src_raw);
+ ArrayForwardCopy<uint16_t>(d, s, count);
+ } else if (sizeof(T) == sizeof(uint32_t)) {
+ uint32_t* d = reinterpret_cast<uint32_t*>(dst_raw);
+ const uint32_t* s = reinterpret_cast<const uint32_t*>(src_raw);
+ ArrayForwardCopy<uint32_t>(d, s, count);
+ } else {
+ DCHECK_EQ(sizeof(T), sizeof(uint64_t));
+ uint64_t* d = reinterpret_cast<uint64_t*>(dst_raw);
+ const uint64_t* s = reinterpret_cast<const uint64_t*>(src_raw);
+ ArrayForwardCopy<uint64_t>(d, s, count);
+ }
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/array.cc b/runtime/mirror/array.cc
index 00b88db..ca0d1f3 100644
--- a/runtime/mirror/array.cc
+++ b/runtime/mirror/array.cc
@@ -103,11 +103,11 @@ Array* Array::CreateMultiArray(Thread* self, Class* element_class, IntArray* dim
return new_array;
}
-void Array::ThrowArrayIndexOutOfBoundsException(int32_t index) const {
+void Array::ThrowArrayIndexOutOfBoundsException(int32_t index) {
art::ThrowArrayIndexOutOfBoundsException(index, GetLength());
}
-void Array::ThrowArrayStoreException(Object* object) const {
+void Array::ThrowArrayStoreException(Object* object) {
art::ThrowArrayStoreException(object->GetClass(), this->GetClass());
}
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index 207573f..6e366a0 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -50,15 +50,15 @@ class MANAGED Array : public Object {
static Array* CreateMultiArray(Thread* self, Class* element_class, IntArray* dimensions)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- size_t SizeOf() const;
+ size_t SizeOf() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- int32_t GetLength() const {
+ int32_t GetLength() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetField32(OFFSET_OF_OBJECT_MEMBER(Array, length_), false);
}
- void SetLength(int32_t length) {
+ void SetLength(int32_t length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
CHECK_GE(length, 0);
- SetField32(OFFSET_OF_OBJECT_MEMBER(Array, length_), length, false);
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Array, length_), length, false, false);
}
static MemberOffset LengthOffset() {
@@ -74,20 +74,22 @@ class MANAGED Array : public Object {
}
}
- void* GetRawData(size_t component_size) {
- intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(component_size).Int32Value();
+ void* GetRawData(size_t component_size, int32_t index)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(component_size).Int32Value() +
+ + (index * component_size);
return reinterpret_cast<void*>(data);
}
- const void* GetRawData(size_t component_size) const {
- intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(component_size).Int32Value();
- return reinterpret_cast<const void*>(data);
+ const void* GetRawData(size_t component_size, int32_t index) const {
+ intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(component_size).Int32Value() +
+ + (index * component_size);
+ return reinterpret_cast<void*>(data);
}
// Returns true if the index is valid. If not, throws an ArrayIndexOutOfBoundsException and
// returns false.
- bool CheckIsValidIndex(int32_t index) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ bool CheckIsValidIndex(int32_t index) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (UNLIKELY(static_cast<uint32_t>(index) >= static_cast<uint32_t>(GetLength()))) {
ThrowArrayIndexOutOfBoundsException(index);
return false;
@@ -96,11 +98,10 @@ class MANAGED Array : public Object {
}
protected:
- void ThrowArrayStoreException(Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void ThrowArrayStoreException(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
private:
- void ThrowArrayIndexOutOfBoundsException(int32_t index) const
+ void ThrowArrayIndexOutOfBoundsException(int32_t index)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// The number of array elements.
@@ -119,17 +120,15 @@ class MANAGED PrimitiveArray : public Array {
static PrimitiveArray<T>* Alloc(Thread* self, size_t length)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- const T* GetData() const {
- intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(sizeof(T)).Int32Value();
- return reinterpret_cast<T*>(data);
+ const T* GetData() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return reinterpret_cast<const T*>(GetRawData(sizeof(T), 0));
}
- T* GetData() {
- intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(sizeof(T)).Int32Value();
- return reinterpret_cast<T*>(data);
+ T* GetData() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return reinterpret_cast<T*>(GetRawData(sizeof(T), 0));
}
- T Get(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ T Get(int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (UNLIKELY(!CheckIsValidIndex(i))) {
DCHECK(Thread::Current()->IsExceptionPending());
return T(0);
@@ -137,7 +136,7 @@ class MANAGED PrimitiveArray : public Array {
return GetWithoutChecks(i);
}
- T GetWithoutChecks(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ T GetWithoutChecks(int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(CheckIsValidIndex(i));
return GetData()[i];
}
@@ -155,6 +154,22 @@ class MANAGED PrimitiveArray : public Array {
GetData()[i] = value;
}
+ /*
+ * Works like memmove(), except we guarantee not to allow tearing of array values (ie using
+ * smaller than element size copies). Arguments are assumed to be within the bounds of the array
+ * and the arrays non-null.
+ */
+ void Memmove(int32_t dst_pos, PrimitiveArray<T>* src, int32_t src_pos, int32_t count)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ /*
+ * Works like memcpy(), except we guarantee not to allow tearing of array values (ie using
+ * smaller than element size copies). Arguments are assumed to be within the bounds of the array
+ * and the arrays non-null.
+ */
+ void Memcpy(int32_t dst_pos, PrimitiveArray<T>* src, int32_t src_pos, int32_t count)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
static void SetArrayClass(Class* array_class) {
CHECK(array_class_ == NULL);
CHECK(array_class != NULL);
diff --git a/runtime/mirror/art_field-inl.h b/runtime/mirror/art_field-inl.h
index d8c278c..530226b 100644
--- a/runtime/mirror/art_field-inl.h
+++ b/runtime/mirror/art_field-inl.h
@@ -29,8 +29,8 @@
namespace art {
namespace mirror {
-inline Class* ArtField::GetDeclaringClass() const {
- Class* result = GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(ArtField, declaring_class_), false);
+inline Class* ArtField::GetDeclaringClass() {
+ Class* result = GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(ArtField, declaring_class_), false);
DCHECK(result != NULL);
DCHECK(result->IsLoaded() || result->IsErroneous());
return result;
@@ -40,106 +40,106 @@ inline void ArtField::SetDeclaringClass(Class *new_declaring_class) {
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(ArtField, declaring_class_), new_declaring_class, false);
}
-inline uint32_t ArtField::GetAccessFlags() const {
+inline uint32_t ArtField::GetAccessFlags() {
DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtField, access_flags_), false);
}
-inline MemberOffset ArtField::GetOffset() const {
+inline MemberOffset ArtField::GetOffset() {
DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous());
return MemberOffset(GetField32(OFFSET_OF_OBJECT_MEMBER(ArtField, offset_), false));
}
-inline MemberOffset ArtField::GetOffsetDuringLinking() const {
+inline MemberOffset ArtField::GetOffsetDuringLinking() {
DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
return MemberOffset(GetField32(OFFSET_OF_OBJECT_MEMBER(ArtField, offset_), false));
}
-inline uint32_t ArtField::Get32(const Object* object) const {
+inline uint32_t ArtField::Get32(Object* object) {
DCHECK(object != NULL) << PrettyField(this);
DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
return object->GetField32(GetOffset(), IsVolatile());
}
-inline void ArtField::Set32(Object* object, uint32_t new_value) const {
+inline void ArtField::Set32(Object* object, uint32_t new_value) {
DCHECK(object != NULL) << PrettyField(this);
DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
object->SetField32(GetOffset(), new_value, IsVolatile());
}
-inline uint64_t ArtField::Get64(const Object* object) const {
+inline uint64_t ArtField::Get64(Object* object) {
DCHECK(object != NULL) << PrettyField(this);
DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
return object->GetField64(GetOffset(), IsVolatile());
}
-inline void ArtField::Set64(Object* object, uint64_t new_value) const {
+inline void ArtField::Set64(Object* object, uint64_t new_value) {
DCHECK(object != NULL) << PrettyField(this);
DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
object->SetField64(GetOffset(), new_value, IsVolatile());
}
-inline Object* ArtField::GetObj(const Object* object) const {
+inline Object* ArtField::GetObj(Object* object) {
DCHECK(object != NULL) << PrettyField(this);
DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
- return object->GetFieldObject<Object*>(GetOffset(), IsVolatile());
+ return object->GetFieldObject<Object>(GetOffset(), IsVolatile());
}
-inline void ArtField::SetObj(Object* object, const Object* new_value) const {
+inline void ArtField::SetObj(Object* object, Object* new_value) {
DCHECK(object != NULL) << PrettyField(this);
DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
object->SetFieldObject(GetOffset(), new_value, IsVolatile());
}
-inline bool ArtField::GetBoolean(const Object* object) const {
+inline bool ArtField::GetBoolean(Object* object) {
DCHECK_EQ(Primitive::kPrimBoolean, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
return Get32(object);
}
-inline void ArtField::SetBoolean(Object* object, bool z) const {
+inline void ArtField::SetBoolean(Object* object, bool z) {
DCHECK_EQ(Primitive::kPrimBoolean, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
Set32(object, z);
}
-inline int8_t ArtField::GetByte(const Object* object) const {
+inline int8_t ArtField::GetByte(Object* object) {
DCHECK_EQ(Primitive::kPrimByte, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
return Get32(object);
}
-inline void ArtField::SetByte(Object* object, int8_t b) const {
+inline void ArtField::SetByte(Object* object, int8_t b) {
DCHECK_EQ(Primitive::kPrimByte, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
Set32(object, b);
}
-inline uint16_t ArtField::GetChar(const Object* object) const {
+inline uint16_t ArtField::GetChar(Object* object) {
DCHECK_EQ(Primitive::kPrimChar, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
return Get32(object);
}
-inline void ArtField::SetChar(Object* object, uint16_t c) const {
+inline void ArtField::SetChar(Object* object, uint16_t c) {
DCHECK_EQ(Primitive::kPrimChar, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
Set32(object, c);
}
-inline int16_t ArtField::GetShort(const Object* object) const {
+inline int16_t ArtField::GetShort(Object* object) {
DCHECK_EQ(Primitive::kPrimShort, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
return Get32(object);
}
-inline void ArtField::SetShort(Object* object, int16_t s) const {
+inline void ArtField::SetShort(Object* object, int16_t s) {
DCHECK_EQ(Primitive::kPrimShort, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
Set32(object, s);
}
-inline int32_t ArtField::GetInt(const Object* object) const {
+inline int32_t ArtField::GetInt(Object* object) {
#ifndef NDEBUG
Primitive::Type type = FieldHelper(this).GetTypeAsPrimitiveType();
CHECK(type == Primitive::kPrimInt || type == Primitive::kPrimFloat) << PrettyField(this);
@@ -147,7 +147,7 @@ inline int32_t ArtField::GetInt(const Object* object) const {
return Get32(object);
}
-inline void ArtField::SetInt(Object* object, int32_t i) const {
+inline void ArtField::SetInt(Object* object, int32_t i) {
#ifndef NDEBUG
Primitive::Type type = FieldHelper(this).GetTypeAsPrimitiveType();
CHECK(type == Primitive::kPrimInt || type == Primitive::kPrimFloat) << PrettyField(this);
@@ -155,7 +155,7 @@ inline void ArtField::SetInt(Object* object, int32_t i) const {
Set32(object, i);
}
-inline int64_t ArtField::GetLong(const Object* object) const {
+inline int64_t ArtField::GetLong(Object* object) {
#ifndef NDEBUG
Primitive::Type type = FieldHelper(this).GetTypeAsPrimitiveType();
CHECK(type == Primitive::kPrimLong || type == Primitive::kPrimDouble) << PrettyField(this);
@@ -163,7 +163,7 @@ inline int64_t ArtField::GetLong(const Object* object) const {
return Get64(object);
}
-inline void ArtField::SetLong(Object* object, int64_t j) const {
+inline void ArtField::SetLong(Object* object, int64_t j) {
#ifndef NDEBUG
Primitive::Type type = FieldHelper(this).GetTypeAsPrimitiveType();
CHECK(type == Primitive::kPrimLong || type == Primitive::kPrimDouble) << PrettyField(this);
@@ -171,7 +171,7 @@ inline void ArtField::SetLong(Object* object, int64_t j) const {
Set64(object, j);
}
-inline float ArtField::GetFloat(const Object* object) const {
+inline float ArtField::GetFloat(Object* object) {
DCHECK_EQ(Primitive::kPrimFloat, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
JValue bits;
@@ -179,7 +179,7 @@ inline float ArtField::GetFloat(const Object* object) const {
return bits.GetF();
}
-inline void ArtField::SetFloat(Object* object, float f) const {
+inline void ArtField::SetFloat(Object* object, float f) {
DCHECK_EQ(Primitive::kPrimFloat, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
JValue bits;
@@ -187,7 +187,7 @@ inline void ArtField::SetFloat(Object* object, float f) const {
Set32(object, bits.GetI());
}
-inline double ArtField::GetDouble(const Object* object) const {
+inline double ArtField::GetDouble(Object* object) {
DCHECK_EQ(Primitive::kPrimDouble, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
JValue bits;
@@ -195,7 +195,7 @@ inline double ArtField::GetDouble(const Object* object) const {
return bits.GetD();
}
-inline void ArtField::SetDouble(Object* object, double d) const {
+inline void ArtField::SetDouble(Object* object, double d) {
DCHECK_EQ(Primitive::kPrimDouble, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
JValue bits;
@@ -203,13 +203,13 @@ inline void ArtField::SetDouble(Object* object, double d) const {
Set64(object, bits.GetJ());
}
-inline Object* ArtField::GetObject(const Object* object) const {
+inline Object* ArtField::GetObject(Object* object) {
DCHECK_EQ(Primitive::kPrimNot, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
return GetObj(object);
}
-inline void ArtField::SetObject(Object* object, const Object* l) const {
+inline void ArtField::SetObject(Object* object, Object* l) {
DCHECK_EQ(Primitive::kPrimNot, FieldHelper(this).GetTypeAsPrimitiveType())
<< PrettyField(this);
SetObj(object, l);
diff --git a/runtime/mirror/art_field.h b/runtime/mirror/art_field.h
index 62bcf06..b33fe4b 100644
--- a/runtime/mirror/art_field.h
+++ b/runtime/mirror/art_field.h
@@ -30,98 +30,74 @@ namespace mirror {
// C++ mirror of java.lang.reflect.ArtField
class MANAGED ArtField : public Object {
public:
- Class* GetDeclaringClass() const;
+ Class* GetDeclaringClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetDeclaringClass(Class *new_declaring_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- uint32_t GetAccessFlags() const;
+ uint32_t GetAccessFlags() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetAccessFlags(uint32_t new_access_flags) {
+ void SetAccessFlags(uint32_t new_access_flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
SetField32(OFFSET_OF_OBJECT_MEMBER(ArtField, access_flags_), new_access_flags, false);
}
- bool IsPublic() const {
+ bool IsPublic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccPublic) != 0;
}
- bool IsStatic() const {
+ bool IsStatic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccStatic) != 0;
}
- bool IsFinal() const {
+ bool IsFinal() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccFinal) != 0;
}
- uint32_t GetDexFieldIndex() const {
+ uint32_t GetDexFieldIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtField, field_dex_idx_), false);
}
- void SetDexFieldIndex(uint32_t new_idx) {
+ void SetDexFieldIndex(uint32_t new_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
SetField32(OFFSET_OF_OBJECT_MEMBER(ArtField, field_dex_idx_), new_idx, false);
}
- // Offset to field within an Object
- MemberOffset GetOffset() const;
+ // Offset to field within an Object.
+ MemberOffset GetOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static MemberOffset OffsetOffset() {
return MemberOffset(OFFSETOF_MEMBER(ArtField, offset_));
}
- MemberOffset GetOffsetDuringLinking() const;
+ MemberOffset GetOffsetDuringLinking() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetOffset(MemberOffset num_bytes);
+ void SetOffset(MemberOffset num_bytes) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// field access, null object for static fields
- bool GetBoolean(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetBoolean(Object* object, bool z) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- int8_t GetByte(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetByte(Object* object, int8_t b) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- uint16_t GetChar(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetChar(Object* object, uint16_t c) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- int16_t GetShort(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetShort(Object* object, int16_t s) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- int32_t GetInt(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetInt(Object* object, int32_t i) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- int64_t GetLong(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetLong(Object* object, int64_t j) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- float GetFloat(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetFloat(Object* object, float f) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- double GetDouble(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetDouble(Object* object, double d) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- Object* GetObject(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetObject(Object* object, const Object* l) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- // raw field accesses
- uint32_t Get32(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void Set32(Object* object, uint32_t new_value) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- uint64_t Get64(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void Set64(Object* object, uint64_t new_value) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- Object* GetObj(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetObj(Object* object, const Object* new_value) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool GetBoolean(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetBoolean(Object* object, bool z) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ int8_t GetByte(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetByte(Object* object, int8_t b) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ uint16_t GetChar(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetChar(Object* object, uint16_t c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ int16_t GetShort(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetShort(Object* object, int16_t s) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ int32_t GetInt(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetInt(Object* object, int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ int64_t GetLong(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetLong(Object* object, int64_t j) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ float GetFloat(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetFloat(Object* object, float f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ double GetDouble(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetDouble(Object* object, double d) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ Object* GetObject(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetObject(Object* object, Object* l) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ // Raw field accesses.
+ uint32_t Get32(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void Set32(Object* object, uint32_t new_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ uint64_t Get64(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void Set64(Object* object, uint64_t new_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ Object* GetObj(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetObj(Object* object, Object* new_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static Class* GetJavaLangReflectArtField() {
DCHECK(java_lang_reflect_ArtField_ != NULL);
@@ -133,14 +109,14 @@ class MANAGED ArtField : public Object {
static void VisitRoots(RootVisitor* visitor, void* arg)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsVolatile() const {
+ bool IsVolatile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccVolatile) != 0;
}
private:
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
// The class we are a part of
- Class* declaring_class_;
+ HeapReference<Class> declaring_class_;
uint32_t access_flags_;
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index 088f616..8ef3be8 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/mirror/art_method-inl.h
@@ -27,8 +27,9 @@
namespace art {
namespace mirror {
-inline Class* ArtMethod::GetDeclaringClass() const {
- Class* result = GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, declaring_class_), false);
+inline Class* ArtMethod::GetDeclaringClass() {
+ Class* result = GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, declaring_class_),
+ false);
DCHECK(result != NULL) << this;
DCHECK(result->IsIdxLoaded() || result->IsErroneous()) << this;
return result;
@@ -38,44 +39,44 @@ inline void ArtMethod::SetDeclaringClass(Class *new_declaring_class) {
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(ArtMethod, declaring_class_), new_declaring_class, false);
}
-inline uint32_t ArtMethod::GetAccessFlags() const {
+inline uint32_t ArtMethod::GetAccessFlags() {
DCHECK(GetDeclaringClass()->IsIdxLoaded() || GetDeclaringClass()->IsErroneous());
return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, access_flags_), false);
}
-inline uint16_t ArtMethod::GetMethodIndex() const {
+inline uint16_t ArtMethod::GetMethodIndex() {
DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous());
return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_), false);
}
-inline uint32_t ArtMethod::GetDexMethodIndex() const {
+inline uint32_t ArtMethod::GetDexMethodIndex() {
#ifdef ART_SEA_IR_MODE
// TODO: Re-add this check for (PORTABLE + SMALL + ) SEA IR when PORTABLE IS fixed!
// DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
#else
DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
#endif
- return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_dex_index_), false);
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_method_index_), false);
}
-inline ObjectArray<String>* ArtMethod::GetDexCacheStrings() const {
- return GetFieldObject<ObjectArray<String>*>(
+inline ObjectArray<String>* ArtMethod::GetDexCacheStrings() {
+ return GetFieldObject<ObjectArray<String> >(
OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_strings_), false);
}
-inline ObjectArray<ArtMethod>* ArtMethod::GetDexCacheResolvedMethods() const {
- return GetFieldObject<ObjectArray<ArtMethod>*>(
+inline ObjectArray<ArtMethod>* ArtMethod::GetDexCacheResolvedMethods() {
+ return GetFieldObject<ObjectArray<ArtMethod> >(
OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_methods_), false);
}
-inline ObjectArray<Class>* ArtMethod::GetDexCacheResolvedTypes() const {
- return GetFieldObject<ObjectArray<Class>*>(
+inline ObjectArray<Class>* ArtMethod::GetDexCacheResolvedTypes() {
+ return GetFieldObject<ObjectArray<Class> >(
OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_types_), false);
}
-inline uint32_t ArtMethod::GetCodeSize() const {
+inline uint32_t ArtMethod::GetCodeSize() {
DCHECK(!IsRuntimeMethod() && !IsProxyMethod()) << PrettyMethod(this);
- uintptr_t code = reinterpret_cast<uintptr_t>(GetEntryPointFromCompiledCode());
+ uintptr_t code = reinterpret_cast<uintptr_t>(GetEntryPointFromQuickCompiledCode());
if (code == 0) {
return 0;
}
@@ -106,7 +107,7 @@ inline bool ArtMethod::CheckIncompatibleClassChange(InvokeType type) {
}
}
-inline void ArtMethod::AssertPcIsWithinCode(uintptr_t pc) const {
+inline void ArtMethod::AssertPcIsWithinQuickCode(uintptr_t pc) {
if (!kIsDebugBuild) {
return;
}
@@ -116,34 +117,44 @@ inline void ArtMethod::AssertPcIsWithinCode(uintptr_t pc) const {
if (pc == GetQuickInstrumentationExitPc()) {
return;
}
- const void* code = GetEntryPointFromCompiledCode();
- if (code == GetCompiledCodeToInterpreterBridge() || code == GetQuickInstrumentationEntryPoint()) {
+ const void* code = GetEntryPointFromQuickCompiledCode();
+ if (code == GetQuickToInterpreterBridge() || code == GetQuickInstrumentationEntryPoint()) {
return;
}
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- if (code == GetResolutionTrampoline(class_linker)) {
+ if (code == GetQuickResolutionTrampoline(class_linker)) {
return;
}
- DCHECK(IsWithinCode(pc))
+ DCHECK(IsWithinQuickCode(pc))
<< PrettyMethod(this)
<< " pc=" << std::hex << pc
<< " code=" << code
<< " size=" << GetCodeSize();
}
-inline uint32_t ArtMethod::GetOatCodeOffset() const {
+inline uint32_t ArtMethod::GetQuickOatCodeOffset() {
DCHECK(!Runtime::Current()->IsStarted());
- return reinterpret_cast<uint32_t>(GetEntryPointFromCompiledCode());
+ return PointerToLowMemUInt32(GetEntryPointFromQuickCompiledCode());
}
-inline void ArtMethod::SetOatCodeOffset(uint32_t code_offset) {
+inline uint32_t ArtMethod::GetPortableOatCodeOffset() {
DCHECK(!Runtime::Current()->IsStarted());
- SetEntryPointFromCompiledCode(reinterpret_cast<void*>(code_offset));
+ return PointerToLowMemUInt32(GetEntryPointFromPortableCompiledCode());
}
-inline uint32_t ArtMethod::GetOatMappingTableOffset() const {
+inline void ArtMethod::SetQuickOatCodeOffset(uint32_t code_offset) {
DCHECK(!Runtime::Current()->IsStarted());
- return reinterpret_cast<uint32_t>(GetMappingTable());
+ SetEntryPointFromQuickCompiledCode(reinterpret_cast<void*>(code_offset));
+}
+
+inline void ArtMethod::SetPortableOatCodeOffset(uint32_t code_offset) {
+ DCHECK(!Runtime::Current()->IsStarted());
+ SetEntryPointFromPortableCompiledCode(reinterpret_cast<void*>(code_offset));
+}
+
+inline uint32_t ArtMethod::GetOatMappingTableOffset() {
+ DCHECK(!Runtime::Current()->IsStarted());
+ return PointerToLowMemUInt32(GetMappingTable());
}
inline void ArtMethod::SetOatMappingTableOffset(uint32_t mapping_table_offset) {
@@ -151,9 +162,9 @@ inline void ArtMethod::SetOatMappingTableOffset(uint32_t mapping_table_offset) {
SetMappingTable(reinterpret_cast<const uint8_t*>(mapping_table_offset));
}
-inline uint32_t ArtMethod::GetOatVmapTableOffset() const {
+inline uint32_t ArtMethod::GetOatVmapTableOffset() {
DCHECK(!Runtime::Current()->IsStarted());
- return reinterpret_cast<uint32_t>(GetVmapTable());
+ return PointerToLowMemUInt32(GetVmapTable());
}
inline void ArtMethod::SetOatVmapTableOffset(uint32_t vmap_table_offset) {
@@ -166,16 +177,16 @@ inline void ArtMethod::SetOatNativeGcMapOffset(uint32_t gc_map_offset) {
SetNativeGcMap(reinterpret_cast<uint8_t*>(gc_map_offset));
}
-inline uint32_t ArtMethod::GetOatNativeGcMapOffset() const {
+inline uint32_t ArtMethod::GetOatNativeGcMapOffset() {
DCHECK(!Runtime::Current()->IsStarted());
- return reinterpret_cast<uint32_t>(GetNativeGcMap());
+ return PointerToLowMemUInt32(GetNativeGcMap());
}
-inline bool ArtMethod::IsRuntimeMethod() const {
+inline bool ArtMethod::IsRuntimeMethod() {
return GetDexMethodIndex() == DexFile::kDexNoIndex;
}
-inline bool ArtMethod::IsCalleeSaveMethod() const {
+inline bool ArtMethod::IsCalleeSaveMethod() {
if (!IsRuntimeMethod()) {
return false;
}
@@ -190,14 +201,14 @@ inline bool ArtMethod::IsCalleeSaveMethod() const {
return result;
}
-inline bool ArtMethod::IsResolutionMethod() const {
+inline bool ArtMethod::IsResolutionMethod() {
bool result = this == Runtime::Current()->GetResolutionMethod();
// Check that if we do think it is phony it looks like the resolution method.
DCHECK(!result || IsRuntimeMethod());
return result;
}
-inline bool ArtMethod::IsImtConflictMethod() const {
+inline bool ArtMethod::IsImtConflictMethod() {
bool result = this == Runtime::Current()->GetImtConflictMethod();
// Check that if we do think it is phony it looks like the imt conflict method.
DCHECK(!result || IsRuntimeMethod());
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index f4a076c..575ea03 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -47,7 +47,7 @@ void ArtMethod::VisitRoots(RootVisitor* visitor, void* arg) {
}
}
-InvokeType ArtMethod::GetInvokeType() const {
+InvokeType ArtMethod::GetInvokeType() {
// TODO: kSuper?
if (GetDeclaringClass()->IsInterface()) {
return kInterface;
@@ -100,11 +100,11 @@ size_t ArtMethod::NumArgRegisters(const StringPiece& shorty) {
return num_registers;
}
-bool ArtMethod::IsProxyMethod() const {
+bool ArtMethod::IsProxyMethod() {
return GetDeclaringClass()->IsProxyClass();
}
-ArtMethod* ArtMethod::FindOverriddenMethod() const {
+ArtMethod* ArtMethod::FindOverriddenMethod() {
if (IsStatic()) {
return NULL;
}
@@ -147,13 +147,16 @@ ArtMethod* ArtMethod::FindOverriddenMethod() const {
return result;
}
-uintptr_t ArtMethod::NativePcOffset(const uintptr_t pc) const {
+uintptr_t ArtMethod::NativePcOffset(const uintptr_t pc) {
const void* code = Runtime::Current()->GetInstrumentation()->GetQuickCodeFor(this);
return pc - reinterpret_cast<uintptr_t>(code);
}
-uint32_t ArtMethod::ToDexPc(const uintptr_t pc) const {
-#if !defined(ART_USE_PORTABLE_COMPILER)
+uint32_t ArtMethod::ToDexPc(const uintptr_t pc) {
+ if (IsPortableCompiled()) {
+ // Portable doesn't use the machine pc, we just use dex pc instead.
+ return static_cast<uint32_t>(pc);
+ }
MappingTable table(GetMappingTable());
if (table.TotalSize() == 0) {
DCHECK(IsNative() || IsCalleeSaveMethod() || IsProxyMethod()) << PrettyMethod(this);
@@ -176,16 +179,12 @@ uint32_t ArtMethod::ToDexPc(const uintptr_t pc) const {
}
}
LOG(FATAL) << "Failed to find Dex offset for PC offset " << reinterpret_cast<void*>(sought_offset)
- << "(PC " << reinterpret_cast<void*>(pc) << ", code=" << code
- << ") in " << PrettyMethod(this);
+ << "(PC " << reinterpret_cast<void*>(pc) << ", code=" << code
+ << ") in " << PrettyMethod(this);
return DexFile::kDexNoIndex;
-#else
- // Compiler LLVM doesn't use the machine pc, we just use dex pc instead.
- return static_cast<uint32_t>(pc);
-#endif
}
-uintptr_t ArtMethod::ToNativePc(const uint32_t dex_pc) const {
+uintptr_t ArtMethod::ToNativePc(const uint32_t dex_pc) {
MappingTable table(GetMappingTable());
if (table.TotalSize() == 0) {
DCHECK_EQ(dex_pc, 0U);
@@ -213,7 +212,7 @@ uintptr_t ArtMethod::ToNativePc(const uint32_t dex_pc) const {
}
uint32_t ArtMethod::FindCatchBlock(Class* exception_type, uint32_t dex_pc,
- bool* has_no_move_exception) const {
+ bool* has_no_move_exception) {
MethodHelper mh(this);
const DexFile::CodeItem* code_item = mh.GetCodeItem();
// Default to handler not found.
@@ -265,16 +264,21 @@ void ArtMethod::Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue*
}
} else {
const bool kLogInvocationStartAndReturn = false;
- if (GetEntryPointFromCompiledCode() != NULL) {
+ bool have_quick_code = GetEntryPointFromQuickCompiledCode() != nullptr;
+ bool have_portable_code = GetEntryPointFromPortableCompiledCode() != nullptr;
+ if (LIKELY(have_quick_code || have_portable_code)) {
if (kLogInvocationStartAndReturn) {
- LOG(INFO) << StringPrintf("Invoking '%s' code=%p", PrettyMethod(this).c_str(), GetEntryPointFromCompiledCode());
+ LOG(INFO) << StringPrintf("Invoking '%s' %s code=%p", PrettyMethod(this).c_str(),
+ have_quick_code ? "quick" : "portable",
+ have_quick_code ? GetEntryPointFromQuickCompiledCode()
+ : GetEntryPointFromPortableCompiledCode());
}
-#ifdef ART_USE_PORTABLE_COMPILER
- (*art_portable_invoke_stub)(this, args, args_size, self, result, result_type);
-#else
- (*art_quick_invoke_stub)(this, args, args_size, self, result, result_type);
-#endif
- if (UNLIKELY(reinterpret_cast<int32_t>(self->GetException(NULL)) == -1)) {
+ if (!IsPortableCompiled()) {
+ (*art_quick_invoke_stub)(this, args, args_size, self, result, result_type);
+ } else {
+ (*art_portable_invoke_stub)(this, args, args_size, self, result, result_type);
+ }
+ if (UNLIKELY(reinterpret_cast<intptr_t>(self->GetException(NULL)) == -1)) {
// Unusual case where we were running LLVM generated code and an
// exception was thrown to force the activations to be removed from the
// stack. Continue execution in the interpreter.
@@ -285,11 +289,13 @@ void ArtMethod::Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue*
interpreter::EnterInterpreterFromDeoptimize(self, shadow_frame, result);
}
if (kLogInvocationStartAndReturn) {
- LOG(INFO) << StringPrintf("Returned '%s' code=%p", PrettyMethod(this).c_str(), GetEntryPointFromCompiledCode());
+ LOG(INFO) << StringPrintf("Returned '%s' %s code=%p", PrettyMethod(this).c_str(),
+ have_quick_code ? "quick" : "portable",
+ have_quick_code ? GetEntryPointFromQuickCompiledCode()
+ : GetEntryPointFromPortableCompiledCode());
}
} else {
- LOG(INFO) << "Not invoking '" << PrettyMethod(this)
- << "' code=" << reinterpret_cast<const void*>(GetEntryPointFromCompiledCode());
+ LOG(INFO) << "Not invoking '" << PrettyMethod(this) << "' code=null";
if (result != NULL) {
result->SetJ(0);
}
@@ -300,9 +306,10 @@ void ArtMethod::Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue*
self->PopManagedStackFragment(fragment);
}
-bool ArtMethod::IsRegistered() const {
- void* native_method = GetFieldPtr<void*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, native_method_), false);
- CHECK(native_method != NULL);
+bool ArtMethod::IsRegistered() {
+ void* native_method =
+ GetFieldPtr<void*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_jni_), false);
+ CHECK(native_method != nullptr);
void* jni_stub = GetJniDlsymLookupStub();
return native_method != jni_stub;
}
@@ -323,7 +330,7 @@ void ArtMethod::RegisterNative(Thread* self, const void* native_method, bool is_
// around JNI bugs, that include not giving Object** SIRT references to native methods. Direct
// the native method to runtime support and store the target somewhere runtime support will
// find it.
-#if defined(__i386__)
+#if defined(__i386__) || defined(__x86_64__)
UNIMPLEMENTED(FATAL);
#else
SetNativeMethod(reinterpret_cast<void*>(art_work_around_app_jni_bugs));
@@ -340,7 +347,7 @@ void ArtMethod::UnregisterNative(Thread* self) {
}
void ArtMethod::SetNativeMethod(const void* native_method) {
- SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, native_method_),
+ SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_jni_),
native_method, false);
}
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index 95ca4c9..bfa7cbe 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -45,7 +45,7 @@ typedef void (EntryPointFromInterpreter)(Thread* self, MethodHelper& mh,
// C++ mirror of java.lang.reflect.Method and java.lang.reflect.Constructor
class MANAGED ArtMethod : public Object {
public:
- Class* GetDeclaringClass() const;
+ Class* GetDeclaringClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetDeclaringClass(Class *new_declaring_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -53,41 +53,37 @@ class MANAGED ArtMethod : public Object {
return MemberOffset(OFFSETOF_MEMBER(ArtMethod, declaring_class_));
}
- static MemberOffset EntryPointFromCompiledCodeOffset() {
- return MemberOffset(OFFSETOF_MEMBER(ArtMethod, entry_point_from_compiled_code_));
- }
-
- uint32_t GetAccessFlags() const;
+ uint32_t GetAccessFlags() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetAccessFlags(uint32_t new_access_flags) {
+ void SetAccessFlags(uint32_t new_access_flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
SetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, access_flags_), new_access_flags, false);
}
// Approximate what kind of method call would be used for this method.
- InvokeType GetInvokeType() const;
+ InvokeType GetInvokeType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Returns true if the method is declared public.
- bool IsPublic() const {
+ bool IsPublic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccPublic) != 0;
}
// Returns true if the method is declared private.
- bool IsPrivate() const {
+ bool IsPrivate() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccPrivate) != 0;
}
// Returns true if the method is declared static.
- bool IsStatic() const {
+ bool IsStatic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccStatic) != 0;
}
// Returns true if the method is a constructor.
- bool IsConstructor() const {
+ bool IsConstructor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccConstructor) != 0;
}
// Returns true if the method is static, private, or a constructor.
- bool IsDirect() const {
+ bool IsDirect() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return IsDirect(GetAccessFlags());
}
@@ -96,55 +92,70 @@ class MANAGED ArtMethod : public Object {
}
// Returns true if the method is declared synchronized.
- bool IsSynchronized() const {
+ bool IsSynchronized() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
uint32_t synchonized = kAccSynchronized | kAccDeclaredSynchronized;
return (GetAccessFlags() & synchonized) != 0;
}
- bool IsFinal() const {
+ bool IsFinal() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccFinal) != 0;
}
- bool IsMiranda() const {
+ bool IsMiranda() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccMiranda) != 0;
}
- bool IsNative() const {
+ bool IsNative() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccNative) != 0;
}
- bool IsFastNative() const {
+ bool IsFastNative() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
uint32_t mask = kAccFastNative | kAccNative;
return (GetAccessFlags() & mask) == mask;
}
- bool IsAbstract() const {
+ bool IsAbstract() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccAbstract) != 0;
}
- bool IsSynthetic() const {
+ bool IsSynthetic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccSynthetic) != 0;
}
- bool IsProxyMethod() const;
+ bool IsProxyMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsPreverified() const {
+ bool IsPreverified() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccPreverified) != 0;
}
- void SetPreverified() {
+ void SetPreverified() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(!IsPreverified());
SetAccessFlags(GetAccessFlags() | kAccPreverified);
}
+ bool IsPortableCompiled() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return (GetAccessFlags() & kAccPortableCompiled) != 0;
+ }
+
+ void SetIsPortableCompiled() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(!IsPortableCompiled());
+ SetAccessFlags(GetAccessFlags() | kAccPortableCompiled);
+ }
+
+ void ClearIsPortableCompiled() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(IsPortableCompiled());
+ SetAccessFlags(GetAccessFlags() & ~kAccPortableCompiled);
+ }
+
bool CheckIncompatibleClassChange(InvokeType type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- uint16_t GetMethodIndex() const;
+ uint16_t GetMethodIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- size_t GetVtableIndex() const {
+ size_t GetVtableIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetMethodIndex();
}
- void SetMethodIndex(uint16_t new_method_index) {
+ void SetMethodIndex(uint16_t new_method_index) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
SetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_), new_method_index, false);
}
@@ -152,24 +163,24 @@ class MANAGED ArtMethod : public Object {
return OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_);
}
- uint32_t GetCodeItemOffset() const {
- return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, code_item_offset_), false);
+ uint32_t GetCodeItemOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_code_item_offset_), false);
}
void SetCodeItemOffset(uint32_t new_code_off) {
- SetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, code_item_offset_), new_code_off, false);
+ SetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_code_item_offset_), new_code_off, false);
}
// Number of 32bit registers that would be required to hold all the arguments
static size_t NumArgRegisters(const StringPiece& shorty);
- uint32_t GetDexMethodIndex() const;
+ uint32_t GetDexMethodIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetDexMethodIndex(uint32_t new_idx) {
- SetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_dex_index_), new_idx, false);
+ SetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_method_index_), new_idx, false);
}
- ObjectArray<String>* GetDexCacheStrings() const;
+ ObjectArray<String>* GetDexCacheStrings() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetDexCacheStrings(ObjectArray<String>* new_dex_cache_strings)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -185,41 +196,62 @@ class MANAGED ArtMethod : public Object {
return OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_types_);
}
- ObjectArray<ArtMethod>* GetDexCacheResolvedMethods() const;
+ ObjectArray<ArtMethod>* GetDexCacheResolvedMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetDexCacheResolvedMethods(ObjectArray<ArtMethod>* new_dex_cache_methods)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ObjectArray<Class>* GetDexCacheResolvedTypes() const;
+ ObjectArray<Class>* GetDexCacheResolvedTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_types)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Find the method that this method overrides
- ArtMethod* FindOverriddenMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ArtMethod* FindOverriddenMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* result, char result_type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- EntryPointFromInterpreter* GetEntryPointFromInterpreter() const {
- return GetFieldPtr<EntryPointFromInterpreter*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_interpreter_), false);
+ EntryPointFromInterpreter* GetEntryPointFromInterpreter() {
+ return GetFieldPtr<EntryPointFromInterpreter*>(
+ OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_interpreter_), false);
}
void SetEntryPointFromInterpreter(EntryPointFromInterpreter* entry_point_from_interpreter) {
- SetFieldPtr<EntryPointFromInterpreter*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_interpreter_), entry_point_from_interpreter, false);
+ SetFieldPtr<EntryPointFromInterpreter*>(
+ OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_interpreter_),
+ entry_point_from_interpreter, false);
}
- const void* GetEntryPointFromCompiledCode() const {
- return GetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_compiled_code_), false);
+ static MemberOffset EntryPointFromPortableCompiledCodeOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(ArtMethod, entry_point_from_portable_compiled_code_));
}
- void SetEntryPointFromCompiledCode(const void* entry_point_from_compiled_code) {
- SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_compiled_code_), entry_point_from_compiled_code, false);
+ const void* GetEntryPointFromPortableCompiledCode() {
+ return GetFieldPtr<const void*>(EntryPointFromPortableCompiledCodeOffset(), false);
}
- uint32_t GetCodeSize() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetEntryPointFromPortableCompiledCode(const void* entry_point_from_portable_compiled_code) {
+ SetFieldPtr<const void*>(EntryPointFromPortableCompiledCodeOffset(),
+ entry_point_from_portable_compiled_code, false);
+ }
+
+ static MemberOffset EntryPointFromQuickCompiledCodeOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(ArtMethod, entry_point_from_quick_compiled_code_));
+ }
- bool IsWithinCode(uintptr_t pc) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- uintptr_t code = reinterpret_cast<uintptr_t>(GetEntryPointFromCompiledCode());
+ const void* GetEntryPointFromQuickCompiledCode() {
+ return GetFieldPtr<const void*>(EntryPointFromQuickCompiledCodeOffset(), false);
+ }
+
+ void SetEntryPointFromQuickCompiledCode(const void* entry_point_from_quick_compiled_code) {
+ SetFieldPtr<const void*>(EntryPointFromQuickCompiledCodeOffset(),
+ entry_point_from_quick_compiled_code, false);
+ }
+
+
+ uint32_t GetCodeSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ bool IsWithinQuickCode(uintptr_t pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ uintptr_t code = reinterpret_cast<uintptr_t>(GetEntryPointFromQuickCompiledCode());
if (code == 0) {
return pc == 0;
}
@@ -231,45 +263,44 @@ class MANAGED ArtMethod : public Object {
return (code <= pc && pc <= code + GetCodeSize());
}
- void AssertPcIsWithinCode(uintptr_t pc) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- uint32_t GetOatCodeOffset() const;
+ void AssertPcIsWithinQuickCode(uintptr_t pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetOatCodeOffset(uint32_t code_offset);
-
- static MemberOffset GetEntryPointFromCompiledCodeOffset() {
- return OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_compiled_code_);
- }
+ uint32_t GetQuickOatCodeOffset();
+ uint32_t GetPortableOatCodeOffset();
+ void SetQuickOatCodeOffset(uint32_t code_offset);
+ void SetPortableOatCodeOffset(uint32_t code_offset);
// Callers should wrap the uint8_t* in a MappingTable instance for convenient access.
- const uint8_t* GetMappingTable() const {
- return GetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, mapping_table_), false);
+ const uint8_t* GetMappingTable() {
+ return GetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_mapping_table_),
+ false);
}
void SetMappingTable(const uint8_t* mapping_table) {
- SetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, mapping_table_),
- mapping_table, false);
+ SetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_mapping_table_),
+ mapping_table, false);
}
- uint32_t GetOatMappingTableOffset() const;
+ uint32_t GetOatMappingTableOffset();
void SetOatMappingTableOffset(uint32_t mapping_table_offset);
// Callers should wrap the uint8_t* in a VmapTable instance for convenient access.
- const uint8_t* GetVmapTable() const {
- return GetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, vmap_table_), false);
+ const uint8_t* GetVmapTable() {
+ return GetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_vmap_table_),
+ false);
}
void SetVmapTable(const uint8_t* vmap_table) {
- SetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, vmap_table_), vmap_table, false);
+ SetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_vmap_table_), vmap_table,
+ false);
}
- uint32_t GetOatVmapTableOffset() const;
+ uint32_t GetOatVmapTableOffset();
void SetOatVmapTableOffset(uint32_t vmap_table_offset);
- const uint8_t* GetNativeGcMap() const {
+ const uint8_t* GetNativeGcMap() {
return GetFieldPtr<uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, gc_map_), false);
}
void SetNativeGcMap(const uint8_t* data) {
@@ -278,31 +309,30 @@ class MANAGED ArtMethod : public Object {
// When building the oat need a convenient place to stuff the offset of the native GC map.
void SetOatNativeGcMapOffset(uint32_t gc_map_offset);
- uint32_t GetOatNativeGcMapOffset() const;
+ uint32_t GetOatNativeGcMapOffset();
- size_t GetFrameSizeInBytes() const {
+ size_t GetFrameSizeInBytes() {
DCHECK_EQ(sizeof(size_t), sizeof(uint32_t));
- size_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, frame_size_in_bytes_), false);
+ size_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_frame_size_in_bytes_), false);
DCHECK_LE(static_cast<size_t>(kStackAlignment), result);
return result;
}
void SetFrameSizeInBytes(size_t new_frame_size_in_bytes) {
- DCHECK_EQ(sizeof(size_t), sizeof(uint32_t));
- SetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, frame_size_in_bytes_),
+ SetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_frame_size_in_bytes_),
new_frame_size_in_bytes, false);
}
- size_t GetReturnPcOffsetInBytes() const {
+ size_t GetReturnPcOffsetInBytes() {
return GetFrameSizeInBytes() - kPointerSize;
}
- size_t GetSirtOffsetInBytes() const {
+ size_t GetSirtOffsetInBytes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
CHECK(IsNative());
return kPointerSize;
}
- bool IsRegistered() const;
+ bool IsRegistered();
void RegisterNative(Thread* self, const void* native_method, bool is_fast)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -310,10 +340,10 @@ class MANAGED ArtMethod : public Object {
void UnregisterNative(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static MemberOffset NativeMethodOffset() {
- return OFFSET_OF_OBJECT_MEMBER(ArtMethod, native_method_);
+ return OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_jni_);
}
- const void* GetNativeMethod() const {
+ const void* GetNativeMethod() {
return reinterpret_cast<const void*>(GetField32(NativeMethodOffset(), false));
}
@@ -323,47 +353,47 @@ class MANAGED ArtMethod : public Object {
return OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_);
}
- uint32_t GetCoreSpillMask() const {
- return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, core_spill_mask_), false);
+ uint32_t GetCoreSpillMask() {
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_core_spill_mask_), false);
}
void SetCoreSpillMask(uint32_t core_spill_mask) {
// Computed during compilation
- SetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, core_spill_mask_), core_spill_mask, false);
+ SetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_core_spill_mask_), core_spill_mask, false);
}
- uint32_t GetFpSpillMask() const {
- return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, fp_spill_mask_), false);
+ uint32_t GetFpSpillMask() {
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_fp_spill_mask_), false);
}
void SetFpSpillMask(uint32_t fp_spill_mask) {
// Computed during compilation
- SetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, fp_spill_mask_), fp_spill_mask, false);
+ SetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_fp_spill_mask_), fp_spill_mask, false);
}
// Is this a CalleSaveMethod or ResolutionMethod and therefore doesn't adhere to normal
// conventions for a method of managed code. Returns false for Proxy methods.
- bool IsRuntimeMethod() const;
+ bool IsRuntimeMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Is this a hand crafted method used for something like describing callee saves?
- bool IsCalleeSaveMethod() const;
+ bool IsCalleeSaveMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsResolutionMethod() const;
+ bool IsResolutionMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsImtConflictMethod() const;
+ bool IsImtConflictMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- uintptr_t NativePcOffset(const uintptr_t pc) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ uintptr_t NativePcOffset(const uintptr_t pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Converts a native PC to a dex PC.
- uint32_t ToDexPc(const uintptr_t pc) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ uint32_t ToDexPc(const uintptr_t pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Converts a dex PC to a native PC.
- uintptr_t ToNativePc(const uint32_t dex_pc) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ uintptr_t ToNativePc(const uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Find the catch block for the given exception type and dex_pc. When a catch block is found,
// indicates whether the found catch block is responsible for clearing the exception or whether
// a move-exception instruction is present.
- uint32_t FindCatchBlock(Class* exception_type, uint32_t dex_pc, bool* has_no_move_exception) const
+ uint32_t FindCatchBlock(Class* exception_type, uint32_t dex_pc, bool* has_no_move_exception)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static void SetClass(Class* java_lang_reflect_ArtMethod);
@@ -379,65 +409,83 @@ class MANAGED ArtMethod : public Object {
protected:
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
- // The class we are a part of
- Class* declaring_class_;
+ // The class we are a part of.
+ HeapReference<Class> declaring_class_;
- // short cuts to declaring_class_->dex_cache_ member for fast compiled code access
- ObjectArray<ArtMethod>* dex_cache_resolved_methods_;
+ // Short cuts to declaring_class_->dex_cache_ member for fast compiled code access.
+ HeapReference<ObjectArray<ArtMethod> > dex_cache_resolved_methods_;
- // short cuts to declaring_class_->dex_cache_ member for fast compiled code access
- ObjectArray<Class>* dex_cache_resolved_types_;
+ // Short cuts to declaring_class_->dex_cache_ member for fast compiled code access.
+ HeapReference<ObjectArray<Class> > dex_cache_resolved_types_;
- // short cuts to declaring_class_->dex_cache_ member for fast compiled code access
- ObjectArray<String>* dex_cache_strings_;
+ // Short cuts to declaring_class_->dex_cache_ member for fast compiled code access.
+ HeapReference<ObjectArray<String> > dex_cache_strings_;
- // Access flags; low 16 bits are defined by spec.
- uint32_t access_flags_;
+ // Method dispatch from the interpreter invokes this pointer which may cause a bridge into
+ // compiled code.
+ uint64_t entry_point_from_interpreter_;
- // Offset to the CodeItem.
- uint32_t code_item_offset_;
+ // Pointer to JNI function registered to this method, or a function to resolve the JNI function.
+ uint64_t entry_point_from_jni_;
+
+ // Method dispatch from portable compiled code invokes this pointer which may cause bridging into
+ // quick compiled code or the interpreter.
+ uint64_t entry_point_from_portable_compiled_code_;
- // Architecture-dependent register spill mask
- uint32_t core_spill_mask_;
+ // Method dispatch from quick compiled code invokes this pointer which may cause bridging into
+ // portable compiled code or the interpreter.
+ uint64_t entry_point_from_quick_compiled_code_;
- // Compiled code associated with this method for callers from managed code.
- // May be compiled managed code or a bridge for invoking a native method.
- // TODO: Break apart this into portable and quick.
- const void* entry_point_from_compiled_code_;
+ // Pointer to a data structure created by the compiler and used by the garbage collector to
+ // determine which registers hold live references to objects within the heap. Keyed by native PC
+ // offsets for the quick compiler and dex PCs for the portable.
+ uint64_t gc_map_;
+
+ // --- Quick compiler meta-data. ---
+ // TODO: merge and place in native heap, such as done with the code size.
+
+ // Pointer to a data structure created by the quick compiler to map between dex PCs and native
+ // PCs, and vice-versa.
+ uint64_t quick_mapping_table_;
+
+ // When a register is promoted into a register, the spill mask holds which registers hold dex
+ // registers. The first promoted register's corresponding dex register is vmap_table_[1], the Nth
+ // is vmap_table_[N]. vmap_table_[0] holds the length of the table.
+ uint64_t quick_vmap_table_;
- // Called by the interpreter to execute this method.
- EntryPointFromInterpreter* entry_point_from_interpreter_;
+ // --- End of quick compiler meta-data. ---
- // Architecture-dependent register spill mask
- uint32_t fp_spill_mask_;
+ // Access flags; low 16 bits are defined by spec.
+ uint32_t access_flags_;
- // Total size in bytes of the frame
- size_t frame_size_in_bytes_;
+ /* Dex file fields. The defining dex file is available via declaring_class_->dex_cache_ */
- // Garbage collection map of native PC offsets (quick) or dex PCs (portable) to reference bitmaps.
- const uint8_t* gc_map_;
+ // Offset to the CodeItem.
+ uint32_t dex_code_item_offset_;
- // Mapping from native pc to dex pc
- const uint32_t* mapping_table_;
+ // Index into method_ids of the dex file associated with this method.
+ uint32_t dex_method_index_;
- // Index into method_ids of the dex file associated with this method
- uint32_t method_dex_index_;
+ /* End of dex file fields. */
- // For concrete virtual methods, this is the offset of the method in Class::vtable_.
- //
- // For abstract methods in an interface class, this is the offset of the method in
- // "iftable_->Get(n)->GetMethodArray()".
- //
- // For static and direct methods this is the index in the direct methods table.
+ // Entry within a dispatch table for this method. For static/direct methods the index is into
+ // the declaringClass.directMethods, for virtual methods the vtable and for interface methods the
+ // ifTable.
uint32_t method_index_;
- // The target native method registered with this method
- const void* native_method_;
+ // --- Quick compiler meta-data. ---
+ // TODO: merge and place in native heap, such as done with the code size.
- // When a register is promoted into a register, the spill mask holds which registers hold dex
- // registers. The first promoted register's corresponding dex register is vmap_table_[1], the Nth
- // is vmap_table_[N]. vmap_table_[0] holds the length of the table.
- const uint16_t* vmap_table_;
+ // Bit map of spilled machine registers.
+ uint32_t quick_core_spill_mask_;
+
+ // Bit map of spilled floating point machine registers.
+ uint32_t quick_fp_spill_mask_;
+
+ // Fixed frame size for this method when executed.
+ uint32_t quick_frame_size_in_bytes_;
+
+ // --- End of quick compiler meta-data. ---
static Class* java_lang_reflect_ArtMethod_;
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 8ddaeb2..a5f743b 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -33,63 +33,61 @@
namespace art {
namespace mirror {
-inline size_t Class::GetObjectSize() const {
+inline uint32_t Class::GetObjectSize() {
DCHECK(!IsVariableSize()) << " class=" << PrettyTypeOf(this);
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, object_size_), false);
}
-inline Class* Class::GetSuperClass() const {
+inline Class* Class::GetSuperClass() {
// Can only get super class for loaded classes (hack for when runtime is
// initializing)
DCHECK(IsLoaded() || !Runtime::Current()->IsStarted()) << IsLoaded();
- return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Class, super_class_), false);
+ return GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(Class, super_class_), false);
}
-inline ClassLoader* Class::GetClassLoader() const {
- return GetFieldObject<ClassLoader*>(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), false);
+inline ClassLoader* Class::GetClassLoader() {
+ return GetFieldObject<ClassLoader>(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), false);
}
-inline DexCache* Class::GetDexCache() const {
- return GetFieldObject<DexCache*>(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_), false);
+inline DexCache* Class::GetDexCache() {
+ return GetFieldObject<DexCache>(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_), false);
}
-inline ObjectArray<ArtMethod>* Class::GetDirectMethods() const {
+inline ObjectArray<ArtMethod>* Class::GetDirectMethods() {
DCHECK(IsLoaded() || IsErroneous());
- return GetFieldObject<ObjectArray<ArtMethod>*>(
+ return GetFieldObject<ObjectArray<ArtMethod> >(
OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false);
}
inline void Class::SetDirectMethods(ObjectArray<ArtMethod>* new_direct_methods)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(NULL == GetFieldObject<ObjectArray<ArtMethod>*>(
+ DCHECK(NULL == GetFieldObject<ObjectArray<ArtMethod> >(
OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false));
DCHECK_NE(0, new_direct_methods->GetLength());
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_),
new_direct_methods, false);
}
-inline ArtMethod* Class::GetDirectMethod(int32_t i) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+inline ArtMethod* Class::GetDirectMethod(int32_t i) {
return GetDirectMethods()->Get(i);
}
inline void Class::SetDirectMethod(uint32_t i, ArtMethod* f) // TODO: uint16_t
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ObjectArray<ArtMethod>* direct_methods =
- GetFieldObject<ObjectArray<ArtMethod>*>(
+ GetFieldObject<ObjectArray<ArtMethod> >(
OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false);
direct_methods->Set(i, f);
}
// Returns the number of static, private, and constructor methods.
-inline size_t Class::NumDirectMethods() const {
+inline uint32_t Class::NumDirectMethods() {
return (GetDirectMethods() != NULL) ? GetDirectMethods()->GetLength() : 0;
}
-inline ObjectArray<ArtMethod>* Class::GetVirtualMethods() const {
+inline ObjectArray<ArtMethod>* Class::GetVirtualMethods() {
DCHECK(IsLoaded() || IsErroneous());
- return GetFieldObject<ObjectArray<ArtMethod>*>(
+ return GetFieldObject<ObjectArray<ArtMethod> >(
OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_), false);
}
@@ -101,18 +99,16 @@ inline void Class::SetVirtualMethods(ObjectArray<ArtMethod>* new_virtual_methods
new_virtual_methods, false);
}
-inline size_t Class::NumVirtualMethods() const {
+inline uint32_t Class::NumVirtualMethods() {
return (GetVirtualMethods() != NULL) ? GetVirtualMethods()->GetLength() : 0;
}
-inline ArtMethod* Class::GetVirtualMethod(uint32_t i) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+inline ArtMethod* Class::GetVirtualMethod(uint32_t i) {
DCHECK(IsResolved() || IsErroneous());
return GetVirtualMethods()->Get(i);
}
-inline ArtMethod* Class::GetVirtualMethodDuringLinking(uint32_t i) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+inline ArtMethod* Class::GetVirtualMethodDuringLinking(uint32_t i) {
DCHECK(IsLoaded() || IsErroneous());
return GetVirtualMethods()->Get(i);
}
@@ -120,35 +116,34 @@ inline ArtMethod* Class::GetVirtualMethodDuringLinking(uint32_t i) const
inline void Class::SetVirtualMethod(uint32_t i, ArtMethod* f) // TODO: uint16_t
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ObjectArray<ArtMethod>* virtual_methods =
- GetFieldObject<ObjectArray<ArtMethod>*>(
+ GetFieldObject<ObjectArray<ArtMethod> >(
OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_), false);
virtual_methods->Set(i, f);
}
-inline ObjectArray<ArtMethod>* Class::GetVTable() const {
+inline ObjectArray<ArtMethod>* Class::GetVTable() {
DCHECK(IsResolved() || IsErroneous());
- return GetFieldObject<ObjectArray<ArtMethod>*>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false);
+ return GetFieldObject<ObjectArray<ArtMethod> >(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false);
}
-inline ObjectArray<ArtMethod>* Class::GetVTableDuringLinking() const {
+inline ObjectArray<ArtMethod>* Class::GetVTableDuringLinking() {
DCHECK(IsLoaded() || IsErroneous());
- return GetFieldObject<ObjectArray<ArtMethod>*>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false);
+ return GetFieldObject<ObjectArray<ArtMethod> >(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false);
}
-inline void Class::SetVTable(ObjectArray<ArtMethod>* new_vtable)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+inline void Class::SetVTable(ObjectArray<ArtMethod>* new_vtable) {
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), new_vtable, false);
}
-inline ObjectArray<ArtMethod>* Class::GetImTable() const {
- return GetFieldObject<ObjectArray<ArtMethod>*>(OFFSET_OF_OBJECT_MEMBER(Class, imtable_), false);
+inline ObjectArray<ArtMethod>* Class::GetImTable() {
+ return GetFieldObject<ObjectArray<ArtMethod> >(OFFSET_OF_OBJECT_MEMBER(Class, imtable_), false);
}
inline void Class::SetImTable(ObjectArray<ArtMethod>* new_imtable) {
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, imtable_), new_imtable, false);
}
-inline bool Class::Implements(const Class* klass) const {
+inline bool Class::Implements(Class* klass) {
DCHECK(klass != NULL);
DCHECK(klass->IsInterface()) << PrettyClass(this);
// All interfaces implemented directly and by our superclass, and
@@ -183,13 +178,13 @@ inline bool Class::Implements(const Class* klass) const {
// Don't forget about primitive types.
// Object[] = int[] --> false
//
-inline bool Class::IsArrayAssignableFromArray(const Class* src) const {
+inline bool Class::IsArrayAssignableFromArray(Class* src) {
DCHECK(IsArrayClass()) << PrettyClass(this);
DCHECK(src->IsArrayClass()) << PrettyClass(src);
return GetComponentType()->IsAssignableFrom(src->GetComponentType());
}
-inline bool Class::IsAssignableFromArray(const Class* src) const {
+inline bool Class::IsAssignableFromArray(Class* src) {
DCHECK(!IsInterface()) << PrettyClass(this); // handled first in IsAssignableFrom
DCHECK(src->IsArrayClass()) << PrettyClass(src);
if (!IsArrayClass()) {
@@ -205,13 +200,13 @@ inline bool Class::IsAssignableFromArray(const Class* src) const {
template <bool throw_on_failure, bool use_referrers_cache>
inline bool Class::ResolvedFieldAccessTest(Class* access_to, ArtField* field,
- uint32_t field_idx, const DexCache* dex_cache) {
+ uint32_t field_idx, DexCache* dex_cache) {
DCHECK_EQ(use_referrers_cache, dex_cache == nullptr);
if (UNLIKELY(!this->CanAccess(access_to))) {
// The referrer class can't access the field's declaring class but may still be able
// to access the field if the FieldId specifies an accessible subclass of the declaring
// class rather than the declaring class itself.
- const DexCache* referrer_dex_cache = use_referrers_cache ? this->GetDexCache() : dex_cache;
+ DexCache* referrer_dex_cache = use_referrers_cache ? this->GetDexCache() : dex_cache;
uint32_t class_idx = referrer_dex_cache->GetDexFile()->GetFieldId(field_idx).class_idx_;
// The referenced class has already been resolved with the field, get it from the dex cache.
Class* dex_access_to = referrer_dex_cache->GetResolvedType(class_idx);
@@ -236,14 +231,14 @@ inline bool Class::ResolvedFieldAccessTest(Class* access_to, ArtField* field,
template <bool throw_on_failure, bool use_referrers_cache, InvokeType throw_invoke_type>
inline bool Class::ResolvedMethodAccessTest(Class* access_to, ArtMethod* method,
- uint32_t method_idx, const DexCache* dex_cache) {
+ uint32_t method_idx, DexCache* dex_cache) {
COMPILE_ASSERT(throw_on_failure || throw_invoke_type == kStatic, non_default_throw_invoke_type);
DCHECK_EQ(use_referrers_cache, dex_cache == nullptr);
if (UNLIKELY(!this->CanAccess(access_to))) {
// The referrer class can't access the method's declaring class but may still be able
// to access the method if the MethodId specifies an accessible subclass of the declaring
// class rather than the declaring class itself.
- const DexCache* referrer_dex_cache = use_referrers_cache ? this->GetDexCache() : dex_cache;
+ DexCache* referrer_dex_cache = use_referrers_cache ? this->GetDexCache() : dex_cache;
uint32_t class_idx = referrer_dex_cache->GetDexFile()->GetMethodId(method_idx).class_idx_;
// The referenced class has already been resolved with the method, get it from the dex cache.
Class* dex_access_to = referrer_dex_cache->GetResolvedType(class_idx);
@@ -268,8 +263,8 @@ inline bool Class::ResolvedMethodAccessTest(Class* access_to, ArtMethod* method,
}
inline bool Class::CanAccessResolvedField(Class* access_to, ArtField* field,
- const DexCache& dex_cache, uint32_t field_idx) {
- return ResolvedFieldAccessTest<false, false>(access_to, field, field_idx, &dex_cache);
+ DexCache* dex_cache, uint32_t field_idx) {
+ return ResolvedFieldAccessTest<false, false>(access_to, field, field_idx, dex_cache);
}
inline bool Class::CheckResolvedFieldAccess(Class* access_to, ArtField* field,
@@ -278,8 +273,8 @@ inline bool Class::CheckResolvedFieldAccess(Class* access_to, ArtField* field,
}
inline bool Class::CanAccessResolvedMethod(Class* access_to, ArtMethod* method,
- const DexCache& dex_cache, uint32_t method_idx) {
- return ResolvedMethodAccessTest<false, false, kStatic>(access_to, method, method_idx, &dex_cache);
+ DexCache* dex_cache, uint32_t method_idx) {
+ return ResolvedMethodAccessTest<false, false, kStatic>(access_to, method, method_idx, dex_cache);
}
template <InvokeType throw_invoke_type>
@@ -289,10 +284,10 @@ inline bool Class::CheckResolvedMethodAccess(Class* access_to, ArtMethod* method
nullptr);
}
-inline bool Class::IsSubClass(const Class* klass) const {
+inline bool Class::IsSubClass(Class* klass) {
DCHECK(!IsInterface()) << PrettyClass(this);
DCHECK(!IsArrayClass()) << PrettyClass(this);
- const Class* current = this;
+ Class* current = this;
do {
if (current == klass) {
return true;
@@ -302,7 +297,7 @@ inline bool Class::IsSubClass(const Class* klass) const {
return false;
}
-inline ArtMethod* Class::FindVirtualMethodForInterface(ArtMethod* method) const {
+inline ArtMethod* Class::FindVirtualMethodForInterface(ArtMethod* method) {
Class* declaring_class = method->GetDeclaringClass();
DCHECK(declaring_class != NULL) << PrettyClass(this);
DCHECK(declaring_class->IsInterface()) << PrettyMethod(method);
@@ -317,21 +312,19 @@ inline ArtMethod* Class::FindVirtualMethodForInterface(ArtMethod* method) const
return NULL;
}
-inline ArtMethod* Class::FindVirtualMethodForVirtual(ArtMethod* method) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+inline ArtMethod* Class::FindVirtualMethodForVirtual(ArtMethod* method) {
DCHECK(!method->GetDeclaringClass()->IsInterface() || method->IsMiranda());
// The argument method may from a super class.
// Use the index to a potentially overridden one for this instance's class.
return GetVTable()->Get(method->GetMethodIndex());
}
-inline ArtMethod* Class::FindVirtualMethodForSuper(ArtMethod* method) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+inline ArtMethod* Class::FindVirtualMethodForSuper(ArtMethod* method) {
DCHECK(!method->GetDeclaringClass()->IsInterface());
return GetSuperClass()->GetVTable()->Get(method->GetMethodIndex());
}
-inline ArtMethod* Class::FindVirtualMethodForVirtualOrInterface(ArtMethod* method) const {
+inline ArtMethod* Class::FindVirtualMethodForVirtualOrInterface(ArtMethod* method) {
if (method->IsDirect()) {
return method;
}
@@ -341,11 +334,11 @@ inline ArtMethod* Class::FindVirtualMethodForVirtualOrInterface(ArtMethod* metho
return FindVirtualMethodForVirtual(method);
}
-inline IfTable* Class::GetIfTable() const {
- return GetFieldObject<IfTable*>(OFFSET_OF_OBJECT_MEMBER(Class, iftable_), false);
+inline IfTable* Class::GetIfTable() {
+ return GetFieldObject<IfTable>(OFFSET_OF_OBJECT_MEMBER(Class, iftable_), false);
}
-inline int32_t Class::GetIfTableCount() const {
+inline int32_t Class::GetIfTableCount() {
IfTable* iftable = GetIfTable();
if (iftable == NULL) {
return 0;
@@ -357,59 +350,58 @@ inline void Class::SetIfTable(IfTable* new_iftable) {
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, iftable_), new_iftable, false);
}
-inline ObjectArray<ArtField>* Class::GetIFields() const {
+inline ObjectArray<ArtField>* Class::GetIFields() {
DCHECK(IsLoaded() || IsErroneous());
- return GetFieldObject<ObjectArray<ArtField>*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false);
+ return GetFieldObject<ObjectArray<ArtField>>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false);
}
inline void Class::SetIFields(ObjectArray<ArtField>* new_ifields)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(NULL == GetFieldObject<ObjectArray<ArtField>*>(
+ DCHECK(NULL == GetFieldObject<ObjectArray<ArtField> >(
OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false));
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields, false);
}
-inline ObjectArray<ArtField>* Class::GetSFields() const {
+inline ObjectArray<ArtField>* Class::GetSFields() {
DCHECK(IsLoaded() || IsErroneous());
- return GetFieldObject<ObjectArray<ArtField>*>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false);
+ return GetFieldObject<ObjectArray<ArtField> >(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false);
}
inline void Class::SetSFields(ObjectArray<ArtField>* new_sfields)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(NULL == GetFieldObject<ObjectArray<ArtField>*>(
+ DCHECK(NULL == GetFieldObject<ObjectArray<ArtField> >(
OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false));
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields, false);
}
-inline size_t Class::NumStaticFields() const {
+inline uint32_t Class::NumStaticFields() {
return (GetSFields() != NULL) ? GetSFields()->GetLength() : 0;
}
-inline ArtField* Class::GetStaticField(uint32_t i) const // TODO: uint16_t
+inline ArtField* Class::GetStaticField(uint32_t i) // TODO: uint16_t
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetSFields()->Get(i);
}
inline void Class::SetStaticField(uint32_t i, ArtField* f) // TODO: uint16_t
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- ObjectArray<ArtField>* sfields= GetFieldObject<ObjectArray<ArtField>*>(
+ ObjectArray<ArtField>* sfields= GetFieldObject<ObjectArray<ArtField> >(
OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false);
sfields->Set(i, f);
}
-inline size_t Class::NumInstanceFields() const {
+inline uint32_t Class::NumInstanceFields() {
return (GetIFields() != NULL) ? GetIFields()->GetLength() : 0;
}
-inline ArtField* Class::GetInstanceField(uint32_t i) const // TODO: uint16_t
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+inline ArtField* Class::GetInstanceField(uint32_t i) { // TODO: uint16_t
DCHECK_NE(NumInstanceFields(), 0U);
return GetIFields()->Get(i);
}
inline void Class::SetInstanceField(uint32_t i, ArtField* f) // TODO: uint16_t
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- ObjectArray<ArtField>* ifields= GetFieldObject<ObjectArray<ArtField>*>(
+ ObjectArray<ArtField>* ifields= GetFieldObject<ObjectArray<ArtField> >(
OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false);
ifields->Set(i, f);
}
@@ -419,7 +411,7 @@ inline void Class::SetVerifyErrorClass(Class* klass) {
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, verify_error_class_), klass, false);
}
-inline uint32_t Class::GetAccessFlags() const {
+inline uint32_t Class::GetAccessFlags() {
// Check class is loaded or this is java.lang.String that has a
// circularity issue during loading the names of its members
DCHECK(IsLoaded() || IsErroneous() ||
@@ -429,8 +421,8 @@ inline uint32_t Class::GetAccessFlags() const {
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false);
}
-inline String* Class::GetName() const {
- return GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Class, name_), false);
+inline String* Class::GetName() {
+ return GetFieldObject<String>(OFFSET_OF_OBJECT_MEMBER(Class, name_), false);
}
inline void Class::SetName(String* name) {
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, name_), name, false);
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index bd965fa..8051c9b 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -125,7 +125,7 @@ void Class::SetDexCache(DexCache* new_dex_cache) {
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_), new_dex_cache, false);
}
-void Class::SetClassSize(size_t new_class_size) {
+void Class::SetClassSize(uint32_t new_class_size) {
if (kIsDebugBuild && (new_class_size < GetClassSize())) {
DumpClass(LOG(ERROR), kDumpClassFullDetail);
CHECK_GE(new_class_size, GetClassSize()) << " class=" << PrettyTypeOf(this);
@@ -177,7 +177,7 @@ String* Class::ComputeName() {
return name;
}
-void Class::DumpClass(std::ostream& os, int flags) const {
+void Class::DumpClass(std::ostream& os, int flags) {
if ((flags & kDumpClassFullDetail) == 0) {
os << PrettyClass(this);
if ((flags & kDumpClassClassLoader) != 0) {
@@ -281,9 +281,9 @@ bool Class::IsInSamePackage(const StringPiece& descriptor1, const StringPiece& d
}
}
-bool Class::IsInSamePackage(const Class* that) const {
- const Class* klass1 = this;
- const Class* klass2 = that;
+bool Class::IsInSamePackage(Class* that) {
+ Class* klass1 = this;
+ Class* klass2 = that;
if (klass1 == klass2) {
return true;
}
@@ -307,7 +307,7 @@ bool Class::IsInSamePackage(const Class* that) const {
ClassHelper(klass2).GetDescriptor());
}
-bool Class::IsClassClass() const {
+bool Class::IsClassClass() {
Class* java_lang_Class = GetClass()->GetClass();
return this == java_lang_Class;
}
@@ -316,17 +316,17 @@ bool Class::IsStringClass() const {
return this == String::GetJavaLangString();
}
-bool Class::IsThrowableClass() const {
+bool Class::IsThrowableClass() {
return WellKnownClasses::ToClass(WellKnownClasses::java_lang_Throwable)->IsAssignableFrom(this);
}
-bool Class::IsArtFieldClass() const {
+bool Class::IsArtFieldClass() {
Class* java_lang_Class = GetClass();
Class* java_lang_reflect_ArtField = java_lang_Class->GetInstanceField(0)->GetClass();
return this == java_lang_reflect_ArtField;
}
-bool Class::IsArtMethodClass() const {
+bool Class::IsArtMethodClass() {
return this == ArtMethod::GetJavaLangReflectArtMethod();
}
@@ -334,7 +334,7 @@ void Class::SetClassLoader(ClassLoader* new_class_loader) {
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), new_class_loader, false);
}
-ArtMethod* Class::FindInterfaceMethod(const StringPiece& name, const Signature& signature) const {
+ArtMethod* Class::FindInterfaceMethod(const StringPiece& name, const Signature& signature) {
// Check the current class before checking the interfaces.
ArtMethod* method = FindDeclaredVirtualMethod(name, signature);
if (method != NULL) {
@@ -352,7 +352,7 @@ ArtMethod* Class::FindInterfaceMethod(const StringPiece& name, const Signature&
return NULL;
}
-ArtMethod* Class::FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const {
+ArtMethod* Class::FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_method_idx) {
// Check the current class before checking the interfaces.
ArtMethod* method = FindDeclaredVirtualMethod(dex_cache, dex_method_idx);
if (method != NULL) {
@@ -370,7 +370,7 @@ ArtMethod* Class::FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_me
return NULL;
}
-ArtMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature) const {
+ArtMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature) {
MethodHelper mh;
for (size_t i = 0; i < NumDirectMethods(); ++i) {
ArtMethod* method = GetDirectMethod(i);
@@ -382,7 +382,7 @@ ArtMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const String
return NULL;
}
-ArtMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const Signature& signature) const {
+ArtMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const Signature& signature) {
MethodHelper mh;
for (size_t i = 0; i < NumDirectMethods(); ++i) {
ArtMethod* method = GetDirectMethod(i);
@@ -394,7 +394,7 @@ ArtMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const Signat
return NULL;
}
-ArtMethod* Class::FindDeclaredDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const {
+ArtMethod* Class::FindDeclaredDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) {
if (GetDexCache() == dex_cache) {
for (size_t i = 0; i < NumDirectMethods(); ++i) {
ArtMethod* method = GetDirectMethod(i);
@@ -406,8 +406,8 @@ ArtMethod* Class::FindDeclaredDirectMethod(const DexCache* dex_cache, uint32_t d
return NULL;
}
-ArtMethod* Class::FindDirectMethod(const StringPiece& name, const StringPiece& signature) const {
- for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
+ArtMethod* Class::FindDirectMethod(const StringPiece& name, const StringPiece& signature) {
+ for (Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
ArtMethod* method = klass->FindDeclaredDirectMethod(name, signature);
if (method != NULL) {
return method;
@@ -416,8 +416,8 @@ ArtMethod* Class::FindDirectMethod(const StringPiece& name, const StringPiece& s
return NULL;
}
-ArtMethod* Class::FindDirectMethod(const StringPiece& name, const Signature& signature) const {
- for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
+ArtMethod* Class::FindDirectMethod(const StringPiece& name, const Signature& signature) {
+ for (Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
ArtMethod* method = klass->FindDeclaredDirectMethod(name, signature);
if (method != NULL) {
return method;
@@ -426,8 +426,8 @@ ArtMethod* Class::FindDirectMethod(const StringPiece& name, const Signature& sig
return NULL;
}
-ArtMethod* Class::FindDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const {
- for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
+ArtMethod* Class::FindDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) {
+ for (Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
ArtMethod* method = klass->FindDeclaredDirectMethod(dex_cache, dex_method_idx);
if (method != NULL) {
return method;
@@ -436,7 +436,7 @@ ArtMethod* Class::FindDirectMethod(const DexCache* dex_cache, uint32_t dex_metho
return NULL;
}
-ArtMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name, const StringPiece& signature) const {
+ArtMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name, const StringPiece& signature) {
MethodHelper mh;
for (size_t i = 0; i < NumVirtualMethods(); ++i) {
ArtMethod* method = GetVirtualMethod(i);
@@ -449,7 +449,7 @@ ArtMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name, const Strin
}
ArtMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name,
- const Signature& signature) const {
+ const Signature& signature) {
MethodHelper mh;
for (size_t i = 0; i < NumVirtualMethods(); ++i) {
ArtMethod* method = GetVirtualMethod(i);
@@ -461,7 +461,7 @@ ArtMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name,
return NULL;
}
-ArtMethod* Class::FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const {
+ArtMethod* Class::FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) {
if (GetDexCache() == dex_cache) {
for (size_t i = 0; i < NumVirtualMethods(); ++i) {
ArtMethod* method = GetVirtualMethod(i);
@@ -473,8 +473,8 @@ ArtMethod* Class::FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t
return NULL;
}
-ArtMethod* Class::FindVirtualMethod(const StringPiece& name, const StringPiece& signature) const {
- for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
+ArtMethod* Class::FindVirtualMethod(const StringPiece& name, const StringPiece& signature) {
+ for (Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
ArtMethod* method = klass->FindDeclaredVirtualMethod(name, signature);
if (method != NULL) {
return method;
@@ -483,8 +483,8 @@ ArtMethod* Class::FindVirtualMethod(const StringPiece& name, const StringPiece&
return NULL;
}
-ArtMethod* Class::FindVirtualMethod(const StringPiece& name, const Signature& signature) const {
- for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
+ArtMethod* Class::FindVirtualMethod(const StringPiece& name, const Signature& signature) {
+ for (Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
ArtMethod* method = klass->FindDeclaredVirtualMethod(name, signature);
if (method != NULL) {
return method;
@@ -493,8 +493,8 @@ ArtMethod* Class::FindVirtualMethod(const StringPiece& name, const Signature& si
return NULL;
}
-ArtMethod* Class::FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const {
- for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
+ArtMethod* Class::FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) {
+ for (Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
ArtMethod* method = klass->FindDeclaredVirtualMethod(dex_cache, dex_method_idx);
if (method != NULL) {
return method;
@@ -503,7 +503,7 @@ ArtMethod* Class::FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_meth
return NULL;
}
-ArtMethod* Class::FindClassInitializer() const {
+ArtMethod* Class::FindClassInitializer() {
for (size_t i = 0; i < NumDirectMethods(); ++i) {
ArtMethod* method = GetDirectMethod(i);
if (method->IsConstructor() && method->IsStatic()) {
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index a692381..cbec476 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -120,7 +120,7 @@ class MANAGED Class : public Object {
kStatusMax = 10,
};
- Status GetStatus() const {
+ Status GetStatus() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK_EQ(sizeof(Status), sizeof(uint32_t));
return static_cast<Status>(GetField32(OFFSET_OF_OBJECT_MEMBER(Class, status_), true));
}
@@ -132,107 +132,107 @@ class MANAGED Class : public Object {
}
// Returns true if the class has failed to link.
- bool IsErroneous() const {
+ bool IsErroneous() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetStatus() == kStatusError;
}
// Returns true if the class has been loaded.
- bool IsIdxLoaded() const {
+ bool IsIdxLoaded() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetStatus() >= kStatusIdx;
}
// Returns true if the class has been loaded.
- bool IsLoaded() const {
+ bool IsLoaded() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetStatus() >= kStatusLoaded;
}
// Returns true if the class has been linked.
- bool IsResolved() const {
+ bool IsResolved() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetStatus() >= kStatusResolved;
}
// Returns true if the class was compile-time verified.
- bool IsCompileTimeVerified() const {
+ bool IsCompileTimeVerified() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetStatus() >= kStatusRetryVerificationAtRuntime;
}
// Returns true if the class has been verified.
- bool IsVerified() const {
+ bool IsVerified() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetStatus() >= kStatusVerified;
}
// Returns true if the class is initializing.
- bool IsInitializing() const {
+ bool IsInitializing() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetStatus() >= kStatusInitializing;
}
// Returns true if the class is initialized.
- bool IsInitialized() const {
+ bool IsInitialized() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetStatus() == kStatusInitialized;
}
- uint32_t GetAccessFlags() const;
+ uint32_t GetAccessFlags() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetAccessFlags(uint32_t new_access_flags) {
+ void SetAccessFlags(uint32_t new_access_flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
SetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), new_access_flags, false);
}
// Returns true if the class is an interface.
- bool IsInterface() const {
+ bool IsInterface() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccInterface) != 0;
}
// Returns true if the class is declared public.
- bool IsPublic() const {
+ bool IsPublic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccPublic) != 0;
}
// Returns true if the class is declared final.
- bool IsFinal() const {
+ bool IsFinal() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccFinal) != 0;
}
- bool IsFinalizable() const {
+ bool IsFinalizable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccClassIsFinalizable) != 0;
}
- void SetFinalizable() {
+ void SetFinalizable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
uint32_t flags = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false);
SetAccessFlags(flags | kAccClassIsFinalizable);
}
// Returns true if the class is abstract.
- bool IsAbstract() const {
+ bool IsAbstract() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccAbstract) != 0;
}
// Returns true if the class is an annotation.
- bool IsAnnotation() const {
+ bool IsAnnotation() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccAnnotation) != 0;
}
// Returns true if the class is synthetic.
- bool IsSynthetic() const {
+ bool IsSynthetic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccSynthetic) != 0;
}
- bool IsReferenceClass() const {
+ bool IsReferenceClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccClassIsReference) != 0;
}
- bool IsWeakReferenceClass() const {
+ bool IsWeakReferenceClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccClassIsWeakReference) != 0;
}
- bool IsSoftReferenceClass() const {
+ bool IsSoftReferenceClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccReferenceFlagsMask) == kAccClassIsReference;
}
- bool IsFinalizerReferenceClass() const {
+ bool IsFinalizerReferenceClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccClassIsFinalizerReference) != 0;
}
- bool IsPhantomReferenceClass() const {
+ bool IsPhantomReferenceClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags() & kAccClassIsPhantomReference) != 0;
}
@@ -241,7 +241,7 @@ class MANAGED Class : public Object {
// For array classes, where all the classes are final due to there being no sub-classes, an
// Object[] may be assigned to by a String[] but a String[] may not be assigned to by other
// types as the component is final.
- bool CannotBeAssignedFromOtherTypes() const {
+ bool CannotBeAssignedFromOtherTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (!IsArrayClass()) {
return IsFinal();
} else {
@@ -254,12 +254,12 @@ class MANAGED Class : public Object {
}
}
- String* GetName() const; // Returns the cached name.
+ 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_);
- bool IsProxyClass() const {
+ bool IsProxyClass() {
// Read access flags without using getter as whether something is a proxy can be check in
// any loaded state
// TODO: switch to a check if the super class is java.lang.reflect.Proxy?
@@ -267,91 +267,91 @@ class MANAGED Class : public Object {
return (access_flags & kAccClassIsProxy) != 0;
}
- Primitive::Type GetPrimitiveType() const {
+ Primitive::Type GetPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK_EQ(sizeof(Primitive::Type), sizeof(int32_t));
return static_cast<Primitive::Type>(
GetField32(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_), false));
}
- void SetPrimitiveType(Primitive::Type new_type) {
+ void SetPrimitiveType(Primitive::Type new_type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK_EQ(sizeof(Primitive::Type), sizeof(int32_t));
SetField32(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_), new_type, false);
}
// Returns true if the class is a primitive type.
- bool IsPrimitive() const {
+ bool IsPrimitive() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetPrimitiveType() != Primitive::kPrimNot;
}
- bool IsPrimitiveBoolean() const {
+ bool IsPrimitiveBoolean() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetPrimitiveType() == Primitive::kPrimBoolean;
}
- bool IsPrimitiveByte() const {
+ bool IsPrimitiveByte() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetPrimitiveType() == Primitive::kPrimByte;
}
- bool IsPrimitiveChar() const {
+ bool IsPrimitiveChar() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetPrimitiveType() == Primitive::kPrimChar;
}
- bool IsPrimitiveShort() const {
+ bool IsPrimitiveShort() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetPrimitiveType() == Primitive::kPrimShort;
}
- bool IsPrimitiveInt() const {
+ bool IsPrimitiveInt() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetPrimitiveType() == Primitive::kPrimInt;
}
- bool IsPrimitiveLong() const {
+ bool IsPrimitiveLong() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetPrimitiveType() == Primitive::kPrimLong;
}
- bool IsPrimitiveFloat() const {
+ bool IsPrimitiveFloat() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetPrimitiveType() == Primitive::kPrimFloat;
}
- bool IsPrimitiveDouble() const {
+ bool IsPrimitiveDouble() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetPrimitiveType() == Primitive::kPrimDouble;
}
- bool IsPrimitiveVoid() const {
+ bool IsPrimitiveVoid() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetPrimitiveType() == Primitive::kPrimVoid;
}
- bool IsPrimitiveArray() const {
+ bool IsPrimitiveArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return IsArrayClass() && GetComponentType()->IsPrimitive();
}
// Depth of class from java.lang.Object
- size_t Depth() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- size_t depth = 0;
+ uint32_t Depth() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ uint32_t depth = 0;
for (Class* klass = this; klass->GetSuperClass() != NULL; klass = klass->GetSuperClass()) {
depth++;
}
return depth;
}
- bool IsArrayClass() const {
+ bool IsArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetComponentType() != NULL;
}
- bool IsClassClass() const;
+ bool IsClassClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsStringClass() const;
- bool IsThrowableClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool IsThrowableClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsArtFieldClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool IsArtFieldClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsArtMethodClass() const;
+ bool IsArtMethodClass();
static MemberOffset ComponentTypeOffset() {
return OFFSET_OF_OBJECT_MEMBER(Class, component_type_);
}
- Class* GetComponentType() const {
- return GetFieldObject<Class*>(ComponentTypeOffset(), false);
+ Class* GetComponentType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject<Class>(ComponentTypeOffset(), false);
}
void SetComponentType(Class* new_component_type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -360,18 +360,18 @@ class MANAGED Class : public Object {
SetFieldObject(ComponentTypeOffset(), new_component_type, false);
}
- size_t GetComponentSize() const {
+ size_t GetComponentSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return Primitive::ComponentSize(GetComponentType()->GetPrimitiveType());
}
- bool IsObjectClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ bool IsObjectClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return !IsPrimitive() && GetSuperClass() == NULL;
}
- bool IsInstantiable() const {
+ bool IsInstantiable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (!IsPrimitive() && !IsInterface() && !IsAbstract()) || ((IsAbstract()) && IsArrayClass());
}
- bool IsObjectArrayClass() const {
+ bool IsObjectArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetComponentType() != NULL && !GetComponentType()->IsPrimitive();
}
@@ -385,48 +385,44 @@ class MANAGED Class : public Object {
Object* AllocNonMovableObject(Thread* self)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsVariableSize() const {
+ bool IsVariableSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Classes and arrays vary in size, and so the object_size_ field cannot
// be used to get their instance size
return IsClassClass() || IsArrayClass();
}
- size_t SizeOf() const {
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
+ uint32_t SizeOf() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), false);
}
- size_t GetClassSize() const {
- DCHECK_EQ(sizeof(size_t), sizeof(uint32_t));
+ uint32_t GetClassSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), false);
}
- void SetClassSize(size_t new_class_size)
+ void SetClassSize(uint32_t new_class_size)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- size_t GetObjectSize() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ uint32_t GetObjectSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetObjectSize(size_t new_object_size) {
+ void SetObjectSize(uint32_t new_object_size) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(!IsVariableSize());
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
return SetField32(OFFSET_OF_OBJECT_MEMBER(Class, object_size_), new_object_size, false);
}
// Returns true if this class is in the same packages as that class.
- bool IsInSamePackage(const Class* that) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool IsInSamePackage(Class* that) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static bool IsInSamePackage(const StringPiece& descriptor1, const StringPiece& descriptor2);
// Returns true if this class can access that class.
- bool CanAccess(Class* that) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ bool CanAccess(Class* that) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return that->IsPublic() || this->IsInSamePackage(that);
}
// Can this class access a member in the provided class with the provided member access flags?
// Note that access to the class isn't checked in case the declaring class is protected and the
// method has been exposed by a public sub-class
- bool CanAccessMember(Class* access_to, uint32_t member_flags) const
+ bool CanAccessMember(Class* access_to, uint32_t member_flags)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Classes can access all of their own members
if (this == access_to) {
@@ -454,7 +450,7 @@ class MANAGED Class : public Object {
// Note that access to field's class is checked and this may require looking up the class
// referenced by the FieldId in the DexFile in case the declaring class is inaccessible.
bool CanAccessResolvedField(Class* access_to, ArtField* field,
- const DexCache& dex_cache, uint32_t field_idx)
+ DexCache* dex_cache, uint32_t field_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool CheckResolvedFieldAccess(Class* access_to, ArtField* field,
uint32_t field_idx)
@@ -464,22 +460,21 @@ class MANAGED Class : public Object {
// Note that access to methods's class is checked and this may require looking up the class
// referenced by the MethodId in the DexFile in case the declaring class is inaccessible.
bool CanAccessResolvedMethod(Class* access_to, ArtMethod* resolved_method,
- const DexCache& dex_cache, uint32_t method_idx)
+ DexCache* dex_cache, uint32_t method_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
template <InvokeType throw_invoke_type>
bool CheckResolvedMethodAccess(Class* access_to, ArtMethod* resolved_method,
uint32_t method_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsSubClass(const Class* klass) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool IsSubClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Can src be assigned to this class? For example, String can be assigned to Object (by an
// upcast), however, an Object cannot be assigned to a String as a potentially exception throwing
// downcast would be necessary. Similarly for interfaces, a class that implements (or an interface
// that extends) another can be assigned to its parent, but not vice-versa. All Classes may assign
// to themselves. Classes for primitive types may not assign to each other.
- inline bool IsAssignableFrom(const Class* src) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ inline bool IsAssignableFrom(Class* src) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(src != NULL);
if (this == src) {
// Can always assign to things of the same type.
@@ -496,18 +491,18 @@ class MANAGED Class : public Object {
}
}
- Class* GetSuperClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ Class* GetSuperClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetSuperClass(Class *new_super_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- // super class is assigned once, except during class linker initialization
- Class* old_super_class = GetFieldObject<Class*>(
- OFFSET_OF_OBJECT_MEMBER(Class, super_class_), false);
- DCHECK(old_super_class == NULL || old_super_class == new_super_class);
- DCHECK(new_super_class != NULL);
+ // Super class is assigned once, except during class linker initialization.
+ Class* old_super_class = GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(Class, super_class_),
+ false);
+ DCHECK(old_super_class == nullptr || old_super_class == new_super_class);
+ DCHECK(new_super_class != nullptr);
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, super_class_), new_super_class, false);
}
- bool HasSuperClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ bool HasSuperClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetSuperClass() != NULL;
}
@@ -515,7 +510,7 @@ class MANAGED Class : public Object {
return MemberOffset(OFFSETOF_MEMBER(Class, super_class_));
}
- ClassLoader* GetClassLoader() const;
+ ClassLoader* GetClassLoader() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetClassLoader(ClassLoader* new_cl) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -529,46 +524,43 @@ class MANAGED Class : public Object {
kDumpClassInitialized = (1 << 2),
};
- void DumpClass(std::ostream& os, int flags) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void DumpClass(std::ostream& os, int flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- DexCache* GetDexCache() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetDexCache(DexCache* new_dex_cache) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ObjectArray<ArtMethod>* GetDirectMethods() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ObjectArray<ArtMethod>* GetDirectMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetDirectMethods(ObjectArray<ArtMethod>* new_direct_methods)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* GetDirectMethod(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ArtMethod* GetDirectMethod(int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetDirectMethod(uint32_t i, ArtMethod* f) // TODO: uint16_t
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Returns the number of static, private, and constructor methods.
- size_t NumDirectMethods() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ uint32_t NumDirectMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ObjectArray<ArtMethod>* GetVirtualMethods() const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ObjectArray<ArtMethod>* GetVirtualMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetVirtualMethods(ObjectArray<ArtMethod>* new_virtual_methods)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Returns the number of non-inherited virtual methods.
- size_t NumVirtualMethods() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ uint32_t NumVirtualMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* GetVirtualMethod(uint32_t i) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ArtMethod* GetVirtualMethod(uint32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* GetVirtualMethodDuringLinking(uint32_t i) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ArtMethod* GetVirtualMethodDuringLinking(uint32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetVirtualMethod(uint32_t i, ArtMethod* f) // TODO: uint16_t
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ObjectArray<ArtMethod>* GetVTable() const;
+ ObjectArray<ArtMethod>* GetVTable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ObjectArray<ArtMethod>* GetVTableDuringLinking() const;
+ ObjectArray<ArtMethod>* GetVTableDuringLinking() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetVTable(ObjectArray<ArtMethod>* new_vtable)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -577,7 +569,7 @@ class MANAGED Class : public Object {
return OFFSET_OF_OBJECT_MEMBER(Class, vtable_);
}
- ObjectArray<ArtMethod>* GetImTable() const;
+ ObjectArray<ArtMethod>* GetImTable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetImTable(ObjectArray<ArtMethod>* new_imtable)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -588,105 +580,102 @@ class MANAGED Class : public Object {
// Given a method implemented by this class but potentially from a super class, return the
// specific implementation method for this class.
- ArtMethod* FindVirtualMethodForVirtual(ArtMethod* method) const
+ ArtMethod* FindVirtualMethodForVirtual(ArtMethod* method)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Given a method implemented by this class' super class, return the specific implementation
// method for this class.
- ArtMethod* FindVirtualMethodForSuper(ArtMethod* method) const
+ ArtMethod* FindVirtualMethodForSuper(ArtMethod* method)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Given a method implemented by this class, but potentially from a
// super class or interface, return the specific implementation
// method for this class.
- ArtMethod* FindVirtualMethodForInterface(ArtMethod* method) const
+ ArtMethod* FindVirtualMethodForInterface(ArtMethod* method)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE;
- ArtMethod* FindVirtualMethodForVirtualOrInterface(ArtMethod* method) const
+ ArtMethod* FindVirtualMethodForVirtualOrInterface(ArtMethod* method)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindInterfaceMethod(const StringPiece& name, const Signature& signature) const
+ ArtMethod* FindInterfaceMethod(const StringPiece& name, const Signature& signature)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const
+ ArtMethod* FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_method_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature) const
+ ArtMethod* FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindDeclaredDirectMethod(const StringPiece& name, const Signature& signature) const
+ ArtMethod* FindDeclaredDirectMethod(const StringPiece& name, const Signature& signature)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindDeclaredDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const
+ ArtMethod* FindDeclaredDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindDirectMethod(const StringPiece& name, const StringPiece& signature) const
+ ArtMethod* FindDirectMethod(const StringPiece& name, const StringPiece& signature)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindDirectMethod(const StringPiece& name, const Signature& signature) const
+ ArtMethod* FindDirectMethod(const StringPiece& name, const Signature& signature)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const
+ ArtMethod* FindDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindDeclaredVirtualMethod(const StringPiece& name, const StringPiece& signature) const
+ ArtMethod* FindDeclaredVirtualMethod(const StringPiece& name, const StringPiece& signature)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindDeclaredVirtualMethod(const StringPiece& name, const Signature& signature) const
+ ArtMethod* FindDeclaredVirtualMethod(const StringPiece& name, const Signature& signature)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const
+ ArtMethod* FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindVirtualMethod(const StringPiece& name, const StringPiece& signature) const
+ ArtMethod* FindVirtualMethod(const StringPiece& name, const StringPiece& signature)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindVirtualMethod(const StringPiece& name, const Signature& signature) const
+ ArtMethod* FindVirtualMethod(const StringPiece& name, const Signature& signature)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const
+ ArtMethod* FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtMethod* FindClassInitializer() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ArtMethod* FindClassInitializer() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- int32_t GetIfTableCount() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ int32_t GetIfTableCount() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- IfTable* GetIfTable() const;
+ IfTable* GetIfTable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetIfTable(IfTable* new_iftable) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Get instance fields of the class (See also GetSFields).
- ObjectArray<ArtField>* GetIFields() const;
+ ObjectArray<ArtField>* GetIFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetIFields(ObjectArray<ArtField>* new_ifields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- size_t NumInstanceFields() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ uint32_t NumInstanceFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtField* GetInstanceField(uint32_t i) const // TODO: uint16_t
+ ArtField* GetInstanceField(uint32_t i) // TODO: uint16_t
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetInstanceField(uint32_t i, ArtField* f) // TODO: uint16_t
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Returns the number of instance fields containing reference types.
- size_t NumReferenceInstanceFields() const {
+ uint32_t NumReferenceInstanceFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(IsResolved() || IsErroneous());
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_instance_fields_), false);
}
- size_t NumReferenceInstanceFieldsDuringLinking() const {
+ uint32_t NumReferenceInstanceFieldsDuringLinking() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(IsLoaded() || IsErroneous());
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_instance_fields_), false);
}
- void SetNumReferenceInstanceFields(size_t new_num) {
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
+ void SetNumReferenceInstanceFields(uint32_t new_num) {
SetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_instance_fields_), new_num, false);
}
- uint32_t GetReferenceInstanceOffsets() const {
+ uint32_t GetReferenceInstanceOffsets() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(IsResolved() || IsErroneous());
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_), false);
}
@@ -700,39 +689,39 @@ class MANAGED Class : public Object {
}
// Returns the number of static fields containing reference types.
- size_t NumReferenceStaticFields() const {
+ uint32_t NumReferenceStaticFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(IsResolved() || IsErroneous());
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_static_fields_), false);
}
- size_t NumReferenceStaticFieldsDuringLinking() const {
+ uint32_t NumReferenceStaticFieldsDuringLinking() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(IsLoaded() || IsErroneous());
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_static_fields_), false);
}
- void SetNumReferenceStaticFields(size_t new_num) {
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
+ void SetNumReferenceStaticFields(uint32_t new_num) {
SetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_static_fields_), new_num, false);
}
// Gets the static fields of the class.
- ObjectArray<ArtField>* GetSFields() const;
+ ObjectArray<ArtField>* GetSFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetSFields(ObjectArray<ArtField>* new_sfields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- size_t NumStaticFields() const;
+ uint32_t NumStaticFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ArtField* GetStaticField(uint32_t i) const; // TODO: uint16_t
+ // TODO: uint16_t
+ ArtField* GetStaticField(uint32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetStaticField(uint32_t i, ArtField* f); // TODO: uint16_t
+ // TODO: uint16_t
+ void SetStaticField(uint32_t i, ArtField* f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- uint32_t GetReferenceStaticOffsets() const {
+ uint32_t GetReferenceStaticOffsets() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_static_offsets_), false);
}
- void SetReferenceStaticOffsets(uint32_t new_reference_offsets);
+ void SetReferenceStaticOffsets(uint32_t new_reference_offsets)
+ 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)
@@ -768,33 +757,33 @@ class MANAGED Class : public Object {
ArtField* FindDeclaredStaticField(const DexCache* dex_cache, uint32_t dex_field_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- pid_t GetClinitThreadId() const {
+ pid_t GetClinitThreadId() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(IsIdxLoaded() || IsErroneous());
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_), false);
}
- void SetClinitThreadId(pid_t new_clinit_thread_id) {
+ void SetClinitThreadId(pid_t new_clinit_thread_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
SetField32(OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_), new_clinit_thread_id, false);
}
- Class* GetVerifyErrorClass() const {
+ Class* GetVerifyErrorClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// DCHECK(IsErroneous());
- return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Class, verify_error_class_), false);
+ return GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(Class, verify_error_class_), false);
}
- uint16_t GetDexClassDefIndex() const {
+ uint16_t GetDexClassDefIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, dex_class_def_idx_), false);
}
- void SetDexClassDefIndex(uint16_t class_def_idx) {
+ void SetDexClassDefIndex(uint16_t class_def_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
SetField32(OFFSET_OF_OBJECT_MEMBER(Class, dex_class_def_idx_), class_def_idx, false);
}
- uint16_t GetDexTypeIndex() const {
+ uint16_t GetDexTypeIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, dex_type_idx_), false);
}
- void SetDexTypeIndex(uint16_t type_idx) {
+ void SetDexTypeIndex(uint16_t type_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
SetField32(OFFSET_OF_OBJECT_MEMBER(Class, dex_type_idx_), type_idx, false);
}
@@ -817,35 +806,32 @@ class MANAGED Class : public Object {
template <bool throw_on_failure, bool use_referrers_cache>
bool ResolvedFieldAccessTest(Class* access_to, ArtField* field,
- uint32_t field_idx, const DexCache* dex_cache)
+ uint32_t field_idx, DexCache* dex_cache)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
template <bool throw_on_failure, bool use_referrers_cache, InvokeType throw_invoke_type>
bool ResolvedMethodAccessTest(Class* access_to, ArtMethod* resolved_method,
- uint32_t method_idx, const DexCache* dex_cache)
+ uint32_t method_idx, DexCache* dex_cache)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool Implements(const Class* klass) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsArrayAssignableFromArray(const Class* klass) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsAssignableFromArray(const Class* klass) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool Implements(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool IsArrayAssignableFromArray(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool IsAssignableFromArray(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void CheckObjectAlloc() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// defining class loader, or NULL for the "bootstrap" system loader
- ClassLoader* class_loader_;
+ HeapReference<ClassLoader> class_loader_;
// For array classes, the component class object for instanceof/checkcast
// (for String[][][], this will be String[][]). NULL for non-array classes.
- Class* component_type_;
+ HeapReference<Class> component_type_;
// DexCache of resolved constant pool entries (will be NULL for classes generated by the
// runtime such as arrays and primitive classes).
- DexCache* dex_cache_;
+ HeapReference<DexCache> dex_cache_;
// static, private, and <init> methods
- ObjectArray<ArtMethod>* direct_methods_;
+ HeapReference<ObjectArray<ArtMethod> > direct_methods_;
// instance fields
//
@@ -857,7 +843,7 @@ class MANAGED Class : public Object {
// All instance fields that refer to objects are guaranteed to be at
// the beginning of the field list. num_reference_instance_fields_
// specifies the number of reference fields.
- ObjectArray<ArtField>* ifields_;
+ HeapReference<ObjectArray<ArtField> > ifields_;
// The interface table (iftable_) contains pairs of a interface class and an array of the
// interface methods. There is one pair per interface supported by this class. That means one
@@ -870,38 +856,38 @@ class MANAGED Class : public Object {
//
// For every interface a concrete class implements, we create an array of the concrete vtable_
// methods for the methods in the interface.
- IfTable* iftable_;
+ HeapReference<IfTable> iftable_;
// Interface method table (imt), for quick "invoke-interface".
- ObjectArray<ArtMethod>* imtable_;
+ HeapReference<ObjectArray<ArtMethod> > imtable_;
- // descriptor for the class such as "java.lang.Class" or "[C". Lazily initialized by ComputeName
- String* name_;
+ // Descriptor for the class such as "java.lang.Class" or "[C". Lazily initialized by ComputeName
+ HeapReference<String> name_;
// Static fields
- ObjectArray<ArtField>* sfields_;
+ HeapReference<ObjectArray<ArtField>> sfields_;
// The superclass, or NULL if this is java.lang.Object, an interface or primitive type.
- Class* super_class_;
+ HeapReference<Class> super_class_;
// If class verify fails, we must return same error on subsequent tries.
- Class* verify_error_class_;
+ HeapReference<Class> verify_error_class_;
// Virtual methods defined in this class; invoked through vtable.
- ObjectArray<ArtMethod>* virtual_methods_;
+ HeapReference<ObjectArray<ArtMethod> > virtual_methods_;
// Virtual method table (vtable), for use by "invoke-virtual". The vtable from the superclass is
// copied in, and virtual methods from our class either replace those from the super or are
// appended. For abstract classes, methods may be created in the vtable that aren't in
// virtual_ methods_ for miranda methods.
- ObjectArray<ArtMethod>* vtable_;
+ HeapReference<ObjectArray<ArtMethod> > vtable_;
// Access flags; low 16 bits are defined by VM spec.
uint32_t access_flags_;
// Total size of the Class instance; used when allocating storage on gc heap.
// See also object_size_.
- size_t class_size_;
+ uint32_t class_size_;
// Tid used to check for recursive <clinit> invocation.
pid_t clinit_thread_id_;
@@ -915,15 +901,15 @@ class MANAGED Class : public Object {
int32_t dex_type_idx_;
// Number of instance fields that are object refs.
- size_t num_reference_instance_fields_;
+ uint32_t num_reference_instance_fields_;
// Number of static fields that are object refs,
- size_t num_reference_static_fields_;
+ uint32_t num_reference_static_fields_;
// Total object size; used when allocating storage on gc heap.
// (For interfaces and abstract classes this will be zero.)
// See also class_size_.
- size_t object_size_;
+ uint32_t object_size_;
// Primitive type value, or Primitive::kPrimNot (0); set for generated primitive classes.
Primitive::Type primitive_type_;
diff --git a/runtime/mirror/class_loader.h b/runtime/mirror/class_loader.h
index 415cb67..69accf5 100644
--- a/runtime/mirror/class_loader.h
+++ b/runtime/mirror/class_loader.h
@@ -32,9 +32,9 @@ namespace mirror {
class MANAGED ClassLoader : public Object {
private:
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
- Object* packages_;
- ClassLoader* parent_;
- Object* proxyCache_;
+ HeapReference<Object> packages_;
+ HeapReference<ClassLoader> parent_;
+ HeapReference<Object> proxyCache_;
friend struct art::ClassLoaderOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(ClassLoader);
diff --git a/runtime/mirror/dex_cache-inl.h b/runtime/mirror/dex_cache-inl.h
index da26be5..f59c3a2 100644
--- a/runtime/mirror/dex_cache-inl.h
+++ b/runtime/mirror/dex_cache-inl.h
@@ -22,7 +22,7 @@
namespace art {
namespace mirror {
-inline ArtMethod* DexCache::GetResolvedMethod(uint32_t method_idx) const
+inline ArtMethod* DexCache::GetResolvedMethod(uint32_t method_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ArtMethod* method = GetResolvedMethods()->Get(method_idx);
// Hide resolution trampoline methods from the caller
diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h
index a5fe598..99529f0 100644
--- a/runtime/mirror/dex_cache.h
+++ b/runtime/mirror/dex_cache.h
@@ -52,8 +52,8 @@ class MANAGED DexCache : public Object {
void Fixup(ArtMethod* trampoline) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- String* GetLocation() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), false);
+ String* GetLocation() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject<String>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), false);
}
static MemberOffset StringsOffset() {
@@ -68,24 +68,23 @@ class MANAGED DexCache : public Object {
return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_methods_);
}
- size_t NumStrings() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ size_t NumStrings() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetStrings()->GetLength();
}
- size_t NumResolvedTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ size_t NumResolvedTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetResolvedTypes()->GetLength();
}
- size_t NumResolvedMethods() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ size_t NumResolvedMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetResolvedMethods()->GetLength();
}
- size_t NumResolvedFields() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ size_t NumResolvedFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetResolvedFields()->GetLength();
}
- String* GetResolvedString(uint32_t string_idx) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ String* GetResolvedString(uint32_t string_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetStrings()->Get(string_idx);
}
@@ -94,8 +93,7 @@ class MANAGED DexCache : public Object {
GetStrings()->Set(string_idx, resolved);
}
- Class* GetResolvedType(uint32_t type_idx) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ Class* GetResolvedType(uint32_t type_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetResolvedTypes()->Get(type_idx);
}
@@ -104,16 +102,14 @@ class MANAGED DexCache : public Object {
GetResolvedTypes()->Set(type_idx, resolved);
}
- ArtMethod* GetResolvedMethod(uint32_t method_idx) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ArtMethod* GetResolvedMethod(uint32_t method_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetResolvedMethod(uint32_t method_idx, ArtMethod* resolved)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
GetResolvedMethods()->Set(method_idx, resolved);
}
- ArtField* GetResolvedField(uint32_t field_idx) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ ArtField* GetResolvedField(uint32_t field_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetResolvedFields()->Get(field_idx);
}
@@ -122,28 +118,24 @@ class MANAGED DexCache : public Object {
GetResolvedFields()->Set(field_idx, resolved);
}
- ObjectArray<String>* GetStrings() const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetFieldObject< ObjectArray<String>* >(StringsOffset(), false);
+ ObjectArray<String>* GetStrings() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject< ObjectArray<String> >(StringsOffset(), false);
}
- ObjectArray<Class>* GetResolvedTypes() const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetFieldObject< ObjectArray<Class>* >(
+ ObjectArray<Class>* GetResolvedTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject<ObjectArray<Class> >(
OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_types_), false);
}
- ObjectArray<ArtMethod>* GetResolvedMethods() const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetFieldObject< ObjectArray<ArtMethod>* >(ResolvedMethodsOffset(), false);
+ ObjectArray<ArtMethod>* GetResolvedMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject< ObjectArray<ArtMethod> >(ResolvedMethodsOffset(), false);
}
- ObjectArray<ArtField>* GetResolvedFields() const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetFieldObject< ObjectArray<ArtField>* >(ResolvedFieldsOffset(), false);
+ ObjectArray<ArtField>* GetResolvedFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject<ObjectArray<ArtField> >(ResolvedFieldsOffset(), false);
}
- const DexFile* GetDexFile() const {
+ const DexFile* GetDexFile() {
return GetFieldPtr<const DexFile*>(OFFSET_OF_OBJECT_MEMBER(DexCache, dex_file_), false);
}
@@ -152,13 +144,13 @@ class MANAGED DexCache : public Object {
}
private:
- Object* dex_;
- String* location_;
- ObjectArray<ArtField>* resolved_fields_;
- ObjectArray<ArtMethod>* resolved_methods_;
- ObjectArray<Class>* resolved_types_;
- ObjectArray<String>* strings_;
- uint32_t dex_file_;
+ HeapReference<Object> dex_;
+ HeapReference<String> location_;
+ HeapReference<ObjectArray<ArtField> > resolved_fields_;
+ HeapReference<ObjectArray<ArtMethod> > resolved_methods_;
+ HeapReference<ObjectArray<Class> > resolved_types_;
+ HeapReference<ObjectArray<String> > strings_;
+ uint64_t dex_file_;
friend struct art::DexCacheOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(DexCache);
diff --git a/runtime/mirror/iftable.h b/runtime/mirror/iftable.h
index 421893d..be83d03 100644
--- a/runtime/mirror/iftable.h
+++ b/runtime/mirror/iftable.h
@@ -24,7 +24,7 @@ namespace mirror {
class MANAGED IfTable : public ObjectArray<Object> {
public:
- Class* GetInterface(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ Class* GetInterface(int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Class* interface = Get((i * kMax) + kInterface)->AsClass();
DCHECK(interface != NULL);
return interface;
@@ -32,15 +32,14 @@ class MANAGED IfTable : public ObjectArray<Object> {
void SetInterface(int32_t i, Class* interface) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ObjectArray<ArtMethod>* GetMethodArray(int32_t i) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ ObjectArray<ArtMethod>* GetMethodArray(int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ObjectArray<ArtMethod>* method_array =
down_cast<ObjectArray<ArtMethod>*>(Get((i * kMax) + kMethodArray));
DCHECK(method_array != NULL);
return method_array;
}
- size_t GetMethodArrayCount(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ size_t GetMethodArrayCount(int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ObjectArray<ArtMethod>* method_array =
down_cast<ObjectArray<ArtMethod>*>(Get((i * kMax) + kMethodArray));
if (method_array == NULL) {
@@ -56,7 +55,7 @@ class MANAGED IfTable : public ObjectArray<Object> {
Set((i * kMax) + kMethodArray, new_ma);
}
- size_t Count() const {
+ size_t Count() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetLength() / kMax;
}
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index 9161bc5..afa4112 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -32,19 +32,18 @@
namespace art {
namespace mirror {
-inline Class* Object::GetClass() const {
- return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Object, klass_), false);
+inline Class* Object::GetClass() {
+ return GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(Object, klass_), false);
}
inline void Object::SetClass(Class* new_klass) {
- // new_klass may be NULL prior to class linker initialization
- // We don't mark the card since the class is guaranteed to be referenced from another location.
- // Proxy classes are held live by the class loader, and other classes are roots of the class
- // linker.
- SetFieldPtr(OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass, false, false);
+ // new_klass may be NULL prior to class linker initialization.
+ // We don't mark the card as this occurs as part of object allocation. Not all objects have
+ // backing cards, such as large objects.
+ SetFieldObjectWithoutWriteBarrier(OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass, false, false);
}
-inline LockWord Object::GetLockWord() const {
+inline LockWord Object::GetLockWord() {
return LockWord(GetField32(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), true));
}
@@ -85,19 +84,19 @@ inline void Object::Wait(Thread* self, int64_t ms, int32_t ns) {
Monitor::Wait(self, this, ms, ns, true, kTimedWaiting);
}
-inline bool Object::VerifierInstanceOf(const Class* klass) const {
+inline bool Object::VerifierInstanceOf(Class* klass) {
DCHECK(klass != NULL);
DCHECK(GetClass() != NULL);
return klass->IsInterface() || InstanceOf(klass);
}
-inline bool Object::InstanceOf(const Class* klass) const {
+inline bool Object::InstanceOf(Class* klass) {
DCHECK(klass != NULL);
DCHECK(GetClass() != NULL);
return klass->IsAssignableFrom(GetClass());
}
-inline bool Object::IsClass() const {
+inline bool Object::IsClass() {
Class* java_lang_Class = GetClass()->GetClass();
return GetClass() == java_lang_Class;
}
@@ -107,12 +106,7 @@ inline Class* Object::AsClass() {
return down_cast<Class*>(this);
}
-inline const Class* Object::AsClass() const {
- DCHECK(IsClass());
- return down_cast<const Class*>(this);
-}
-
-inline bool Object::IsObjectArray() const {
+inline bool Object::IsObjectArray() {
return IsArrayInstance() && !GetClass()->GetComponentType()->IsPrimitive();
}
@@ -122,17 +116,11 @@ inline ObjectArray<T>* Object::AsObjectArray() {
return down_cast<ObjectArray<T>*>(this);
}
-template<class T>
-inline const ObjectArray<T>* Object::AsObjectArray() const {
- DCHECK(IsObjectArray());
- return down_cast<const ObjectArray<T>*>(this);
-}
-
-inline bool Object::IsArrayInstance() const {
+inline bool Object::IsArrayInstance() {
return GetClass()->IsArrayClass();
}
-inline bool Object::IsArtField() const {
+inline bool Object::IsArtField() {
return GetClass()->IsArtFieldClass();
}
@@ -141,12 +129,7 @@ inline ArtField* Object::AsArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_
return down_cast<ArtField*>(this);
}
-inline const ArtField* Object::AsArtField() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(IsArtField());
- return down_cast<const ArtField*>(this);
-}
-
-inline bool Object::IsArtMethod() const {
+inline bool Object::IsArtMethod() {
return GetClass()->IsArtMethodClass();
}
@@ -155,12 +138,7 @@ inline ArtMethod* Object::AsArtMethod() {
return down_cast<ArtMethod*>(this);
}
-inline const ArtMethod* Object::AsArtMethod() const {
- DCHECK(IsArtMethod());
- return down_cast<const ArtMethod*>(this);
-}
-
-inline bool Object::IsReferenceInstance() const {
+inline bool Object::IsReferenceInstance() {
return GetClass()->IsReferenceClass();
}
@@ -169,11 +147,6 @@ inline Array* Object::AsArray() {
return down_cast<Array*>(this);
}
-inline const Array* Object::AsArray() const {
- DCHECK(IsArrayInstance());
- return down_cast<const Array*>(this);
-}
-
inline BooleanArray* Object::AsBooleanArray() {
DCHECK(GetClass()->IsArrayClass());
DCHECK(GetClass()->GetComponentType()->IsPrimitiveBoolean());
@@ -186,6 +159,13 @@ inline ByteArray* Object::AsByteArray() {
return down_cast<ByteArray*>(this);
}
+inline ByteArray* Object::AsByteSizedArray() {
+ DCHECK(GetClass()->IsArrayClass());
+ DCHECK(GetClass()->GetComponentType()->IsPrimitiveByte() ||
+ GetClass()->GetComponentType()->IsPrimitiveBoolean());
+ return down_cast<ByteArray*>(this);
+}
+
inline CharArray* Object::AsCharArray() {
DCHECK(GetClass()->IsArrayClass());
DCHECK(GetClass()->GetComponentType()->IsPrimitiveChar());
@@ -198,6 +178,13 @@ inline ShortArray* Object::AsShortArray() {
return down_cast<ShortArray*>(this);
}
+inline ShortArray* Object::AsShortSizedArray() {
+ DCHECK(GetClass()->IsArrayClass());
+ DCHECK(GetClass()->GetComponentType()->IsPrimitiveShort() ||
+ GetClass()->GetComponentType()->IsPrimitiveChar());
+ return down_cast<ShortArray*>(this);
+}
+
inline IntArray* Object::AsIntArray() {
DCHECK(GetClass()->IsArrayClass());
DCHECK(GetClass()->GetComponentType()->IsPrimitiveInt() ||
@@ -222,23 +209,23 @@ inline Throwable* Object::AsThrowable() {
return down_cast<Throwable*>(this);
}
-inline bool Object::IsWeakReferenceInstance() const {
+inline bool Object::IsWeakReferenceInstance() {
return GetClass()->IsWeakReferenceClass();
}
-inline bool Object::IsSoftReferenceInstance() const {
+inline bool Object::IsSoftReferenceInstance() {
return GetClass()->IsSoftReferenceClass();
}
-inline bool Object::IsFinalizerReferenceInstance() const {
+inline bool Object::IsFinalizerReferenceInstance() {
return GetClass()->IsFinalizerReferenceClass();
}
-inline bool Object::IsPhantomReferenceInstance() const {
+inline bool Object::IsPhantomReferenceInstance() {
return GetClass()->IsPhantomReferenceClass();
}
-inline size_t Object::SizeOf() const {
+inline size_t Object::SizeOf() {
size_t result;
if (IsArrayInstance()) {
result = AsArray()->SizeOf();
@@ -253,13 +240,13 @@ inline size_t Object::SizeOf() const {
return result;
}
-inline uint32_t Object::GetField32(MemberOffset field_offset, bool is_volatile) const {
+inline uint32_t Object::GetField32(MemberOffset field_offset, bool is_volatile) {
VerifyObject(this);
const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value();
const int32_t* word_addr = reinterpret_cast<const int32_t*>(raw_addr);
if (UNLIKELY(is_volatile)) {
int32_t result = *(reinterpret_cast<volatile int32_t*>(const_cast<int32_t*>(word_addr)));
- QuasiAtomic::MembarLoadLoad();
+ QuasiAtomic::MembarLoadLoad(); // Ensure volatile loads don't re-order.
return result;
} else {
return *word_addr;
@@ -276,7 +263,7 @@ inline void Object::SetField32(MemberOffset field_offset, uint32_t new_value, bo
if (UNLIKELY(is_volatile)) {
QuasiAtomic::MembarStoreStore(); // Ensure this store occurs after others in the queue.
*word_addr = new_value;
- QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any loads.
+ QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any volatile loads.
} else {
*word_addr = new_value;
}
@@ -289,28 +276,31 @@ inline bool Object::CasField32(MemberOffset field_offset, uint32_t old_value, ui
return __sync_bool_compare_and_swap(addr, old_value, new_value);
}
-inline uint64_t Object::GetField64(MemberOffset field_offset, bool is_volatile) const {
+inline uint64_t Object::GetField64(MemberOffset field_offset, bool is_volatile) {
VerifyObject(this);
const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value();
const int64_t* addr = reinterpret_cast<const int64_t*>(raw_addr);
if (UNLIKELY(is_volatile)) {
uint64_t result = QuasiAtomic::Read64(addr);
- QuasiAtomic::MembarLoadLoad();
+ QuasiAtomic::MembarLoadLoad(); // Ensure volatile loads don't re-order.
return result;
} else {
return *addr;
}
}
-inline void Object::SetField64(MemberOffset field_offset, uint64_t new_value, bool is_volatile) {
- VerifyObject(this);
+inline void Object::SetField64(MemberOffset field_offset, uint64_t new_value, bool is_volatile,
+ bool this_is_valid) {
+ if (this_is_valid) {
+ VerifyObject(this);
+ }
byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
int64_t* addr = reinterpret_cast<int64_t*>(raw_addr);
if (UNLIKELY(is_volatile)) {
QuasiAtomic::MembarStoreStore(); // Ensure this store occurs after others in the queue.
QuasiAtomic::Write64(addr, new_value);
if (!QuasiAtomic::LongAtomicsUseMutexes()) {
- QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any loads.
+ QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any volatile loads.
} else {
// Fence from from mutex is enough.
}
@@ -319,12 +309,69 @@ inline void Object::SetField64(MemberOffset field_offset, uint64_t new_value, bo
}
}
-inline void Object::WriteBarrierField(const Object* dst, MemberOffset field_offset,
- const Object* new_value) {
- Runtime::Current()->GetHeap()->WriteBarrierField(dst, field_offset, new_value);
+inline bool Object::CasField64(MemberOffset field_offset, uint64_t old_value, uint64_t new_value) {
+ VerifyObject(this);
+ byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
+ volatile uint64_t* addr = reinterpret_cast<volatile uint64_t*>(raw_addr);
+ return __sync_bool_compare_and_swap(addr, old_value, new_value);
+}
+
+template<class T>
+inline T* Object::GetFieldObject(MemberOffset field_offset, bool is_volatile) {
+ VerifyObject(this);
+ byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
+ HeapReference<T>* objref_addr = reinterpret_cast<HeapReference<T>*>(raw_addr);
+ HeapReference<T> objref = *objref_addr;
+
+ if (UNLIKELY(is_volatile)) {
+ QuasiAtomic::MembarLoadLoad(); // Ensure loads don't re-order.
+ }
+ T* result = objref.AsMirrorPtr();
+ VerifyObject(result);
+ return result;
+}
+
+inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset, Object* new_value,
+ bool is_volatile, bool this_is_valid) {
+ if (this_is_valid) {
+ VerifyObject(this);
+ }
+ VerifyObject(new_value);
+ HeapReference<Object> objref(HeapReference<Object>::FromMirrorPtr(new_value));
+ byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
+ HeapReference<Object>* objref_addr = reinterpret_cast<HeapReference<Object>*>(raw_addr);
+ if (UNLIKELY(is_volatile)) {
+ QuasiAtomic::MembarStoreStore(); // Ensure this store occurs after others in the queue.
+ objref_addr->Assign(new_value);
+ QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any loads.
+ } else {
+ objref_addr->Assign(new_value);
+ }
+}
+
+inline void Object::SetFieldObject(MemberOffset field_offset, Object* new_value, bool is_volatile,
+ bool this_is_valid) {
+ SetFieldObjectWithoutWriteBarrier(field_offset, new_value, is_volatile, this_is_valid);
+ if (new_value != nullptr) {
+ CheckFieldAssignment(field_offset, new_value);
+ Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
+ }
+}
+
+inline bool Object::CasFieldObject(MemberOffset field_offset, Object* old_value, Object* new_value) {
+ VerifyObject(this);
+ byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
+ volatile uint32_t* addr = reinterpret_cast<volatile uint32_t*>(raw_addr);
+ HeapReference<Object> old_ref(HeapReference<Object>::FromMirrorPtr(old_value));
+ HeapReference<Object> new_ref(HeapReference<Object>::FromMirrorPtr(new_value));
+ bool success = __sync_bool_compare_and_swap(addr, old_ref.reference_, new_ref.reference_);
+ if (success) {
+ Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
+ }
+ return success;
}
-inline void Object::VerifyObject(const Object* obj) {
+inline void Object::VerifyObject(Object* obj) {
if (kIsDebugBuild) {
Runtime::Current()->GetHeap()->VerifyObject(obj);
}
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index bdb3250..1251852 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -52,7 +52,7 @@ static Object* CopyObject(Thread* self, mirror::Object* dest, mirror::Object* sr
Class* c = src->GetClass();
if (c->IsArrayClass()) {
if (!c->GetComponentType()->IsPrimitive()) {
- const ObjectArray<Object>* array = dest->AsObjectArray<Object>();
+ ObjectArray<Object>* array = dest->AsObjectArray<Object>();
heap->WriteBarrierArray(dest, 0, array->GetLength());
}
} else {
@@ -139,14 +139,15 @@ int32_t Object::IdentityHashCode() const {
return 0;
}
-void Object::CheckFieldAssignmentImpl(MemberOffset field_offset, const Object* new_value) {
- const Class* c = GetClass();
+void Object::CheckFieldAssignmentImpl(MemberOffset field_offset, Object* new_value) {
+ Class* c = GetClass();
if (Runtime::Current()->GetClassLinker() == NULL ||
+ !Runtime::Current()->IsStarted() ||
!Runtime::Current()->GetHeap()->IsObjectValidationEnabled() ||
!c->IsResolved()) {
return;
}
- for (const Class* cur = c; cur != NULL; cur = cur->GetSuperClass()) {
+ for (Class* cur = c; cur != NULL; cur = cur->GetSuperClass()) {
ObjectArray<ArtField>* fields = cur->GetIFields();
if (fields != NULL) {
size_t num_ref_ifields = cur->NumReferenceInstanceFields();
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 058aee7..6fe8b73 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -21,6 +21,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "cutils/atomic-inline.h"
+#include "object_reference.h"
#include "offsets.h"
namespace art {
@@ -51,17 +52,13 @@ typedef PrimitiveArray<int16_t> ShortArray;
class String;
class Throwable;
-// Classes shared with the managed side of the world need to be packed so that they don't have
-// extra platform specific padding.
-#define MANAGED PACKED(4)
-
// Fields within mirror objects aren't accessed directly so that the appropriate amount of
// handshaking is done with GC (for example, read and write barriers). This macro is used to
// compute an offset for the Set/Get methods defined in Object that can safely access fields.
#define OFFSET_OF_OBJECT_MEMBER(type, field) \
MemberOffset(OFFSETOF_MEMBER(type, field))
-const bool kCheckFieldAssignments = false;
+constexpr bool kCheckFieldAssignments = false;
// C++ mirror of java.lang.Object
class MANAGED Object {
@@ -70,19 +67,17 @@ class MANAGED Object {
return OFFSET_OF_OBJECT_MEMBER(Object, klass_);
}
- Class* GetClass() const;
+ Class* GetClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetClass(Class* new_klass);
+ void SetClass(Class* new_klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// The verifier treats all interfaces as java.lang.Object and relies on runtime checks in
// invoke-interface to detect incompatible interface types.
- bool VerifierInstanceOf(const Class* klass) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool VerifierInstanceOf(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool InstanceOf(const Class* klass) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool InstanceOf(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- size_t SizeOf() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ size_t SizeOf() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
Object* Clone(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -92,9 +87,9 @@ class MANAGED Object {
return OFFSET_OF_OBJECT_MEMBER(Object, monitor_);
}
- LockWord GetLockWord() const;
+ LockWord GetLockWord();
void SetLockWord(LockWord new_val);
- bool CasLockWord(LockWord old_val, LockWord new_val);
+ bool CasLockWord(LockWord old_val, LockWord new_val) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
uint32_t GetLockOwnerThreadId();
void MonitorEnter(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
@@ -111,111 +106,113 @@ class MANAGED Object {
void Wait(Thread* self, int64_t timeout, int32_t nanos) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsClass() const;
-
- Class* AsClass();
+ bool IsClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- const Class* AsClass() const;
+ Class* AsClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsObjectArray() const;
+ bool IsObjectArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
template<class T>
- ObjectArray<T>* AsObjectArray();
+ ObjectArray<T>* AsObjectArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- template<class T>
- const ObjectArray<T>* AsObjectArray() const;
+ bool IsArrayInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsArrayInstance() const;
+ Array* AsArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- Array* AsArray();
+ BooleanArray* AsBooleanArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ByteArray* AsByteArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ByteArray* AsByteSizedArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- const Array* AsArray() const;
+ CharArray* AsCharArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ShortArray* AsShortArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ShortArray* AsShortSizedArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- BooleanArray* AsBooleanArray();
- ByteArray* AsByteArray();
- CharArray* AsCharArray();
- ShortArray* AsShortArray();
- IntArray* AsIntArray();
- LongArray* AsLongArray();
+ IntArray* AsIntArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ LongArray* AsLongArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- String* AsString();
+ String* AsString() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
Throwable* AsThrowable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsArtMethod() const;
-
- ArtMethod* AsArtMethod();
+ bool IsArtMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- const ArtMethod* AsArtMethod() const;
+ ArtMethod* AsArtMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsArtField() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool IsArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
ArtField* AsArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- const ArtField* AsArtField() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- bool IsReferenceInstance() const;
+ bool IsReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsWeakReferenceInstance() const;
+ bool IsWeakReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsSoftReferenceInstance() const;
+ bool IsSoftReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsFinalizerReferenceInstance() const;
+ bool IsFinalizerReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsPhantomReferenceInstance() const;
+ bool IsPhantomReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- // Accessors for Java type fields
- template<class T>
- T GetFieldObject(MemberOffset field_offset, bool is_volatile) const {
- T result = reinterpret_cast<T>(GetField32(field_offset, is_volatile));
- VerifyObject(result);
- return result;
- }
-
- void SetFieldObject(MemberOffset field_offset, const Object* new_value, bool is_volatile,
- bool this_is_valid = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- VerifyObject(new_value);
- SetField32(field_offset, reinterpret_cast<uint32_t>(new_value), is_volatile, this_is_valid);
- if (new_value != NULL) {
- CheckFieldAssignment(field_offset, new_value);
- WriteBarrierField(this, field_offset, new_value);
- }
- }
+ // Accessor for Java type fields.
+ template<class T> T* GetFieldObject(MemberOffset field_offset, bool is_volatile)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset, Object* new_value,
+ bool is_volatile, bool this_is_valid = true)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetFieldObject(MemberOffset field_offset, Object* new_value, bool is_volatile,
+ bool this_is_valid = true)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool CasFieldObject(MemberOffset field_offset, Object* old_value, Object* new_value)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- Object** GetFieldObjectAddr(MemberOffset field_offset) ALWAYS_INLINE {
+ HeapReference<Object>* GetFieldObjectReferenceAddr(MemberOffset field_offset) ALWAYS_INLINE {
VerifyObject(this);
- return reinterpret_cast<Object**>(reinterpret_cast<byte*>(this) + field_offset.Int32Value());
+ return reinterpret_cast<HeapReference<Object>*>(reinterpret_cast<byte*>(this) +
+ field_offset.Int32Value());
}
- uint32_t GetField32(MemberOffset field_offset, bool is_volatile) const;
+ uint32_t GetField32(MemberOffset field_offset, bool is_volatile);
void SetField32(MemberOffset field_offset, uint32_t new_value, bool is_volatile,
bool this_is_valid = true);
- bool CasField32(MemberOffset field_offset, uint32_t old_value, uint32_t new_value);
+ bool CasField32(MemberOffset field_offset, uint32_t old_value, uint32_t new_value)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- uint64_t GetField64(MemberOffset field_offset, bool is_volatile) const;
+ uint64_t GetField64(MemberOffset field_offset, bool is_volatile);
- void SetField64(MemberOffset field_offset, uint64_t new_value, bool is_volatile);
+ void SetField64(MemberOffset field_offset, uint64_t new_value, bool is_volatile,
+ bool this_is_valid = true);
+
+ bool CasField64(MemberOffset field_offset, uint64_t old_value, uint64_t new_value)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
template<typename T>
- void SetFieldPtr(MemberOffset field_offset, T new_value, bool is_volatile, bool this_is_valid = true) {
+ void SetFieldPtr(MemberOffset field_offset, T new_value, bool is_volatile,
+ bool this_is_valid = true) {
+#ifndef __LP64__
SetField32(field_offset, reinterpret_cast<uint32_t>(new_value), is_volatile, this_is_valid);
+#else
+ SetField64(field_offset, reinterpret_cast<uint64_t>(new_value), is_volatile, this_is_valid);
+#endif
}
protected:
// Accessors for non-Java type fields
template<class T>
- T GetFieldPtr(MemberOffset field_offset, bool is_volatile) const {
+ T GetFieldPtr(MemberOffset field_offset, bool is_volatile) {
+#ifndef __LP64__
return reinterpret_cast<T>(GetField32(field_offset, is_volatile));
+#else
+ return reinterpret_cast<T>(GetField64(field_offset, is_volatile));
+#endif
}
private:
- static void VerifyObject(const Object* obj) ALWAYS_INLINE;
+ static void VerifyObject(Object* obj) ALWAYS_INLINE;
// Verify the type correctness of stores to fields.
- void CheckFieldAssignmentImpl(MemberOffset field_offset, const Object* new_value)
+ void CheckFieldAssignmentImpl(MemberOffset field_offset, Object* new_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void CheckFieldAssignment(MemberOffset field_offset, const Object* new_value)
+ void CheckFieldAssignment(MemberOffset field_offset, Object* new_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (kCheckFieldAssignments) {
CheckFieldAssignmentImpl(field_offset, new_value);
@@ -225,11 +222,9 @@ class MANAGED Object {
// Generate an identity hash code.
static int32_t GenerateIdentityHashCode();
- // Write barrier called post update to a reference bearing field.
- static void WriteBarrierField(const Object* dst, MemberOffset offset, const Object* new_value);
-
- Class* klass_;
-
+ // The Class representing the type of the object.
+ HeapReference<Class> klass_;
+ // Monitor and hash code information.
uint32_t monitor_;
friend class art::ImageWriter;
diff --git a/runtime/mirror/object_array-inl.h b/runtime/mirror/object_array-inl.h
index 6a50dfe..c342479 100644
--- a/runtime/mirror/object_array-inl.h
+++ b/runtime/mirror/object_array-inl.h
@@ -25,6 +25,7 @@
#include "runtime.h"
#include "sirt_ref.h"
#include "thread.h"
+#include <string>
namespace art {
namespace mirror {
@@ -32,8 +33,8 @@ namespace mirror {
template<class T>
inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self, Class* object_array_class,
int32_t length, gc::AllocatorType allocator_type) {
- Array* array = Array::Alloc<true>(self, object_array_class, length, sizeof(Object*),
- allocator_type);
+ Array* array = Array::Alloc<true>(self, object_array_class, length,
+ sizeof(HeapReference<Object>), allocator_type);
if (UNLIKELY(array == nullptr)) {
return nullptr;
} else {
@@ -49,12 +50,12 @@ inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self, Class* object_array_c
}
template<class T>
-inline T* ObjectArray<T>::Get(int32_t i) const {
+inline T* ObjectArray<T>::Get(int32_t i) {
if (UNLIKELY(!CheckIsValidIndex(i))) {
DCHECK(Thread::Current()->IsExceptionPending());
return NULL;
}
- return GetWithoutChecks(i);
+ return GetFieldObject<T>(OffsetOfElement(i), false);
}
template<class T>
@@ -72,7 +73,7 @@ inline bool ObjectArray<T>::CheckAssignable(T* object) {
template<class T>
inline void ObjectArray<T>::Set(int32_t i, T* object) {
if (LIKELY(CheckIsValidIndex(i) && CheckAssignable(object))) {
- SetWithoutChecks(i, object);
+ SetFieldObject(OffsetOfElement(i), object, false);
} else {
DCHECK(Thread::Current()->IsExceptionPending());
}
@@ -82,72 +83,123 @@ template<class T>
inline void ObjectArray<T>::SetWithoutChecks(int32_t i, T* object) {
DCHECK(CheckIsValidIndex(i));
DCHECK(CheckAssignable(object));
- MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*));
- SetFieldObject(data_offset, object, false);
+ SetFieldObject(OffsetOfElement(i), object, false);
}
template<class T>
-inline void ObjectArray<T>::SetPtrWithoutChecks(int32_t i, T* object) {
+inline void ObjectArray<T>::SetWithoutChecksAndWriteBarrier(int32_t i, T* object) {
DCHECK(CheckIsValidIndex(i));
- // TODO enable this check. It fails when writing the image in ImageWriter::FixupObjectArray.
+ // TODO: enable this check. It fails when writing the image in ImageWriter::FixupObjectArray.
// DCHECK(CheckAssignable(object));
- MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*));
- SetFieldPtr(data_offset, object, false);
+ SetFieldObjectWithoutWriteBarrier(OffsetOfElement(i), object, false);
}
template<class T>
-inline T* ObjectArray<T>::GetWithoutChecks(int32_t i) const {
+inline T* ObjectArray<T>::GetWithoutChecks(int32_t i) {
DCHECK(CheckIsValidIndex(i));
- MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*));
- return GetFieldObject<T*>(data_offset, false);
+ return GetFieldObject<T>(OffsetOfElement(i), false);
}
template<class T>
-inline void ObjectArray<T>::Copy(const ObjectArray<T>* src, int src_pos,
- ObjectArray<T>* dst, int dst_pos,
- size_t length) {
- if (src->CheckIsValidIndex(src_pos) &&
- src->CheckIsValidIndex(src_pos + length - 1) &&
- dst->CheckIsValidIndex(dst_pos) &&
- dst->CheckIsValidIndex(dst_pos + length - 1)) {
- MemberOffset src_offset(DataOffset(sizeof(Object*)).Int32Value() + src_pos * sizeof(Object*));
- MemberOffset dst_offset(DataOffset(sizeof(Object*)).Int32Value() + dst_pos * sizeof(Object*));
- Class* array_class = dst->GetClass();
- gc::Heap* heap = Runtime::Current()->GetHeap();
- if (array_class == src->GetClass()) {
- // No need for array store checks if arrays are of the same type
- for (size_t i = 0; i < length; i++) {
- Object* object = src->GetFieldObject<Object*>(src_offset, false);
- heap->VerifyObject(object);
- // directly set field, we do a bulk write barrier at the end
- dst->SetField32(dst_offset, reinterpret_cast<uint32_t>(object), false, true);
- src_offset = MemberOffset(src_offset.Uint32Value() + sizeof(Object*));
- dst_offset = MemberOffset(dst_offset.Uint32Value() + sizeof(Object*));
- }
+inline void ObjectArray<T>::AssignableMemmove(int32_t dst_pos, ObjectArray<T>* src,
+ int32_t src_pos, int32_t count) {
+ if (kIsDebugBuild) {
+ for (int i = 0; i < count; ++i) {
+ // The Get will perform the VerifyObject.
+ src->GetWithoutChecks(src_pos + i);
+ }
+ }
+ // Perform the memmove using int memmove then perform the write barrier.
+ CHECK_EQ(sizeof(HeapReference<T>), sizeof(uint32_t));
+ IntArray* dstAsIntArray = reinterpret_cast<IntArray*>(this);
+ IntArray* srcAsIntArray = reinterpret_cast<IntArray*>(src);
+ dstAsIntArray->Memmove(dst_pos, srcAsIntArray, src_pos, count);
+ Runtime::Current()->GetHeap()->WriteBarrierArray(this, dst_pos, count);
+ if (kIsDebugBuild) {
+ for (int i = 0; i < count; ++i) {
+ // The Get will perform the VerifyObject.
+ GetWithoutChecks(dst_pos + i);
+ }
+ }
+}
+
+template<class T>
+inline void ObjectArray<T>::AssignableMemcpy(int32_t dst_pos, ObjectArray<T>* src,
+ int32_t src_pos, int32_t count) {
+ if (kIsDebugBuild) {
+ for (int i = 0; i < count; ++i) {
+ // The Get will perform the VerifyObject.
+ src->GetWithoutChecks(src_pos + i);
+ }
+ }
+ // Perform the memmove using int memcpy then perform the write barrier.
+ CHECK_EQ(sizeof(HeapReference<T>), sizeof(uint32_t));
+ IntArray* dstAsIntArray = reinterpret_cast<IntArray*>(this);
+ IntArray* srcAsIntArray = reinterpret_cast<IntArray*>(src);
+ dstAsIntArray->Memcpy(dst_pos, srcAsIntArray, src_pos, count);
+ Runtime::Current()->GetHeap()->WriteBarrierArray(this, dst_pos, count);
+ if (kIsDebugBuild) {
+ for (int i = 0; i < count; ++i) {
+ // The Get will perform the VerifyObject.
+ GetWithoutChecks(dst_pos + i);
+ }
+ }
+}
+
+template<class T>
+inline void ObjectArray<T>::AssignableCheckingMemcpy(int32_t dst_pos, ObjectArray<T>* src,
+ int32_t src_pos, int32_t count,
+ bool throw_exception) {
+ DCHECK_NE(this, src)
+ << "This case should be handled with memmove that handles overlaps correctly";
+ // We want to avoid redundant IsAssignableFrom checks where possible, so we cache a class that
+ // we know is assignable to the destination array's component type.
+ Class* dst_class = GetClass()->GetComponentType();
+ Class* lastAssignableElementClass = dst_class;
+
+ Object* o = nullptr;
+ int i = 0;
+ for (; i < count; ++i) {
+ // The follow get operations force the objects to be verified.
+ o = src->GetWithoutChecks(src_pos + i);
+ if (o == nullptr) {
+ // Null is always assignable.
+ SetWithoutChecks(dst_pos + i, nullptr);
} else {
- Class* element_class = array_class->GetComponentType();
- CHECK(!element_class->IsPrimitive());
- for (size_t i = 0; i < length; i++) {
- Object* object = src->GetFieldObject<Object*>(src_offset, false);
- if (object != NULL && !object->InstanceOf(element_class)) {
- dst->ThrowArrayStoreException(object);
- return;
- }
- heap->VerifyObject(object);
- // directly set field, we do a bulk write barrier at the end
- dst->SetField32(dst_offset, reinterpret_cast<uint32_t>(object), false, true);
- src_offset = MemberOffset(src_offset.Uint32Value() + sizeof(Object*));
- dst_offset = MemberOffset(dst_offset.Uint32Value() + sizeof(Object*));
+ // TODO: use the underlying class reference to avoid uncompression when not necessary.
+ Class* o_class = o->GetClass();
+ if (LIKELY(lastAssignableElementClass == o_class)) {
+ SetWithoutChecks(dst_pos + i, o);
+ } else if (LIKELY(dst_class->IsAssignableFrom(o_class))) {
+ lastAssignableElementClass = o_class;
+ SetWithoutChecks(dst_pos + i, o);
+ } else {
+ // Can't put this element into the array, break to perform write-barrier and throw
+ // exception.
+ break;
}
}
- heap->WriteBarrierArray(dst, dst_pos, length);
- } else {
- DCHECK(Thread::Current()->IsExceptionPending());
+ }
+ Runtime::Current()->GetHeap()->WriteBarrierArray(this, dst_pos, count);
+ if (UNLIKELY(i != count)) {
+ std::string actualSrcType(PrettyTypeOf(o));
+ std::string dstType(PrettyTypeOf(this));
+ Thread* self = Thread::Current();
+ ThrowLocation throw_location = self->GetCurrentLocationForThrow();
+ if (throw_exception) {
+ self->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayStoreException;",
+ "source[%d] of type %s cannot be stored in destination array of type %s",
+ src_pos + i, actualSrcType.c_str(), dstType.c_str());
+ } else {
+ LOG(FATAL) << StringPrintf("source[%d] of type %s cannot be stored in destination array of type %s",
+ src_pos + i, actualSrcType.c_str(), dstType.c_str());
+ }
}
}
template<class T>
inline ObjectArray<T>* ObjectArray<T>::CopyOf(Thread* self, int32_t new_length) {
+ DCHECK_GE(new_length, 0);
// We may get copied by a compacting GC.
SirtRef<ObjectArray<T> > sirt_this(self, this);
gc::Heap* heap = Runtime::Current()->GetHeap();
@@ -155,11 +207,17 @@ inline ObjectArray<T>* ObjectArray<T>::CopyOf(Thread* self, int32_t new_length)
heap->GetCurrentNonMovingAllocator();
ObjectArray<T>* new_array = Alloc(self, GetClass(), new_length, allocator_type);
if (LIKELY(new_array != nullptr)) {
- Copy(sirt_this.get(), 0, new_array, 0, std::min(sirt_this->GetLength(), new_length));
+ new_array->AssignableMemcpy(0, sirt_this.get(), 0, std::min(sirt_this->GetLength(), new_length));
}
return new_array;
}
+template<class T>
+inline MemberOffset ObjectArray<T>::OffsetOfElement(int32_t i) {
+ return MemberOffset(DataOffset(sizeof(HeapReference<Object>)).Int32Value() +
+ (i * sizeof(HeapReference<Object>)));
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/object_array.h b/runtime/mirror/object_array.h
index 5da8845..347494e 100644
--- a/runtime/mirror/object_array.h
+++ b/runtime/mirror/object_array.h
@@ -33,7 +33,7 @@ class MANAGED ObjectArray : public Array {
static ObjectArray<T>* Alloc(Thread* self, Class* object_array_class, int32_t length)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- T* Get(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ T* Get(int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Returns true if the object can be stored into the array. If not, throws
// an ArrayStoreException and returns false.
@@ -44,22 +44,30 @@ class MANAGED ObjectArray : public Array {
// Set element without bound and element type checks, to be used in limited
// circumstances, such as during boot image writing
void SetWithoutChecks(int32_t i, T* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetWithoutChecksAndWriteBarrier(int32_t i, T* object)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ T* GetWithoutChecks(int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- // Set element without bound and element type checks, to be used in limited circumstances, such
- // as during boot image writing. Does not do write barrier.
- void SetPtrWithoutChecks(int32_t i, T* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ // Copy src into this array (dealing with overlaps as memmove does) without assignability checks.
+ void AssignableMemmove(int32_t dst_pos, ObjectArray<T>* src, int32_t src_pos,
+ int32_t count) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- T* GetWithoutChecks(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ // Copy src into this array assuming no overlap and without assignability checks.
+ void AssignableMemcpy(int32_t dst_pos, ObjectArray<T>* src, int32_t src_pos,
+ int32_t count) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- static void Copy(const ObjectArray<T>* src, int src_pos,
- ObjectArray<T>* dst, int dst_pos,
- size_t length)
+ // Copy src into this array with assignability checks.
+ void AssignableCheckingMemcpy(int32_t dst_pos, ObjectArray<T>* src, int32_t src_pos,
+ int32_t count, bool throw_exception)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
ObjectArray<T>* CopyOf(Thread* self, int32_t new_length)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
private:
+ static MemberOffset OffsetOfElement(int32_t i);
+
DISALLOW_IMPLICIT_CONSTRUCTORS(ObjectArray);
};
diff --git a/runtime/mirror/object_reference.h b/runtime/mirror/object_reference.h
new file mode 100644
index 0000000..b30890f
--- /dev/null
+++ b/runtime/mirror/object_reference.h
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_RUNTIME_MIRROR_OBJECT_REFERENCE_H_
+#define ART_RUNTIME_MIRROR_OBJECT_REFERENCE_H_
+
+#include "locks.h"
+
+namespace art {
+namespace mirror {
+
+class Object;
+
+// Classes shared with the managed side of the world need to be packed so that they don't have
+// extra platform specific padding.
+#define MANAGED PACKED(4)
+
+// Value type representing a reference to a mirror::Object of type MirrorType.
+template<bool kPoisonReferences, class MirrorType>
+class MANAGED ObjectReference {
+ public:
+ MirrorType* AsMirrorPtr() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return UnCompress();
+ }
+
+ void Assign(MirrorType* other) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ reference_ = Compress(other);
+ }
+
+ void Clear() {
+ reference_ = 0;
+ }
+
+ uint32_t AsVRegValue() const {
+ return reference_;
+ }
+
+ protected:
+ ObjectReference<kPoisonReferences, MirrorType>(MirrorType* mirror_ptr)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : reference_(Compress(mirror_ptr)) {
+ }
+
+ // Compress reference to its bit representation.
+ static uint32_t Compress(MirrorType* mirror_ptr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ uintptr_t as_bits = reinterpret_cast<uintptr_t>(mirror_ptr);
+ return static_cast<uint32_t>(kPoisonReferences ? -as_bits : as_bits);
+ }
+
+ // Uncompress an encoded reference from its bit representation.
+ MirrorType* UnCompress() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ uintptr_t as_bits = kPoisonReferences ? -reference_ : reference_;
+ return reinterpret_cast<MirrorType*>(as_bits);
+ }
+
+ friend class Object;
+
+ // The encoded reference to a mirror::Object.
+ uint32_t reference_;
+};
+
+// References between objects within the managed heap.
+template<class MirrorType>
+class MANAGED HeapReference : public ObjectReference<false, MirrorType> {
+ public:
+ static HeapReference<MirrorType> FromMirrorPtr(MirrorType* mirror_ptr)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return HeapReference<MirrorType>(mirror_ptr);
+ }
+ private:
+ HeapReference<MirrorType>(MirrorType* mirror_ptr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : ObjectReference<false, MirrorType>(mirror_ptr) {}
+};
+
+} // namespace mirror
+} // namespace art
+
+#endif // ART_RUNTIME_MIRROR_OBJECT_REFERENCE_H_
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index 3637181..2af32da 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -77,7 +77,7 @@ TEST_F(ObjectTest, AsmConstants) {
EXPECT_EQ(CLASS_COMPONENT_TYPE_OFFSET, Class::ComponentTypeOffset().Int32Value());
EXPECT_EQ(ARRAY_LENGTH_OFFSET, Array::LengthOffset().Int32Value());
- EXPECT_EQ(OBJECT_ARRAY_DATA_OFFSET, Array::DataOffset(sizeof(Object*)).Int32Value());
+ EXPECT_EQ(OBJECT_ARRAY_DATA_OFFSET, Array::DataOffset(sizeof(HeapReference<Object>)).Int32Value());
EXPECT_EQ(STRING_VALUE_OFFSET, String::ValueOffset().Int32Value());
EXPECT_EQ(STRING_COUNT_OFFSET, String::CountOffset().Int32Value());
@@ -85,7 +85,8 @@ TEST_F(ObjectTest, AsmConstants) {
EXPECT_EQ(STRING_DATA_OFFSET, Array::DataOffset(sizeof(uint16_t)).Int32Value());
EXPECT_EQ(METHOD_DEX_CACHE_METHODS_OFFSET, ArtMethod::DexCacheResolvedMethodsOffset().Int32Value());
- EXPECT_EQ(METHOD_CODE_OFFSET, ArtMethod::EntryPointFromCompiledCodeOffset().Int32Value());
+ EXPECT_EQ(METHOD_PORTABLE_CODE_OFFSET, ArtMethod::EntryPointFromPortableCompiledCodeOffset().Int32Value());
+ EXPECT_EQ(METHOD_QUICK_CODE_OFFSET, ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value());
}
TEST_F(ObjectTest, IsInSamePackage) {
@@ -295,7 +296,7 @@ TEST_F(ObjectTest, StaticFieldFromCode) {
uint32_t field_idx = dex_file->GetIndexForFieldId(*field_id);
ArtField* field = FindFieldFromCode<StaticObjectRead, true>(field_idx, clinit, Thread::Current(),
- sizeof(Object*));
+ sizeof(HeapReference<Object>));
Object* s0 = field->GetObj(klass);
EXPECT_TRUE(s0 != NULL);
diff --git a/runtime/mirror/proxy.h b/runtime/mirror/proxy.h
index 18a84dc..ff019c6 100644
--- a/runtime/mirror/proxy.h
+++ b/runtime/mirror/proxy.h
@@ -29,24 +29,28 @@ namespace mirror {
// has the static fields used to implement reflection on proxy objects.
class MANAGED SynthesizedProxyClass : public Class {
public:
- ObjectArray<Class>* GetInterfaces() {
- return interfaces_;
+ ObjectArray<Class>* GetInterfaces() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject<ObjectArray<Class> >(OFFSET_OF_OBJECT_MEMBER(SynthesizedProxyClass,
+ interfaces_),
+ false);
}
- ObjectArray<ObjectArray<Class> >* GetThrows() {
- return throws_;
+ ObjectArray<ObjectArray<Class> >* GetThrows() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject<ObjectArray<ObjectArray<Class> > >(OFFSET_OF_OBJECT_MEMBER(SynthesizedProxyClass,
+ throws_),
+ false);
}
private:
- ObjectArray<Class>* interfaces_;
- ObjectArray<ObjectArray<Class> >* throws_;
+ HeapReference<ObjectArray<Class> > interfaces_;
+ HeapReference<ObjectArray<ObjectArray<Class> > > throws_;
DISALLOW_IMPLICIT_CONSTRUCTORS(SynthesizedProxyClass);
};
// C++ mirror of java.lang.reflect.Proxy.
class MANAGED Proxy : public Object {
private:
- Object* h_;
+ HeapReference<Object> h_;
friend struct art::ProxyOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(Proxy);
diff --git a/runtime/mirror/stack_trace_element.h b/runtime/mirror/stack_trace_element.h
index d1be4dc..73d2673 100644
--- a/runtime/mirror/stack_trace_element.h
+++ b/runtime/mirror/stack_trace_element.h
@@ -29,24 +29,23 @@ namespace mirror {
// C++ mirror of java.lang.StackTraceElement
class MANAGED StackTraceElement : public Object {
public:
- const String* GetDeclaringClass() const {
- return GetFieldObject<const String*>(
- OFFSET_OF_OBJECT_MEMBER(StackTraceElement, declaring_class_), false);
+ String* GetDeclaringClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject<String>(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, declaring_class_),
+ false);
}
- const String* GetMethodName() const {
- return GetFieldObject<const String*>(
- OFFSET_OF_OBJECT_MEMBER(StackTraceElement, method_name_), false);
+ String* GetMethodName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject<String>(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, method_name_),
+ false);
}
- const String* GetFileName() const {
- return GetFieldObject<const String*>(
- OFFSET_OF_OBJECT_MEMBER(StackTraceElement, file_name_), false);
+ String* GetFileName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject<String>(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, file_name_),
+ false);
}
- int32_t GetLineNumber() const {
- return GetField32(
- OFFSET_OF_OBJECT_MEMBER(StackTraceElement, line_number_), false);
+ int32_t GetLineNumber() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, line_number_), false);
}
static StackTraceElement* Alloc(Thread* self,
@@ -63,9 +62,9 @@ class MANAGED StackTraceElement : public Object {
private:
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
- String* declaring_class_;
- String* file_name_;
- String* method_name_;
+ HeapReference<String> declaring_class_;
+ HeapReference<String> file_name_;
+ HeapReference<String> method_name_;
int32_t line_number_;
static Class* GetStackTraceElement() {
diff --git a/runtime/mirror/string.cc b/runtime/mirror/string.cc
index 1f756a1..10ae066 100644
--- a/runtime/mirror/string.cc
+++ b/runtime/mirror/string.cc
@@ -29,23 +29,19 @@
namespace art {
namespace mirror {
-const CharArray* String::GetCharArray() const {
- return GetFieldObject<const CharArray*>(ValueOffset(), false);
-}
-
CharArray* String::GetCharArray() {
- return GetFieldObject<CharArray*>(ValueOffset(), false);
+ return GetFieldObject<CharArray>(ValueOffset(), false);
}
void String::ComputeHashCode() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
SetHashCode(ComputeUtf16Hash(GetCharArray(), GetOffset(), GetLength()));
}
-int32_t String::GetUtfLength() const {
+int32_t String::GetUtfLength() {
return CountUtf8Bytes(GetCharArray()->GetData() + GetOffset(), GetLength());
}
-int32_t String::FastIndexOf(int32_t ch, int32_t start) const {
+int32_t String::FastIndexOf(int32_t ch, int32_t start) {
int32_t count = GetLength();
if (start < 0) {
start = 0;
@@ -97,13 +93,13 @@ int32_t String::GetHashCode() {
return result;
}
-int32_t String::GetLength() const {
+int32_t String::GetLength() {
int32_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(String, count_), false);
DCHECK(result >= 0 && result <= GetCharArray()->GetLength());
return result;
}
-uint16_t String::CharAt(int32_t index) const {
+uint16_t String::CharAt(int32_t index) {
// TODO: do we need this? Equals is the only caller, and could
// bounds check itself.
DCHECK_GE(count_, 0); // ensures the unsigned comparison is safe.
@@ -179,7 +175,7 @@ String* String::Alloc(Thread* self, const SirtRef<CharArray>& array) {
return string;
}
-bool String::Equals(const String* that) const {
+bool String::Equals(String* that) {
if (this == that) {
// Quick reference equality test
return true;
@@ -201,7 +197,7 @@ bool String::Equals(const String* that) const {
}
}
-bool String::Equals(const uint16_t* that_chars, int32_t that_offset, int32_t that_length) const {
+bool String::Equals(const uint16_t* that_chars, int32_t that_offset, int32_t that_length) {
if (this->GetLength() != that_length) {
return false;
} else {
@@ -214,7 +210,7 @@ bool String::Equals(const uint16_t* that_chars, int32_t that_offset, int32_t tha
}
}
-bool String::Equals(const char* modified_utf8) const {
+bool String::Equals(const char* modified_utf8) {
for (int32_t i = 0; i < GetLength(); ++i) {
uint16_t ch = GetUtf16FromUtf8(&modified_utf8);
if (ch == '\0' || ch != CharAt(i)) {
@@ -224,7 +220,7 @@ bool String::Equals(const char* modified_utf8) const {
return *modified_utf8 == '\0';
}
-bool String::Equals(const StringPiece& modified_utf8) const {
+bool String::Equals(const StringPiece& modified_utf8) {
const char* p = modified_utf8.data();
for (int32_t i = 0; i < GetLength(); ++i) {
uint16_t ch = GetUtf16FromUtf8(&p);
@@ -236,7 +232,7 @@ bool String::Equals(const StringPiece& modified_utf8) const {
}
// Create a modified UTF-8 encoded std::string from a java/lang/String object.
-std::string String::ToModifiedUtf8() const {
+std::string String::ToModifiedUtf8() {
const uint16_t* chars = GetCharArray()->GetData() + GetOffset();
size_t byte_count = GetUtfLength();
std::string result(byte_count, static_cast<char>(0));
@@ -259,9 +255,9 @@ static uint32_t MemCmp16(const uint16_t* s0, const uint16_t* s1, size_t count) {
}
#endif
-int32_t String::CompareTo(String* rhs) const {
+int32_t String::CompareTo(String* rhs) {
// Quick test for comparison of a string with itself.
- const String* lhs = this;
+ String* lhs = this;
if (lhs == rhs) {
return 0;
}
diff --git a/runtime/mirror/string.h b/runtime/mirror/string.h
index 4bbcb9c..a82b26c 100644
--- a/runtime/mirror/string.h
+++ b/runtime/mirror/string.h
@@ -44,24 +44,23 @@ class MANAGED String : public Object {
return OFFSET_OF_OBJECT_MEMBER(String, offset_);
}
- const CharArray* GetCharArray() const;
- CharArray* GetCharArray();
+ CharArray* GetCharArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- int32_t GetOffset() const {
+ int32_t GetOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
int32_t result = GetField32(OffsetOffset(), false);
DCHECK_LE(0, result);
return result;
}
- int32_t GetLength() const;
+ int32_t GetLength() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
int32_t GetHashCode() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void ComputeHashCode() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- int32_t GetUtfLength() const;
+ int32_t GetUtfLength() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- uint16_t CharAt(int32_t index) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ uint16_t CharAt(int32_t index) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
String* Intern() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -78,29 +77,28 @@ class MANAGED String : public Object {
const char* utf8_data_in)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool Equals(const char* modified_utf8) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool Equals(const char* modified_utf8) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// TODO: do we need this overload? give it a more intention-revealing name.
- bool Equals(const StringPiece& modified_utf8) const
+ bool Equals(const StringPiece& modified_utf8)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool Equals(const String* that) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool Equals(String* that) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Compare UTF-16 code point values not in a locale-sensitive manner
int Compare(int32_t utf16_length, const char* utf8_data_in);
// TODO: do we need this overload? give it a more intention-revealing name.
bool Equals(const uint16_t* that_chars, int32_t that_offset,
- int32_t that_length) const
+ int32_t that_length)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Create a modified UTF-8 encoded std::string from a java/lang/String object.
- std::string ToModifiedUtf8() const;
+ std::string ToModifiedUtf8() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- int32_t FastIndexOf(int32_t ch, int32_t start) const;
+ int32_t FastIndexOf(int32_t ch, int32_t start) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- int32_t CompareTo(String* other) const;
+ int32_t CompareTo(String* other) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static Class* GetJavaLangString() {
DCHECK(java_lang_String_ != NULL);
@@ -123,7 +121,7 @@ class MANAGED String : public Object {
SetField32(OFFSET_OF_OBJECT_MEMBER(String, count_), new_count, false);
}
- void SetOffset(int32_t new_offset) {
+ void SetOffset(int32_t new_offset) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK_LE(0, new_offset);
DCHECK_GE(GetLength(), new_offset);
SetField32(OFFSET_OF_OBJECT_MEMBER(String, offset_), new_offset, false);
@@ -138,7 +136,7 @@ class MANAGED String : public Object {
void SetArray(CharArray* new_array) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
- CharArray* array_;
+ HeapReference<CharArray> array_;
int32_t count_;
@@ -155,8 +153,8 @@ class MANAGED String : public Object {
class MANAGED StringClass : public Class {
private:
- CharArray* ASCII_;
- Object* CASE_INSENSITIVE_ORDER_;
+ HeapReference<CharArray> ASCII_;
+ HeapReference<Object> CASE_INSENSITIVE_ORDER_;
uint32_t REPLACEMENT_CHAR_;
int64_t serialVersionUID_;
friend struct art::StringClassOffsets; // for verifying offset information
diff --git a/runtime/mirror/throwable.cc b/runtime/mirror/throwable.cc
index b55db72..2318b74 100644
--- a/runtime/mirror/throwable.cc
+++ b/runtime/mirror/throwable.cc
@@ -33,22 +33,22 @@ namespace mirror {
Class* Throwable::java_lang_Throwable_ = NULL;
void Throwable::SetCause(Throwable* cause) {
- CHECK(cause != NULL);
+ CHECK(cause != nullptr);
CHECK(cause != this);
- Throwable* current_cause = GetFieldObject<Throwable*>(OFFSET_OF_OBJECT_MEMBER(Throwable, cause_),
- false);
+ Throwable* current_cause = GetFieldObject<Throwable>(OFFSET_OF_OBJECT_MEMBER(Throwable, cause_),
+ false);
CHECK(current_cause == NULL || current_cause == this);
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Throwable, cause_), cause, false);
}
-bool Throwable::IsCheckedException() const {
+bool Throwable::IsCheckedException() {
if (InstanceOf(WellKnownClasses::ToClass(WellKnownClasses::java_lang_Error))) {
return false;
}
return !InstanceOf(WellKnownClasses::ToClass(WellKnownClasses::java_lang_RuntimeException));
}
-std::string Throwable::Dump() const {
+std::string Throwable::Dump() {
std::string result(PrettyTypeOf(this));
result += ": ";
String* msg = GetDetailMessage();
@@ -74,7 +74,7 @@ std::string Throwable::Dump() const {
source_file, line_number);
}
}
- Throwable* cause = GetFieldObject<Throwable*>(OFFSET_OF_OBJECT_MEMBER(Throwable, cause_), false);
+ Throwable* cause = GetFieldObject<Throwable>(OFFSET_OF_OBJECT_MEMBER(Throwable, cause_), false);
if (cause != NULL && cause != this) { // Constructor makes cause == this by default.
result += "Caused by: ";
result += cause->Dump();
diff --git a/runtime/mirror/throwable.h b/runtime/mirror/throwable.h
index 5a90599..bc9848a 100644
--- a/runtime/mirror/throwable.h
+++ b/runtime/mirror/throwable.h
@@ -33,16 +33,16 @@ class MANAGED Throwable : public Object {
void SetDetailMessage(String* new_detail_message) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Throwable, detail_message_), new_detail_message, false);
}
- String* GetDetailMessage() const {
- return GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Throwable, detail_message_), false);
+ String* GetDetailMessage() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject<String>(OFFSET_OF_OBJECT_MEMBER(Throwable, detail_message_), false);
}
- std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ std::string Dump() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// This is a runtime version of initCause, you shouldn't use it if initCause may have been
// overridden. Also it asserts rather than throwing exceptions. Currently this is only used
// in cases like the verifier where the checks cannot fail and initCause isn't overridden.
void SetCause(Throwable* cause) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsCheckedException() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool IsCheckedException() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static Class* GetJavaLangThrowable() {
DCHECK(java_lang_Throwable_ != NULL);
@@ -55,16 +55,16 @@ class MANAGED Throwable : public Object {
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
private:
- Object* GetStackState() const {
- return GetFieldObject<Object*>(OFFSET_OF_OBJECT_MEMBER(Throwable, stack_state_), true);
+ Object* GetStackState() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject<Object>(OFFSET_OF_OBJECT_MEMBER(Throwable, stack_state_), true);
}
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
- Throwable* cause_;
- String* detail_message_;
- Object* stack_state_; // Note this is Java volatile:
- Object* stack_trace_;
- Object* suppressed_exceptions_;
+ HeapReference<Throwable> cause_;
+ HeapReference<String> detail_message_;
+ HeapReference<Object> stack_state_; // Note this is Java volatile:
+ HeapReference<Object> stack_trace_;
+ HeapReference<Object> suppressed_exceptions_;
static Class* java_lang_Throwable_;
diff --git a/runtime/modifiers.h b/runtime/modifiers.h
index 4e365be..0addd51 100644
--- a/runtime/modifiers.h
+++ b/runtime/modifiers.h
@@ -47,6 +47,7 @@ static const uint32_t kAccDeclaredSynchronized = 0x00020000; // method (dex onl
static const uint32_t kAccClassIsProxy = 0x00040000; // class (dex only)
static const uint32_t kAccPreverified = 0x00080000; // method (dex only)
static const uint32_t kAccFastNative = 0x0080000; // method (dex only)
+static const uint32_t kAccPortableCompiled = 0x0100000; // method (dex only)
// Special runtime-only flags.
// Note: if only kAccClassIsReference is set, we have a soft reference.
diff --git a/runtime/monitor.cc b/runtime/monitor.cc
index 4186693..72220e0 100644
--- a/runtime/monitor.cc
+++ b/runtime/monitor.cc
@@ -79,7 +79,7 @@ void Monitor::Init(uint32_t lock_profiling_threshold, bool (*is_sensitive_thread
is_sensitive_thread_hook_ = is_sensitive_thread_hook;
}
-Monitor::Monitor(Thread* owner, mirror::Object* obj, int32_t hash_code)
+Monitor::Monitor(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_code)
: monitor_lock_("a monitor lock", kMonitorLock),
monitor_contenders_("monitor contenders", monitor_lock_),
num_waiters_(0),
@@ -89,10 +89,11 @@ Monitor::Monitor(Thread* owner, mirror::Object* obj, int32_t hash_code)
wait_set_(NULL),
hash_code_(hash_code),
locking_method_(NULL),
- locking_dex_pc_(0) {
+ locking_dex_pc_(0),
+ monitor_id_(MonitorPool::CreateMonitorId(self, this)) {
// We should only inflate a lock if the owner is ourselves or suspended. This avoids a race
// with the owner unlocking the thin-lock.
- CHECK(owner == nullptr || owner == Thread::Current() || owner->IsSuspended());
+ CHECK(owner == nullptr || owner == self || owner->IsSuspended());
// The identity hash code is set for the life time of the monitor.
}
@@ -145,6 +146,7 @@ bool Monitor::Install(Thread* self) {
}
Monitor::~Monitor() {
+ MonitorPool::ReleaseMonitorId(monitor_id_);
// Deflated monitors have a null object.
}
@@ -219,7 +221,7 @@ void Monitor::Lock(Thread* self) {
// Contended.
const bool log_contention = (lock_profiling_threshold_ != 0);
uint64_t wait_start_ms = log_contention ? 0 : MilliTime();
- const mirror::ArtMethod* owners_method = locking_method_;
+ mirror::ArtMethod* owners_method = locking_method_;
uint32_t owners_dex_pc = locking_dex_pc_;
monitor_lock_.Unlock(self); // Let go of locks in order.
{
@@ -411,7 +413,7 @@ void Monitor::Wait(Thread* self, int64_t ms, int32_t ns,
if (ms < 0 || ns < 0 || ns > 999999) {
ThrowLocation throw_location = self->GetCurrentLocationForThrow();
self->ThrowNewExceptionF(throw_location, "Ljava/lang/IllegalArgumentException;",
- "timeout arguments out of range: ms=%lld ns=%d", ms, ns);
+ "timeout arguments out of range: ms=%" PRId64 " ns=%d", ms, ns);
monitor_lock_.Unlock(self);
return;
}
@@ -430,7 +432,7 @@ void Monitor::Wait(Thread* self, int64_t ms, int32_t ns,
int prev_lock_count = lock_count_;
lock_count_ = 0;
owner_ = NULL;
- const mirror::ArtMethod* saved_method = locking_method_;
+ mirror::ArtMethod* saved_method = locking_method_;
locking_method_ = NULL;
uintptr_t saved_dex_pc = locking_dex_pc_;
locking_dex_pc_ = 0;
@@ -611,7 +613,7 @@ void Monitor::Inflate(Thread* self, Thread* owner, mirror::Object* obj, int32_t
DCHECK(self != NULL);
DCHECK(obj != NULL);
// Allocate and acquire a new monitor.
- UniquePtr<Monitor> m(new Monitor(owner, obj, hash_code));
+ UniquePtr<Monitor> m(new Monitor(self, owner, obj, hash_code));
if (m->Install(self)) {
VLOG(monitor) << "monitor: thread " << owner->GetThreadId()
<< " created monitor " << m.get() << " for object " << obj;
@@ -1008,7 +1010,7 @@ bool Monitor::IsLocked() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return owner_ != nullptr;
}
-void Monitor::TranslateLocation(const mirror::ArtMethod* method, uint32_t dex_pc,
+void Monitor::TranslateLocation(mirror::ArtMethod* method, uint32_t dex_pc,
const char** source_file, uint32_t* line_number) const {
// If method is null, location is unknown
if (method == NULL) {
diff --git a/runtime/monitor.h b/runtime/monitor.h
index 16e9410..85a8c48 100644
--- a/runtime/monitor.h
+++ b/runtime/monitor.h
@@ -24,7 +24,7 @@
#include <list>
#include <vector>
-#include "atomic_integer.h"
+#include "atomic.h"
#include "base/mutex.h"
#include "root_visitor.h"
#include "sirt_ref.h"
@@ -40,6 +40,8 @@ class LockWord;
class Thread;
class StackVisitor;
+typedef uint32_t MonitorId;
+
class Monitor {
public:
// The default number of spins that are done before thread suspension is used to forcibly inflate
@@ -108,6 +110,10 @@ class Monitor {
return hash_code_.Load() != 0;
}
+ MonitorId GetMonitorId() const {
+ return monitor_id_;
+ }
+
static void InflateThinLocked(Thread* self, SirtRef<mirror::Object>& obj, LockWord lock_word,
uint32_t hash_code) NO_THREAD_SAFETY_ANALYSIS;
@@ -115,7 +121,7 @@ class Monitor {
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
private:
- explicit Monitor(Thread* owner, mirror::Object* obj, int32_t hash_code)
+ explicit Monitor(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_code)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Install the monitor into its object, may fail if another thread installs a different monitor
@@ -162,7 +168,7 @@ class Monitor {
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Translates the provided method and pc into its declaring class' source file and line number.
- void TranslateLocation(const mirror::ArtMethod* method, uint32_t pc,
+ void TranslateLocation(mirror::ArtMethod* method, uint32_t pc,
const char** source_file, uint32_t* line_number) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -195,9 +201,12 @@ class Monitor {
// Method and dex pc where the lock owner acquired the lock, used when lock
// sampling is enabled. locking_method_ may be null if the lock is currently
// unlocked, or if the lock is acquired by the system when the stack is empty.
- const mirror::ArtMethod* locking_method_ GUARDED_BY(monitor_lock_);
+ mirror::ArtMethod* locking_method_ GUARDED_BY(monitor_lock_);
uint32_t locking_dex_pc_ GUARDED_BY(monitor_lock_);
+ // The denser encoded version of this monitor as stored in the lock word.
+ MonitorId monitor_id_;
+
friend class MonitorInfo;
friend class MonitorList;
friend class mirror::Object;
diff --git a/runtime/monitor_pool.cc b/runtime/monitor_pool.cc
new file mode 100644
index 0000000..eadd7a6
--- /dev/null
+++ b/runtime/monitor_pool.cc
@@ -0,0 +1,56 @@
+/*
+ * 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 "monitor_pool.h"
+
+#include "base/logging.h"
+#include "base/mutex-inl.h"
+#include "monitor.h"
+
+namespace art {
+
+MonitorPool::MonitorPool() : allocated_ids_lock_("allocated monitor ids lock") {
+}
+
+Monitor* MonitorPool::LookupMonitorFromTable(MonitorId mon_id) {
+ ReaderMutexLock mu(Thread::Current(), allocated_ids_lock_);
+ return table_.Get(mon_id);
+}
+
+MonitorId MonitorPool::AllocMonitorIdFromTable(Thread* self, Monitor* mon) {
+ WriterMutexLock mu(self, allocated_ids_lock_);
+ for (size_t i = 0; i < allocated_ids_.size(); ++i) {
+ if (!allocated_ids_[i]) {
+ allocated_ids_.set(i);
+ MonitorId mon_id = i + 1; // Zero is reserved to mean "invalid".
+ table_.Put(mon_id, mon);
+ return mon_id;
+ }
+ }
+ LOG(FATAL) << "Out of internal monitor ids";
+ return 0;
+}
+
+void MonitorPool::ReleaseMonitorIdFromTable(MonitorId mon_id) {
+ WriterMutexLock mu(Thread::Current(), allocated_ids_lock_);
+ DCHECK(table_.Get(mon_id) != nullptr);
+ table_.erase(mon_id);
+ --mon_id; // Zero is reserved to mean "invalid".
+ DCHECK(allocated_ids_[mon_id]) << mon_id;
+ allocated_ids_.reset(mon_id);
+}
+
+} // namespace art
diff --git a/runtime/monitor_pool.h b/runtime/monitor_pool.h
new file mode 100644
index 0000000..32f3f4e
--- /dev/null
+++ b/runtime/monitor_pool.h
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_RUNTIME_MONITOR_POOL_H_
+#define ART_RUNTIME_MONITOR_POOL_H_
+
+#include "monitor.h"
+
+#include "safe_map.h"
+
+#include <stdint.h>
+
+namespace art {
+
+// Abstraction to keep monitors small enough to fit in a lock word (32bits). On 32bit systems the
+// monitor id loses the alignment bits of the Monitor*.
+class MonitorPool {
+ public:
+ static MonitorPool* Create() {
+#ifndef __LP64__
+ return nullptr;
+#else
+ return new MonitorPool();
+#endif
+ }
+
+ static Monitor* MonitorFromMonitorId(MonitorId mon_id) {
+#ifndef __LP64__
+ return reinterpret_cast<Monitor*>(mon_id << 3);
+#else
+ return Runtime::Current()->GetMonitorPool()->LookupMonitorFromTable(mon_id);
+#endif
+ }
+
+ static MonitorId MonitorIdFromMonitor(Monitor* mon) {
+#ifndef __LP64__
+ return reinterpret_cast<MonitorId>(mon) >> 3;
+#else
+ return mon->GetMonitorId();
+#endif
+ }
+
+ static MonitorId CreateMonitorId(Thread* self, Monitor* mon) {
+#ifndef __LP64__
+ UNUSED(self);
+ return MonitorIdFromMonitor(mon);
+#else
+ return Runtime::Current()->GetMonitorPool()->AllocMonitorIdFromTable(self, mon);
+#endif
+ }
+
+ static void ReleaseMonitorId(MonitorId mon_id) {
+#ifndef __LP64__
+ UNUSED(mon_id);
+#else
+ Runtime::Current()->GetMonitorPool()->ReleaseMonitorIdFromTable(mon_id);
+#endif
+ }
+
+ private:
+#ifdef __LP64__
+ MonitorPool();
+
+ Monitor* LookupMonitorFromTable(MonitorId mon_id);
+
+ MonitorId LookupMonitorIdFromTable(Monitor* mon);
+
+ MonitorId AllocMonitorIdFromTable(Thread* self, Monitor* mon);
+
+ void ReleaseMonitorIdFromTable(MonitorId mon_id);
+
+ ReaderWriterMutex allocated_ids_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
+ static constexpr uint32_t kMaxMonitorId = 0xFFFF;
+ std::bitset<kMaxMonitorId> allocated_ids_ GUARDED_BY(allocated_ids_lock_);
+ SafeMap<MonitorId, Monitor*> table_ GUARDED_BY(allocated_ids_lock_);
+#endif
+};
+
+} // namespace art
+
+#endif // ART_RUNTIME_MONITOR_POOL_H_
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index 2c75ecc..1a3ceb8 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -290,7 +290,7 @@ static jboolean DexFile_isDexOptNeeded(JNIEnv* env, jclass, jstring javaFilename
return JNI_TRUE;
}
if (oat_file->GetOatHeader().GetImageFileLocationOatDataBegin()
- != reinterpret_cast<uint32_t>(image_header.GetOatDataBegin())) {
+ != reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin())) {
if (kDebugLogging) {
ScopedObjectAccess soa(env);
LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index c9e255c..e1b5f97 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -90,7 +90,7 @@ static jlong VMRuntime_addressOf(JNIEnv* env, jobject, jobject javaArray) {
ThrowRuntimeException("Trying to get address of movable array object");
return 0;
}
- return reinterpret_cast<uintptr_t>(array->GetRawData(array->GetClass()->GetComponentSize()));
+ return reinterpret_cast<uintptr_t>(array->GetRawData(array->GetClass()->GetComponentSize(), 0));
}
static void VMRuntime_clearGrowthLimit(JNIEnv*, jobject) {
@@ -181,7 +181,8 @@ static void VMRuntime_concurrentGC(JNIEnv* env, jobject) {
typedef std::map<std::string, mirror::String*> StringTable;
-static mirror::Object* PreloadDexCachesStringsVisitor(mirror::Object* root, void* arg) {
+static mirror::Object* PreloadDexCachesStringsVisitor(mirror::Object* root, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
StringTable& table = *reinterpret_cast<StringTable*>(arg);
mirror::String* string = const_cast<mirror::Object*>(root)->AsString();
// LOG(INFO) << "VMRuntime.preloadDexCaches interned=" << string->ToModifiedUtf8();
diff --git a/runtime/native/dalvik_system_VMStack.cc b/runtime/native/dalvik_system_VMStack.cc
index f915365..7e02e29 100644
--- a/runtime/native/dalvik_system_VMStack.cc
+++ b/runtime/native/dalvik_system_VMStack.cc
@@ -79,7 +79,7 @@ static jobject VMStack_getClosestUserClassLoader(JNIEnv* env, jclass, jobject ja
ClosestUserClassLoaderVisitor(Thread* thread, mirror::Object* bootstrap, mirror::Object* system)
: StackVisitor(thread, NULL), bootstrap(bootstrap), system(system), class_loader(NULL) {}
- bool VisitFrame() {
+ bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(class_loader == NULL);
mirror::Class* c = GetMethod()->GetDeclaringClass();
mirror::Object* cl = c->GetClassLoader();
diff --git a/runtime/native/dalvik_system_Zygote.cc b/runtime/native/dalvik_system_Zygote.cc
index 7fa9457..22c5430 100644
--- a/runtime/native/dalvik_system_Zygote.cc
+++ b/runtime/native/dalvik_system_Zygote.cc
@@ -47,8 +47,10 @@
#if defined(__linux__)
#include <sys/personality.h>
#include <sys/utsname.h>
+#if defined(HAVE_ANDROID_OS)
#include <sys/capability.h>
#endif
+#endif
namespace art {
diff --git a/runtime/native/java_lang_System.cc b/runtime/native/java_lang_System.cc
index ea78e04..6bbe642 100644
--- a/runtime/native/java_lang_System.cc
+++ b/runtime/native/java_lang_System.cc
@@ -24,150 +24,14 @@
#include "mirror/object_array-inl.h"
#include "scoped_fast_native_object_access.h"
-/*
- * We make guarantees about the atomicity of accesses to primitive
- * variables. These guarantees also apply to elements of arrays.
- * In particular, 8-bit, 16-bit, and 32-bit accesses must be atomic and
- * must not cause "word tearing". Accesses to 64-bit array elements must
- * either be atomic or treated as two 32-bit operations. References are
- * always read and written atomically, regardless of the number of bits
- * used to represent them.
- *
- * We can't rely on standard libc functions like memcpy(3) and memmove(3)
- * in our implementation of System.arraycopy, because they may copy
- * byte-by-byte (either for the full run or for "unaligned" parts at the
- * start or end). We need to use functions that guarantee 16-bit or 32-bit
- * atomicity as appropriate.
- *
- * System.arraycopy() is heavily used, so having an efficient implementation
- * is important. The bionic libc provides a platform-optimized memory move
- * function that should be used when possible. If it's not available,
- * the trivial "reference implementation" versions below can be used until
- * a proper version can be written.
- *
- * For these functions, The caller must guarantee that dst/src are aligned
- * appropriately for the element type, and that n is a multiple of the
- * element size.
- */
+namespace art {
/*
- * Works like memmove(), except:
- * - if all arguments are at least 32-bit aligned, we guarantee that we
- * will use operations that preserve atomicity of 32-bit values
- * - if not, we guarantee atomicity of 16-bit values
- *
- * If all three arguments are not at least 16-bit aligned, the behavior
- * of this function is undefined. (We could remove this restriction by
- * testing for unaligned values and punting to memmove(), but that's
- * not currently useful.)
- *
- * TODO: add loop for 64-bit alignment
- * TODO: use __builtin_prefetch
- * TODO: write ARM/MIPS/x86 optimized versions
+ * We make guarantees about the atomicity of accesses to primitive variables. These guarantees
+ * also apply to elements of arrays. In particular, 8-bit, 16-bit, and 32-bit accesses must not
+ * cause "word tearing". Accesses to 64-bit array elements may be two 32-bit operations.
+ * References are never torn regardless of the number of bits used to represent them.
*/
-void MemmoveWords(void* dst, const void* src, size_t n) {
- DCHECK_EQ((((uintptr_t) dst | (uintptr_t) src | n) & 0x01), 0U);
-
- char* d = reinterpret_cast<char*>(dst);
- const char* s = reinterpret_cast<const char*>(src);
- size_t copyCount;
-
- // If the source and destination pointers are the same, this is
- // an expensive no-op. Testing for an empty move now allows us
- // to skip a check later.
- if (n == 0 || d == s) {
- return;
- }
-
- // Determine if the source and destination buffers will overlap if
- // we copy data forward (i.e. *dst++ = *src++).
- //
- // It's okay if the destination buffer starts before the source and
- // there is some overlap, because the reader is always ahead of the
- // writer.
- if (LIKELY((d < s) || ((size_t)(d - s) >= n))) {
- // Copy forward. We prefer 32-bit loads and stores even for 16-bit
- // data, so sort that out.
- if (((reinterpret_cast<uintptr_t>(d) | reinterpret_cast<uintptr_t>(s)) & 0x03) != 0) {
- // Not 32-bit aligned. Two possibilities:
- // (1) Congruent, we can align to 32-bit by copying one 16-bit val
- // (2) Non-congruent, we can do one of:
- // a. copy whole buffer as a series of 16-bit values
- // b. load/store 32 bits, using shifts to ensure alignment
- // c. just copy the as 32-bit values and assume the CPU
- // will do a reasonable job
- //
- // We're currently using (a), which is suboptimal.
- if (((reinterpret_cast<uintptr_t>(d) ^ reinterpret_cast<uintptr_t>(s)) & 0x03) != 0) {
- copyCount = n;
- } else {
- copyCount = 2;
- }
- n -= copyCount;
- copyCount /= sizeof(uint16_t);
-
- while (copyCount--) {
- *reinterpret_cast<uint16_t*>(d) = *reinterpret_cast<const uint16_t*>(s);
- d += sizeof(uint16_t);
- s += sizeof(uint16_t);
- }
- }
-
- // Copy 32-bit aligned words.
- copyCount = n / sizeof(uint32_t);
- while (copyCount--) {
- *reinterpret_cast<uint32_t*>(d) = *reinterpret_cast<const uint32_t*>(s);
- d += sizeof(uint32_t);
- s += sizeof(uint32_t);
- }
-
- // Check for leftovers. Either we finished exactly, or we have one remaining 16-bit chunk.
- if ((n & 0x02) != 0) {
- *reinterpret_cast<uint16_t*>(d) = *reinterpret_cast<const uint16_t*>(s);
- }
- } else {
- // Copy backward, starting at the end.
- d += n;
- s += n;
-
- if (((reinterpret_cast<uintptr_t>(d) | reinterpret_cast<uintptr_t>(s)) & 0x03) != 0) {
- // try for 32-bit alignment.
- if (((reinterpret_cast<uintptr_t>(d) ^ reinterpret_cast<uintptr_t>(s)) & 0x03) != 0) {
- copyCount = n;
- } else {
- copyCount = 2;
- }
- n -= copyCount;
- copyCount /= sizeof(uint16_t);
-
- while (copyCount--) {
- d -= sizeof(uint16_t);
- s -= sizeof(uint16_t);
- *reinterpret_cast<uint16_t*>(d) = *reinterpret_cast<const uint16_t*>(s);
- }
- }
-
- // Copy 32-bit aligned words.
- copyCount = n / sizeof(uint32_t);
- while (copyCount--) {
- d -= sizeof(uint32_t);
- s -= sizeof(uint32_t);
- *reinterpret_cast<uint32_t*>(d) = *reinterpret_cast<const uint32_t*>(s);
- }
-
- // Copy leftovers.
- if ((n & 0x02) != 0) {
- d -= sizeof(uint16_t);
- s -= sizeof(uint16_t);
- *reinterpret_cast<uint16_t*>(d) = *reinterpret_cast<const uint16_t*>(s);
- }
- }
-}
-
-#define move16 MemmoveWords
-#define move32 MemmoveWords
-
-namespace art {
static void ThrowArrayStoreException_NotAnArray(const char* identifier, mirror::Object* array)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -178,168 +42,132 @@ static void ThrowArrayStoreException_NotAnArray(const char* identifier, mirror::
"%s of type %s is not an array", identifier, actualType.c_str());
}
-static void System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, jobject javaDst, jint dstPos, jint length) {
+static void System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, jobject javaDst,
+ jint dstPos, jint length) {
+ // The API is defined in terms of length, but length is somewhat overloaded so we use count.
+ const jint count = length;
ScopedFastNativeObjectAccess soa(env);
// Null pointer checks.
- if (UNLIKELY(javaSrc == NULL)) {
- ThrowNullPointerException(NULL, "src == null");
+ if (UNLIKELY(javaSrc == nullptr)) {
+ ThrowNullPointerException(nullptr, "src == null");
return;
}
- if (UNLIKELY(javaDst == NULL)) {
- ThrowNullPointerException(NULL, "dst == null");
+ if (UNLIKELY(javaDst == nullptr)) {
+ ThrowNullPointerException(nullptr, "dst == null");
return;
}
// Make sure source and destination are both arrays.
mirror::Object* srcObject = soa.Decode<mirror::Object*>(javaSrc);
- mirror::Object* dstObject = soa.Decode<mirror::Object*>(javaDst);
if (UNLIKELY(!srcObject->IsArrayInstance())) {
ThrowArrayStoreException_NotAnArray("source", srcObject);
return;
}
+ mirror::Object* dstObject = soa.Decode<mirror::Object*>(javaDst);
if (UNLIKELY(!dstObject->IsArrayInstance())) {
ThrowArrayStoreException_NotAnArray("destination", dstObject);
return;
}
mirror::Array* srcArray = srcObject->AsArray();
mirror::Array* dstArray = dstObject->AsArray();
- mirror::Class* srcComponentType = srcArray->GetClass()->GetComponentType();
- mirror::Class* dstComponentType = dstArray->GetClass()->GetComponentType();
// Bounds checking.
- if (UNLIKELY(srcPos < 0 || dstPos < 0 || length < 0 || srcPos > srcArray->GetLength() - length || dstPos > dstArray->GetLength() - length)) {
+ if (UNLIKELY(srcPos < 0) || UNLIKELY(dstPos < 0) || UNLIKELY(count < 0) ||
+ UNLIKELY(srcPos > srcArray->GetLength() - count) ||
+ UNLIKELY(dstPos > dstArray->GetLength() - count)) {
ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayIndexOutOfBoundsException;",
"src.length=%d srcPos=%d dst.length=%d dstPos=%d length=%d",
- srcArray->GetLength(), srcPos, dstArray->GetLength(), dstPos, length);
+ srcArray->GetLength(), srcPos, dstArray->GetLength(), dstPos,
+ count);
return;
}
- // Handle primitive arrays.
- if (srcComponentType->IsPrimitive() || dstComponentType->IsPrimitive()) {
- // If one of the arrays holds a primitive type the other array must hold the exact same type.
- if (UNLIKELY(srcComponentType != dstComponentType)) {
- std::string srcType(PrettyTypeOf(srcArray));
- std::string dstType(PrettyTypeOf(dstArray));
- ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
- soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayStoreException;",
- "Incompatible types: src=%s, dst=%s",
- srcType.c_str(), dstType.c_str());
- return;
- }
-
- size_t width = srcArray->GetClass()->GetComponentSize();
- uint8_t* dstBytes = reinterpret_cast<uint8_t*>(dstArray->GetRawData(width));
- const uint8_t* srcBytes = reinterpret_cast<const uint8_t*>(srcArray->GetRawData(width));
-
- switch (width) {
- case 1:
- memmove(dstBytes + dstPos, srcBytes + srcPos, length);
- break;
- case 2:
- move16(dstBytes + dstPos * 2, srcBytes + srcPos * 2, length * 2);
- break;
- case 4:
- move32(dstBytes + dstPos * 4, srcBytes + srcPos * 4, length * 4);
- break;
- case 8:
- // We don't need to guarantee atomicity of the entire 64-bit word.
- move32(dstBytes + dstPos * 8, srcBytes + srcPos * 8, length * 8);
- break;
- default:
- LOG(FATAL) << "Unknown primitive array type: " << PrettyTypeOf(srcArray);
- }
-
- return;
- }
-
- // Neither class is primitive. Are the types trivially compatible?
- const size_t width = sizeof(mirror::Object*);
- uint8_t* dstBytes = reinterpret_cast<uint8_t*>(dstArray->GetRawData(width));
- const uint8_t* srcBytes = reinterpret_cast<const uint8_t*>(srcArray->GetRawData(width));
- if (dstArray == srcArray || dstComponentType->IsAssignableFrom(srcComponentType)) {
- // Yes. Bulk copy.
- COMPILE_ASSERT(sizeof(width) == sizeof(uint32_t), move32_assumes_Object_references_are_32_bit);
- move32(dstBytes + dstPos * width, srcBytes + srcPos * width, length * width);
- Runtime::Current()->GetHeap()->WriteBarrierArray(dstArray, dstPos, length);
- return;
- }
-
- // The arrays are not trivially compatible. However, we may still be able to copy some or all of
- // the elements if the source objects are compatible (for example, copying an Object[] to
- // String[], the Objects being copied might actually be Strings).
- // We can't do a bulk move because that would introduce a check-use race condition, so we copy
- // elements one by one.
-
- // We already dealt with overlapping copies, so we don't need to cope with that case below.
- CHECK_NE(dstArray, srcArray);
-
- mirror::Object* const * srcObjects =
- reinterpret_cast<mirror::Object* const *>(srcBytes + srcPos * width);
- mirror::Object** dstObjects = reinterpret_cast<mirror::Object**>(dstBytes + dstPos * width);
- mirror::Class* dstClass = dstArray->GetClass()->GetComponentType();
-
- // We want to avoid redundant IsAssignableFrom checks where possible, so we cache a class that
- // we know is assignable to the destination array's component type.
- mirror::Class* lastAssignableElementClass = dstClass;
-
- mirror::Object* o = NULL;
- int i = 0;
- for (; i < length; ++i) {
- o = srcObjects[i];
- if (o != NULL) {
- mirror::Class* oClass = o->GetClass();
- if (lastAssignableElementClass == oClass) {
- dstObjects[i] = o;
- } else if (dstClass->IsAssignableFrom(oClass)) {
- lastAssignableElementClass = oClass;
- dstObjects[i] = o;
- } else {
- // Can't put this element into the array.
- break;
+ mirror::Class* dstComponentType = dstArray->GetClass()->GetComponentType();
+ mirror::Class* srcComponentType = srcArray->GetClass()->GetComponentType();
+ Primitive::Type dstComponentPrimitiveType = dstComponentType->GetPrimitiveType();
+
+ if (LIKELY(srcComponentType == dstComponentType)) {
+ // Trivial assignability.
+ switch (dstComponentPrimitiveType) {
+ case Primitive::kPrimVoid:
+ LOG(FATAL) << "Unreachable, cannot have arrays of type void";
+ return;
+ case Primitive::kPrimBoolean:
+ case Primitive::kPrimByte:
+ DCHECK_EQ(Primitive::ComponentSize(dstComponentPrimitiveType), 1U);
+ dstArray->AsByteSizedArray()->Memmove(dstPos, srcArray->AsByteSizedArray(), srcPos, count);
+ return;
+ case Primitive::kPrimChar:
+ case Primitive::kPrimShort:
+ DCHECK_EQ(Primitive::ComponentSize(dstComponentPrimitiveType), 2U);
+ dstArray->AsShortSizedArray()->Memmove(dstPos, srcArray->AsShortSizedArray(), srcPos, count);
+ return;
+ case Primitive::kPrimInt:
+ case Primitive::kPrimFloat:
+ DCHECK_EQ(Primitive::ComponentSize(dstComponentPrimitiveType), 4U);
+ dstArray->AsIntArray()->Memmove(dstPos, srcArray->AsIntArray(), srcPos, count);
+ return;
+ case Primitive::kPrimLong:
+ case Primitive::kPrimDouble:
+ DCHECK_EQ(Primitive::ComponentSize(dstComponentPrimitiveType), 8U);
+ dstArray->AsLongArray()->Memmove(dstPos, srcArray->AsLongArray(), srcPos, count);
+ return;
+ case Primitive::kPrimNot: {
+ mirror::ObjectArray<mirror::Object>* dstObjArray = dstArray->AsObjectArray<mirror::Object>();
+ mirror::ObjectArray<mirror::Object>* srcObjArray = srcArray->AsObjectArray<mirror::Object>();
+ dstObjArray->AssignableMemmove(dstPos, srcObjArray, srcPos, count);
+ return;
}
- } else {
- dstObjects[i] = NULL;
+ default:
+ LOG(FATAL) << "Unknown array type: " << PrettyTypeOf(srcArray);
+ return;
}
}
-
- Runtime::Current()->GetHeap()->WriteBarrierArray(dstArray, dstPos, length);
- if (UNLIKELY(i != length)) {
- std::string actualSrcType(PrettyTypeOf(o));
+ // If one of the arrays holds a primitive type the other array must hold the exact same type.
+ if (UNLIKELY((dstComponentPrimitiveType != Primitive::kPrimNot) ||
+ srcComponentType->IsPrimitive())) {
+ std::string srcType(PrettyTypeOf(srcArray));
std::string dstType(PrettyTypeOf(dstArray));
ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayStoreException;",
- "source[%d] of type %s cannot be stored in destination array of type %s",
- srcPos + i, actualSrcType.c_str(), dstType.c_str());
+ "Incompatible types: src=%s, dst=%s",
+ srcType.c_str(), dstType.c_str());
+ return;
+ }
+ // Arrays hold distinct types and so therefore can't alias - use memcpy instead of memmove.
+ mirror::ObjectArray<mirror::Object>* dstObjArray = dstArray->AsObjectArray<mirror::Object>();
+ mirror::ObjectArray<mirror::Object>* srcObjArray = srcArray->AsObjectArray<mirror::Object>();
+ // If we're assigning into say Object[] then we don't need per element checks.
+ if (dstComponentType->IsAssignableFrom(srcComponentType)) {
+ dstObjArray->AssignableMemcpy(dstPos, srcObjArray, srcPos, count);
return;
}
+ dstObjArray->AssignableCheckingMemcpy(dstPos, srcObjArray, srcPos, count, true);
}
-static void System_arraycopyCharUnchecked(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, jobject javaDst, jint dstPos, jint length) {
+static void System_arraycopyCharUnchecked(JNIEnv* env, jclass, jobject javaSrc, jint srcPos,
+ jobject javaDst, jint dstPos, jint count) {
ScopedFastNativeObjectAccess soa(env);
- DCHECK(javaSrc != NULL);
- DCHECK(javaDst != NULL);
mirror::Object* srcObject = soa.Decode<mirror::Object*>(javaSrc);
mirror::Object* dstObject = soa.Decode<mirror::Object*>(javaDst);
- DCHECK(srcObject->IsArrayInstance());
- DCHECK(dstObject->IsArrayInstance());
+ DCHECK(srcObject != nullptr);
+ DCHECK(dstObject != nullptr);
mirror::Array* srcArray = srcObject->AsArray();
mirror::Array* dstArray = dstObject->AsArray();
- DCHECK(srcPos >= 0 && dstPos >= 0 && length >= 0 &&
- srcPos + length <= srcArray->GetLength() && dstPos + length <= dstArray->GetLength());
- DCHECK_EQ(srcArray->GetClass()->GetComponentType(), dstArray->GetClass()->GetComponentType());
- DCHECK(srcArray->GetClass()->GetComponentType()->IsPrimitive());
- DCHECK(dstArray->GetClass()->GetComponentType()->IsPrimitive());
- DCHECK_EQ(srcArray->GetClass()->GetComponentSize(), static_cast<size_t>(2));
- DCHECK_EQ(dstArray->GetClass()->GetComponentSize(), static_cast<size_t>(2));
- uint8_t* dstBytes = reinterpret_cast<uint8_t*>(dstArray->GetRawData(2));
- const uint8_t* srcBytes = reinterpret_cast<const uint8_t*>(srcArray->GetRawData(2));
- move16(dstBytes + dstPos * 2, srcBytes + srcPos * 2, length * 2);
+ DCHECK_GE(srcPos, 0);
+ DCHECK_GE(dstPos, 0);
+ DCHECK_GE(count, 0);
+ DCHECK_LE(srcPos + count, srcArray->GetLength());
+ DCHECK_LE(dstPos + count, dstArray->GetLength());
+ DCHECK_EQ(srcArray->GetClass(), dstArray->GetClass());
+ DCHECK_EQ(srcArray->GetClass()->GetComponentType()->GetPrimitiveType(), Primitive::kPrimChar);
+ dstArray->AsCharArray()->Memmove(dstPos, srcArray->AsCharArray(), srcPos, count);
}
static jint System_identityHashCode(JNIEnv* env, jclass, jobject javaObject) {
- if (javaObject == nullptr) {
+ if (UNLIKELY(javaObject == nullptr)) {
return 0;
}
ScopedFastNativeObjectAccess soa(env);
diff --git a/runtime/native/sun_misc_Unsafe.cc b/runtime/native/sun_misc_Unsafe.cc
index b5fc7e7..6c22003 100644
--- a/runtime/native/sun_misc_Unsafe.cc
+++ b/runtime/native/sun_misc_Unsafe.cc
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include "atomic.h"
#include "gc/accounting/card_table-inl.h"
#include "jni_internal.h"
#include "mirror/object.h"
@@ -23,40 +22,30 @@
namespace art {
-static jboolean Unsafe_compareAndSwapInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint expectedValue, jint newValue) {
+static jboolean Unsafe_compareAndSwapInt(JNIEnv* env, jobject, jobject javaObj, jlong offset,
+ jint expectedValue, jint newValue) {
ScopedFastNativeObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
- byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
- volatile int32_t* address = reinterpret_cast<volatile int32_t*>(raw_addr);
- // Note: android_atomic_release_cas() returns 0 on success, not failure.
- int result = android_atomic_release_cas(expectedValue, newValue, address);
- return (result == 0) ? JNI_TRUE : JNI_FALSE;
+ bool success = obj->CasField32(MemberOffset(offset), expectedValue, newValue);
+ return success ? JNI_TRUE : JNI_FALSE;
}
-static jboolean Unsafe_compareAndSwapLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong expectedValue, jlong newValue) {
+static jboolean Unsafe_compareAndSwapLong(JNIEnv* env, jobject, jobject javaObj, jlong offset,
+ jlong expectedValue, jlong newValue) {
ScopedFastNativeObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
- byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
- volatile int64_t* address = reinterpret_cast<volatile int64_t*>(raw_addr);
- // Note: android_atomic_cmpxchg() returns 0 on success, not failure.
- bool success = QuasiAtomic::Cas64(expectedValue, newValue, address);
+ bool success = obj->CasField64(MemberOffset(offset), expectedValue, newValue);
return success ? JNI_TRUE : JNI_FALSE;
}
-static jboolean Unsafe_compareAndSwapObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaExpectedValue, jobject javaNewValue) {
+static jboolean Unsafe_compareAndSwapObject(JNIEnv* env, jobject, jobject javaObj, jlong offset,
+ jobject javaExpectedValue, jobject javaNewValue) {
ScopedFastNativeObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
mirror::Object* expectedValue = soa.Decode<mirror::Object*>(javaExpectedValue);
mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue);
- byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
- int32_t* address = reinterpret_cast<int32_t*>(raw_addr);
- // Note: android_atomic_cmpxchg() returns 0 on success, not failure.
- int result = android_atomic_release_cas(reinterpret_cast<int32_t>(expectedValue),
- reinterpret_cast<int32_t>(newValue), address);
- if (result == 0) {
- Runtime::Current()->GetHeap()->WriteBarrierField(obj, MemberOffset(offset), newValue);
- }
- return (result == 0) ? JNI_TRUE : JNI_FALSE;
+ bool success = obj->CasFieldObject(MemberOffset(offset), expectedValue, newValue);
+ return success ? JNI_TRUE : JNI_FALSE;
}
static jint Unsafe_getInt(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
@@ -77,13 +66,15 @@ static void Unsafe_putInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, j
obj->SetField32(MemberOffset(offset), newValue, false);
}
-static void Unsafe_putIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) {
+static void Unsafe_putIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
+ jint newValue) {
ScopedFastNativeObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
obj->SetField32(MemberOffset(offset), newValue, true);
}
-static void Unsafe_putOrderedInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) {
+static void Unsafe_putOrderedInt(JNIEnv* env, jobject, jobject javaObj, jlong offset,
+ jint newValue) {
ScopedFastNativeObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
QuasiAtomic::MembarStoreStore();
@@ -108,13 +99,15 @@ static void Unsafe_putLong(JNIEnv* env, jobject, jobject javaObj, jlong offset,
obj->SetField64(MemberOffset(offset), newValue, false);
}
-static void Unsafe_putLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) {
+static void Unsafe_putLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
+ jlong newValue) {
ScopedFastNativeObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
obj->SetField64(MemberOffset(offset), newValue, true);
}
-static void Unsafe_putOrderedLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) {
+static void Unsafe_putOrderedLong(JNIEnv* env, jobject, jobject javaObj, jlong offset,
+ jlong newValue) {
ScopedFastNativeObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
QuasiAtomic::MembarStoreStore();
@@ -124,32 +117,35 @@ static void Unsafe_putOrderedLong(JNIEnv* env, jobject, jobject javaObj, jlong o
static jobject Unsafe_getObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
ScopedFastNativeObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
- mirror::Object* value = obj->GetFieldObject<mirror::Object*>(MemberOffset(offset), true);
+ mirror::Object* value = obj->GetFieldObject<mirror::Object>(MemberOffset(offset), true);
return soa.AddLocalReference<jobject>(value);
}
static jobject Unsafe_getObject(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
ScopedFastNativeObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
- mirror::Object* value = obj->GetFieldObject<mirror::Object*>(MemberOffset(offset), false);
+ mirror::Object* value = obj->GetFieldObject<mirror::Object>(MemberOffset(offset), false);
return soa.AddLocalReference<jobject>(value);
}
-static void Unsafe_putObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) {
+static void Unsafe_putObject(JNIEnv* env, jobject, jobject javaObj, jlong offset,
+ jobject javaNewValue) {
ScopedFastNativeObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue);
obj->SetFieldObject(MemberOffset(offset), newValue, false);
}
-static void Unsafe_putObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) {
+static void Unsafe_putObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
+ jobject javaNewValue) {
ScopedFastNativeObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue);
obj->SetFieldObject(MemberOffset(offset), newValue, true);
}
-static void Unsafe_putOrderedObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) {
+static void Unsafe_putOrderedObject(JNIEnv* env, jobject, jobject javaObj, jlong offset,
+ jobject javaNewValue) {
ScopedFastNativeObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue);
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index be88204..0f380ad 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -66,16 +66,16 @@ OatFile* OatFile::Open(const std::string& filename,
std::string* error_msg) {
CHECK(!filename.empty()) << location;
CheckLocation(filename);
-#ifdef ART_USE_PORTABLE_COMPILER
- // If we are using PORTABLE, use dlopen to deal with relocations.
- //
- // We use our own ELF loader for Quick to deal with legacy apps that
- // open a generated dex file by name, remove the file, then open
- // another generated dex file with the same name. http://b/10614658
- if (executable) {
- return OpenDlopen(filename, location, requested_base, error_msg);
+ if (kUsePortableCompiler) {
+ // If we are using PORTABLE, use dlopen to deal with relocations.
+ //
+ // We use our own ELF loader for Quick to deal with legacy apps that
+ // open a generated dex file by name, remove the file, then open
+ // another generated dex file with the same name. http://b/10614658
+ if (executable) {
+ return OpenDlopen(filename, location, requested_base, error_msg);
+ }
}
-#endif
// If we aren't trying to execute, we just use our own ElfFile loader for a couple reasons:
//
// On target, dlopen may fail when compiling due to selinux restrictions on installd.
@@ -503,51 +503,40 @@ OatFile::OatMethod::OatMethod(const byte* base,
mapping_table_offset_(mapping_table_offset),
vmap_table_offset_(vmap_table_offset),
native_gc_map_offset_(gc_map_offset) {
-#ifndef NDEBUG
- if (mapping_table_offset_ != 0) { // implies non-native, non-stub code
- if (vmap_table_offset_ == 0) {
- DCHECK_EQ(0U, static_cast<uint32_t>(__builtin_popcount(core_spill_mask_) +
- __builtin_popcount(fp_spill_mask_)));
+ if (kIsDebugBuild) {
+ if (mapping_table_offset_ != 0) { // implies non-native, non-stub code
+ if (vmap_table_offset_ == 0) {
+ CHECK_EQ(0U, static_cast<uint32_t>(__builtin_popcount(core_spill_mask_) +
+ __builtin_popcount(fp_spill_mask_)));
+ } else {
+ VmapTable vmap_table(reinterpret_cast<const uint8_t*>(begin_ + vmap_table_offset_));
+
+ CHECK_EQ(vmap_table.Size(), static_cast<uint32_t>(__builtin_popcount(core_spill_mask_) +
+ __builtin_popcount(fp_spill_mask_)));
+ }
} else {
- VmapTable vmap_table(reinterpret_cast<const uint8_t*>(begin_ + vmap_table_offset_));
-
- DCHECK_EQ(vmap_table.Size(), static_cast<uint32_t>(__builtin_popcount(core_spill_mask_) +
- __builtin_popcount(fp_spill_mask_)));
+ CHECK_EQ(vmap_table_offset_, 0U);
}
- } else {
- DCHECK_EQ(vmap_table_offset_, 0U);
}
-#endif
}
OatFile::OatMethod::~OatMethod() {}
-const void* OatFile::OatMethod::GetCode() const {
- return GetOatPointer<const void*>(code_offset_);
-}
-
-uint32_t OatFile::OatMethod::GetCodeSize() const {
-#if defined(ART_USE_PORTABLE_COMPILER)
- // TODO: With Quick, we store the size before the code. With
- // Portable, the code is in a .o file we don't manage ourselves. ELF
- // symbols do have a concept of size, so we could capture that and
- // store it somewhere, such as the OatMethod.
- return 0;
-#else
- uintptr_t code = reinterpret_cast<uint32_t>(GetCode());
+uint32_t OatFile::OatMethod::GetQuickCodeSize() const {
+ uintptr_t code = reinterpret_cast<uintptr_t>(GetQuickCode());
if (code == 0) {
return 0;
}
// TODO: make this Thumb2 specific
code &= ~0x1;
return reinterpret_cast<uint32_t*>(code)[-1];
-#endif
}
void OatFile::OatMethod::LinkMethod(mirror::ArtMethod* method) const {
CHECK(method != NULL);
- method->SetEntryPointFromCompiledCode(GetCode());
+ method->SetEntryPointFromPortableCompiledCode(GetPortableCode());
+ method->SetEntryPointFromQuickCompiledCode(GetQuickCode());
method->SetFrameSizeInBytes(frame_size_in_bytes_);
method->SetCoreSpillMask(core_spill_mask_);
method->SetFpSpillMask(fp_spill_mask_);
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index 887a9d1..d6e8dc0 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -97,8 +97,30 @@ class OatFile {
return native_gc_map_offset_;
}
- const void* GetCode() const;
- uint32_t GetCodeSize() const;
+ const void* GetPortableCode() const {
+ // TODO: encode whether code is portable/quick in flags within OatMethod.
+ if (kUsePortableCompiler) {
+ return GetOatPointer<const void*>(code_offset_);
+ } else {
+ return nullptr;
+ }
+ }
+
+ const void* GetQuickCode() const {
+ if (kUsePortableCompiler) {
+ return nullptr;
+ } else {
+ return GetOatPointer<const void*>(code_offset_);
+ }
+ }
+
+ uint32_t GetPortableCodeSize() const {
+ // TODO: With Quick, we store the size before the code. With Portable, the code is in a .o
+ // file we don't manage ourselves. ELF symbols do have a concept of size, so we could capture
+ // that and store it somewhere, such as the OatMethod.
+ return 0;
+ }
+ uint32_t GetQuickCodeSize() const;
const uint8_t* GetMappingTable() const {
return GetOatPointer<const uint8_t*>(mapping_table_offset_);
diff --git a/runtime/object_utils.h b/runtime/object_utils.h
index 407aa65..0451f5d 100644
--- a/runtime/object_utils.h
+++ b/runtime/object_utils.h
@@ -69,30 +69,29 @@ class ObjectLock {
class ClassHelper {
public:
- explicit ClassHelper(const mirror::Class* c )
+ explicit ClassHelper(mirror::Class* c )
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- : interface_type_list_(NULL),
- klass_(NULL) {
- if (c != NULL) {
+ : interface_type_list_(nullptr), klass_(nullptr) {
+ if (c != nullptr) {
ChangeClass(c);
}
}
- void ChangeClass(const mirror::Class* new_c)
+ void ChangeClass(mirror::Class* new_c)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- CHECK(new_c != NULL) << "klass_=" << klass_; // Log what we were changing from if any
+ 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() : NULL);
+ << ((new_c->GetClass() != nullptr) ? new_c->GetClass()->GetClass() : nullptr);
}
klass_ = new_c;
- interface_type_list_ = NULL;
+ 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_ != NULL);
+ CHECK(klass_ != nullptr);
if (UNLIKELY(klass_->IsArrayClass())) {
return GetArrayDescriptor();
} else if (UNLIKELY(klass_->IsPrimitive())) {
@@ -109,8 +108,8 @@ class ClassHelper {
const char* GetArrayDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
std::string result("[");
- const mirror::Class* saved_klass = klass_;
- CHECK(saved_klass != NULL);
+ mirror::Class* saved_klass = klass_;
+ CHECK(saved_klass != nullptr);
ChangeClass(klass_->GetComponentType());
result += GetDescriptor();
ChangeClass(saved_klass);
@@ -128,7 +127,7 @@ class ClassHelper {
}
uint32_t NumDirectInterfaces() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(klass_ != NULL);
+ DCHECK(klass_ != nullptr);
if (klass_->IsPrimitive()) {
return 0;
} else if (klass_->IsArrayClass()) {
@@ -137,7 +136,7 @@ class ClassHelper {
return klass_->GetIfTable()->GetLength();
} else {
const DexFile::TypeList* interfaces = GetInterfaceTypeList();
- if (interfaces == NULL) {
+ if (interfaces == nullptr) {
return 0;
} else {
return interfaces->Size();
@@ -147,7 +146,7 @@ class ClassHelper {
uint16_t GetDirectInterfaceTypeIdx(uint32_t idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(klass_ != NULL);
+ DCHECK(klass_ != nullptr);
DCHECK(!klass_->IsPrimitive());
DCHECK(!klass_->IsArrayClass());
return GetInterfaceTypeList()->GetTypeItem(idx).type_idx_;
@@ -155,7 +154,7 @@ class ClassHelper {
mirror::Class* GetDirectInterface(uint32_t idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(klass_ != NULL);
+ DCHECK(klass_ != nullptr);
DCHECK(!klass_->IsPrimitive());
if (klass_->IsArrayClass()) {
if (idx == 0) {
@@ -169,9 +168,9 @@ class ClassHelper {
} else {
uint16_t type_idx = GetDirectInterfaceTypeIdx(idx);
mirror::Class* interface = GetDexCache()->GetResolvedType(type_idx);
- if (interface == NULL) {
+ if (interface == nullptr) {
interface = GetClassLinker()->ResolveType(GetDexFile(), type_idx, klass_);
- CHECK(interface != NULL || Thread::Current()->IsExceptionPending());
+ CHECK(interface != nullptr || Thread::Current()->IsExceptionPending());
}
return interface;
}
@@ -181,13 +180,13 @@ class ClassHelper {
std::string descriptor(GetDescriptor());
const DexFile& dex_file = GetDexFile();
const DexFile::ClassDef* dex_class_def = GetClassDef();
- CHECK(dex_class_def != NULL);
+ CHECK(dex_class_def != nullptr);
return dex_file.GetSourceFile(*dex_class_def);
}
std::string GetLocation() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::DexCache* dex_cache = GetDexCache();
- if (dex_cache != NULL && !klass_->IsProxyClass()) {
+ if (dex_cache != nullptr && !klass_->IsProxyClass()) {
return dex_cache->GetLocation()->ToModifiedUtf8();
} else {
// Arrays and proxies are generated and have no corresponding dex file location.
@@ -207,9 +206,9 @@ class ClassHelper {
const DexFile::TypeList* GetInterfaceTypeList()
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
const DexFile::TypeList* result = interface_type_list_;
- if (result == NULL) {
+ if (result == nullptr) {
const DexFile::ClassDef* class_def = GetClassDef();
- if (class_def != NULL) {
+ if (class_def != nullptr) {
result = GetDexFile().GetInterfacesList(*class_def);
interface_type_list_ = result;
}
@@ -222,7 +221,7 @@ class ClassHelper {
}
const DexFile::TypeList* interface_type_list_;
- const mirror::Class* klass_;
+ mirror::Class* klass_;
std::string descriptor_;
DISALLOW_COPY_AND_ASSIGN(ClassHelper);
@@ -230,11 +229,11 @@ class ClassHelper {
class FieldHelper {
public:
- FieldHelper() : field_(NULL) {}
- explicit FieldHelper(const mirror::ArtField* f) : field_(f) {}
+ FieldHelper() : field_(nullptr) {}
+ explicit FieldHelper(mirror::ArtField* f) : field_(f) {}
- void ChangeField(const mirror::ArtField* new_f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(new_f != NULL);
+ void ChangeField(mirror::ArtField* new_f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(new_f != nullptr);
field_ = new_f;
}
@@ -257,9 +256,9 @@ class FieldHelper {
const DexFile& dex_file = GetDexFile();
const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
mirror::Class* type = GetDexCache()->GetResolvedType(field_id.type_idx_);
- if (resolve && (type == NULL)) {
+ if (resolve && (type == nullptr)) {
type = GetClassLinker()->ResolveType(field_id.type_idx_, field_);
- CHECK(type != NULL || Thread::Current()->IsExceptionPending());
+ CHECK(type != nullptr || Thread::Current()->IsExceptionPending());
}
return type;
}
@@ -320,7 +319,7 @@ class FieldHelper {
const DexFile& GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return *GetDexCache()->GetDexFile();
}
- const mirror::ArtField* field_;
+ mirror::ArtField* field_;
std::string declaring_class_descriptor_;
DISALLOW_COPY_AND_ASSIGN(FieldHelper);
@@ -328,20 +327,18 @@ class FieldHelper {
class MethodHelper {
public:
- MethodHelper()
- : method_(NULL), shorty_(NULL),
- shorty_len_(0) {}
+ MethodHelper() : method_(nullptr), shorty_(nullptr), shorty_len_(0) {}
- explicit MethodHelper(const mirror::ArtMethod* m)
+ explicit MethodHelper(mirror::ArtMethod* m)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- : method_(NULL), shorty_(NULL), shorty_len_(0) {
+ : method_(nullptr), shorty_(nullptr), shorty_len_(0) {
SetMethod(m);
}
void ChangeMethod(mirror::ArtMethod* new_m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(new_m != NULL);
+ DCHECK(new_m != nullptr);
SetMethod(new_m);
- shorty_ = NULL;
+ shorty_ = nullptr;
}
const mirror::ArtMethod* GetMethod() const {
@@ -381,7 +378,7 @@ class MethodHelper {
const char* GetShorty() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
const char* result = shorty_;
- if (result == NULL) {
+ if (result == nullptr) {
const DexFile& dex_file = GetDexFile();
result = dex_file.GetMethodShorty(dex_file.GetMethodId(method_->GetDexMethodIndex()),
&shorty_len_);
@@ -391,7 +388,7 @@ class MethodHelper {
}
uint32_t GetShortyLength() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (shorty_ == NULL) {
+ if (shorty_ == nullptr) {
GetShorty();
}
return shorty_len_;
@@ -529,15 +526,15 @@ class MethodHelper {
bool IsResolvedTypeIdx(uint16_t type_idx) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return method_->GetDexCacheResolvedTypes()->Get(type_idx) != NULL;
+ return method_->GetDexCacheResolvedTypes()->Get(type_idx) != nullptr;
}
mirror::Class* GetClassFromTypeIdx(uint16_t type_idx, bool resolve = true)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::Class* type = method_->GetDexCacheResolvedTypes()->Get(type_idx);
- if (type == NULL && resolve) {
+ if (type == nullptr && resolve) {
type = GetClassLinker()->ResolveType(type_idx, method_);
- CHECK(type != NULL || Thread::Current()->IsExceptionPending());
+ CHECK(type != nullptr || Thread::Current()->IsExceptionPending());
}
return type;
}
@@ -563,7 +560,7 @@ class MethodHelper {
mirror::String* ResolveString(uint32_t string_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::String* s = method_->GetDexCacheStrings()->Get(string_idx);
- if (UNLIKELY(s == NULL)) {
+ if (UNLIKELY(s == nullptr)) {
SirtRef<mirror::DexCache> dex_cache(Thread::Current(), GetDexCache());
s = GetClassLinker()->ResolveString(GetDexFile(), string_idx, dex_cache);
}
@@ -613,13 +610,13 @@ class MethodHelper {
private:
// Set the method_ field, for proxy methods looking up the interface method via the resolved
// methods table.
- void SetMethod(const mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (method != NULL) {
+ void SetMethod(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ if (method != nullptr) {
mirror::Class* klass = method->GetDeclaringClass();
if (UNLIKELY(klass->IsProxyClass())) {
mirror::ArtMethod* interface_method =
method->GetDexCacheResolvedMethods()->Get(method->GetDexMethodIndex());
- DCHECK(interface_method != NULL);
+ DCHECK(interface_method != nullptr);
DCHECK(interface_method == GetClassLinker()->FindMethodForProxy(klass, method));
method = interface_method;
}
@@ -631,7 +628,7 @@ class MethodHelper {
return Runtime::Current()->GetClassLinker();
}
- const mirror::ArtMethod* method_;
+ mirror::ArtMethod* method_;
const char* shorty_;
uint32_t shorty_len_;
diff --git a/runtime/offsets.h b/runtime/offsets.h
index 94ae805..e2dba9d 100644
--- a/runtime/offsets.h
+++ b/runtime/offsets.h
@@ -22,7 +22,7 @@
namespace art {
-// Allow the meaning of offsets to be strongly typed
+// Allow the meaning of offsets to be strongly typed.
class Offset {
public:
explicit Offset(size_t val) : val_(val) {}
@@ -37,7 +37,7 @@ class Offset {
};
std::ostream& operator<<(std::ostream& os, const Offset& offs);
-// Offsets relative to the current frame
+// Offsets relative to the current frame.
class FrameOffset : public Offset {
public:
explicit FrameOffset(size_t val) : Offset(val) {}
@@ -45,13 +45,13 @@ class FrameOffset : public Offset {
bool operator<(FrameOffset other) const { return val_ < other.val_; }
};
-// Offsets relative to the current running thread
+// Offsets relative to the current running thread.
class ThreadOffset : public Offset {
public:
explicit ThreadOffset(size_t val) : Offset(val) {}
};
-// Offsets relative to an object
+// Offsets relative to an object.
class MemberOffset : public Offset {
public:
explicit MemberOffset(size_t val) : Offset(val) {}
diff --git a/runtime/primitive.h b/runtime/primitive.h
index 5e07311..b436bd2 100644
--- a/runtime/primitive.h
+++ b/runtime/primitive.h
@@ -21,6 +21,7 @@
#include "base/logging.h"
#include "base/macros.h"
+#include "mirror/object_reference.h"
namespace art {
namespace mirror {
@@ -78,7 +79,7 @@ class Primitive {
case kPrimFloat: return 4;
case kPrimLong:
case kPrimDouble: return 8;
- case kPrimNot: return sizeof(mirror::Object*);
+ case kPrimNot: return sizeof(mirror::HeapReference<mirror::Object>);
default:
LOG(FATAL) << "Invalid type " << static_cast<int>(type);
return 0;
diff --git a/runtime/profiler.cc b/runtime/profiler.cc
index 365c9c3..20e08b8 100644
--- a/runtime/profiler.cc
+++ b/runtime/profiler.cc
@@ -455,9 +455,7 @@ void ProfileSampleResults::Clear() {
}
uint32_t ProfileSampleResults::Hash(mirror::ArtMethod* method) {
- uint32_t value = reinterpret_cast<uint32_t>(method);
- value >>= 2;
- return value % kHashSize;
+ return (PointerToLowMemUInt32(method) >> 3) % kHashSize;
}
} // namespace art
diff --git a/runtime/reference_table.cc b/runtime/reference_table.cc
index 6f65bff..b5ef735 100644
--- a/runtime/reference_table.cc
+++ b/runtime/reference_table.cc
@@ -59,7 +59,7 @@ void ReferenceTable::Remove(mirror::Object* obj) {
// If "obj" is an array, return the number of elements in the array.
// Otherwise, return zero.
-static size_t GetElementCount(const mirror::Object* obj) {
+static size_t GetElementCount(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (obj == NULL || obj == kClearedJniWeakGlobal || !obj->IsArrayInstance()) {
return 0;
}
@@ -67,7 +67,7 @@ static size_t GetElementCount(const mirror::Object* obj) {
}
struct ObjectComparator {
- bool operator()(const mirror::Object* obj1, const mirror::Object* obj2)
+ bool operator()(mirror::Object* obj1, mirror::Object* obj2)
// TODO: enable analysis when analysis can work with the STL.
NO_THREAD_SAFETY_ANALYSIS {
Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
@@ -105,7 +105,7 @@ struct ObjectComparator {
// Pass in the number of elements in the array (or 0 if this is not an
// array object), and the number of additional objects that are identical
// or equivalent to the original.
-static void DumpSummaryLine(std::ostream& os, const mirror::Object* obj, size_t element_count,
+static void DumpSummaryLine(std::ostream& os, mirror::Object* obj, size_t element_count,
int identical, int equiv)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (obj == NULL) {
@@ -159,7 +159,7 @@ void ReferenceTable::Dump(std::ostream& os, const Table& entries) {
}
os << " Last " << (count - first) << " entries (of " << count << "):\n";
for (int idx = count - 1; idx >= first; --idx) {
- const mirror::Object* ref = entries[idx];
+ mirror::Object* ref = entries[idx];
if (ref == NULL) {
continue;
}
@@ -212,8 +212,8 @@ void ReferenceTable::Dump(std::ostream& os, const Table& entries) {
size_t equiv = 0;
size_t identical = 0;
for (size_t idx = 1; idx < count; idx++) {
- const mirror::Object* prev = sorted_entries[idx-1];
- const mirror::Object* current = sorted_entries[idx];
+ mirror::Object* prev = sorted_entries[idx-1];
+ mirror::Object* current = sorted_entries[idx];
size_t element_count = GetElementCount(prev);
if (current == prev) {
// Same reference, added more than once.
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index bcd3d31..4e90478 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -31,6 +31,7 @@
#include "arch/arm/registers_arm.h"
#include "arch/mips/registers_mips.h"
#include "arch/x86/registers_x86.h"
+#include "arch/x86_64/registers_x86_64.h"
#include "atomic.h"
#include "class_linker.h"
#include "debugger.h"
@@ -75,19 +76,27 @@ Runtime::Runtime()
is_zygote_(false),
is_concurrent_gc_enabled_(true),
is_explicit_gc_disabled_(false),
+ compiler_filter_(kSpeed),
+ huge_method_threshold_(0),
+ large_method_threshold_(0),
+ small_method_threshold_(0),
+ tiny_method_threshold_(0),
+ num_dex_methods_threshold_(0),
+ sea_ir_mode_(false),
default_stack_size_(0),
- heap_(NULL),
+ heap_(nullptr),
max_spins_before_thin_lock_inflation_(Monitor::kDefaultMaxSpinsBeforeThinLockInflation),
- monitor_list_(NULL),
- thread_list_(NULL),
- intern_table_(NULL),
- class_linker_(NULL),
- signal_catcher_(NULL),
- java_vm_(NULL),
- pre_allocated_OutOfMemoryError_(NULL),
- resolution_method_(NULL),
- imt_conflict_method_(NULL),
- default_imt_(NULL),
+ monitor_list_(nullptr),
+ monitor_pool_(nullptr),
+ thread_list_(nullptr),
+ intern_table_(nullptr),
+ class_linker_(nullptr),
+ signal_catcher_(nullptr),
+ java_vm_(nullptr),
+ pre_allocated_OutOfMemoryError_(nullptr),
+ resolution_method_(nullptr),
+ imt_conflict_method_(nullptr),
+ default_imt_(nullptr),
method_verifiers_lock_("Method verifiers lock"),
threads_being_born_(0),
shutdown_cond_(new ConditionVariable("Runtime shutdown", *Locks::runtime_shutdown_lock_)),
@@ -95,19 +104,25 @@ Runtime::Runtime()
shutting_down_started_(false),
started_(false),
finished_starting_(false),
- vfprintf_(NULL),
- exit_(NULL),
- abort_(NULL),
+ vfprintf_(nullptr),
+ exit_(nullptr),
+ abort_(nullptr),
stats_enabled_(false),
- method_trace_(0),
+ profile_(false),
+ profile_period_s_(0),
+ profile_duration_s_(0),
+ profile_interval_us_(0),
+ profile_backoff_coefficient_(0),
+ method_trace_(false),
method_trace_file_size_(0),
instrumentation_(),
use_compile_time_class_path_(false),
- main_thread_group_(NULL),
- system_thread_group_(NULL),
- system_class_loader_(NULL) {
+ main_thread_group_(nullptr),
+ system_thread_group_(nullptr),
+ system_class_loader_(nullptr),
+ dump_gc_performance_on_shutdown_(false) {
for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
- callee_save_methods_[i] = NULL;
+ callee_save_methods_[i] = nullptr;
}
}
@@ -141,6 +156,7 @@ Runtime::~Runtime() {
// Make sure all other non-daemon threads have terminated, and all daemon threads are suspended.
delete thread_list_;
delete monitor_list_;
+ delete monitor_pool_;
delete class_linker_;
delete heap_;
delete intern_table_;
@@ -149,8 +165,8 @@ Runtime::~Runtime() {
QuasiAtomic::Shutdown();
verifier::MethodVerifier::Shutdown();
// TODO: acquire a static mutex on Runtime to avoid racing.
- CHECK(instance_ == NULL || instance_ == this);
- instance_ = NULL;
+ CHECK(instance_ == nullptr || instance_ == this);
+ instance_ = nullptr;
}
struct AbortState {
@@ -976,6 +992,7 @@ bool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) {
max_spins_before_thin_lock_inflation_ = options->max_spins_before_thin_lock_inflation_;
monitor_list_ = new MonitorList;
+ monitor_pool_ = MonitorPool::Create();
thread_list_ = new ThreadList;
intern_table_ = new InternTable;
@@ -1345,40 +1362,53 @@ mirror::ObjectArray<mirror::ArtMethod>* Runtime::CreateDefaultImt(ClassLinker* c
mirror::ArtMethod* Runtime::CreateImtConflictMethod() {
Thread* self = Thread::Current();
- Runtime* r = Runtime::Current();
- ClassLinker* cl = r->GetClassLinker();
- SirtRef<mirror::ArtMethod> method(self, cl->AllocArtMethod(self));
+ Runtime* runtime = Runtime::Current();
+ ClassLinker* class_linker = runtime->GetClassLinker();
+ SirtRef<mirror::ArtMethod> method(self, class_linker->AllocArtMethod(self));
method->SetDeclaringClass(mirror::ArtMethod::GetJavaLangReflectArtMethod());
- // TODO: use a special method for imt conflict method saves
+ // TODO: use a special method for imt conflict method saves.
method->SetDexMethodIndex(DexFile::kDexNoIndex);
// When compiling, the code pointer will get set later when the image is loaded.
- method->SetEntryPointFromCompiledCode(r->IsCompiler() ? NULL : GetImtConflictTrampoline(cl));
+ if (runtime->IsCompiler()) {
+ method->SetEntryPointFromPortableCompiledCode(nullptr);
+ method->SetEntryPointFromQuickCompiledCode(nullptr);
+ } else {
+ method->SetEntryPointFromPortableCompiledCode(GetPortableImtConflictTrampoline(class_linker));
+ method->SetEntryPointFromQuickCompiledCode(GetQuickImtConflictTrampoline(class_linker));
+ }
return method.get();
}
mirror::ArtMethod* Runtime::CreateResolutionMethod() {
Thread* self = Thread::Current();
- Runtime* r = Runtime::Current();
- ClassLinker* cl = r->GetClassLinker();
- SirtRef<mirror::ArtMethod> method(self, cl->AllocArtMethod(self));
+ Runtime* runtime = Runtime::Current();
+ ClassLinker* class_linker = runtime->GetClassLinker();
+ SirtRef<mirror::ArtMethod> method(self, class_linker->AllocArtMethod(self));
method->SetDeclaringClass(mirror::ArtMethod::GetJavaLangReflectArtMethod());
// TODO: use a special method for resolution method saves
method->SetDexMethodIndex(DexFile::kDexNoIndex);
// When compiling, the code pointer will get set later when the image is loaded.
- method->SetEntryPointFromCompiledCode(r->IsCompiler() ? NULL : GetResolutionTrampoline(cl));
+ if (runtime->IsCompiler()) {
+ method->SetEntryPointFromPortableCompiledCode(nullptr);
+ method->SetEntryPointFromQuickCompiledCode(nullptr);
+ } else {
+ method->SetEntryPointFromPortableCompiledCode(GetPortableResolutionTrampoline(class_linker));
+ method->SetEntryPointFromQuickCompiledCode(GetQuickResolutionTrampoline(class_linker));
+ }
return method.get();
}
mirror::ArtMethod* Runtime::CreateCalleeSaveMethod(InstructionSet instruction_set,
CalleeSaveType type) {
Thread* self = Thread::Current();
- Runtime* r = Runtime::Current();
- ClassLinker* cl = r->GetClassLinker();
- SirtRef<mirror::ArtMethod> method(self, cl->AllocArtMethod(self));
+ Runtime* runtime = Runtime::Current();
+ ClassLinker* class_linker = runtime->GetClassLinker();
+ SirtRef<mirror::ArtMethod> method(self, class_linker->AllocArtMethod(self));
method->SetDeclaringClass(mirror::ArtMethod::GetJavaLangReflectArtMethod());
// TODO: use a special method for callee saves
method->SetDexMethodIndex(DexFile::kDexNoIndex);
- method->SetEntryPointFromCompiledCode(NULL);
+ method->SetEntryPointFromPortableCompiledCode(nullptr);
+ method->SetEntryPointFromQuickCompiledCode(nullptr);
if ((instruction_set == kThumb2) || (instruction_set == kArm)) {
uint32_t ref_spills = (1 << art::arm::R5) | (1 << art::arm::R6) | (1 << art::arm::R7) |
(1 << art::arm::R8) | (1 << art::arm::R10) | (1 << art::arm::R11);
@@ -1428,8 +1458,23 @@ mirror::ArtMethod* Runtime::CreateCalleeSaveMethod(InstructionSet instruction_se
method->SetFrameSizeInBytes(frame_size);
method->SetCoreSpillMask(core_spills);
method->SetFpSpillMask(0);
+ } else if (instruction_set == kX86_64) {
+ uint32_t ref_spills =
+ (1 << art::x86_64::RBP) | (1 << art::x86_64::RSI) | (1 << art::x86_64::RDI) |
+ (1 << art::x86_64::R8) | (1 << art::x86_64::R9) | (1 << art::x86_64::R10) |
+ (1 << art::x86_64::R11) | (1 << art::x86_64::R12) | (1 << art::x86_64::R13) |
+ (1 << art::x86_64::R14) | (1 << art::x86_64::R15);
+ uint32_t arg_spills =
+ (1 << art::x86_64::RCX) | (1 << art::x86_64::RDX) | (1 << art::x86_64::RBX);
+ uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills : 0) |
+ (1 << art::x86::kNumberOfCpuRegisters); // fake return address callee save
+ size_t frame_size = RoundUp((__builtin_popcount(core_spills) /* gprs */ +
+ 1 /* Method* */) * kPointerSize, kStackAlignment);
+ method->SetFrameSizeInBytes(frame_size);
+ method->SetCoreSpillMask(core_spills);
+ method->SetFpSpillMask(0);
} else {
- UNIMPLEMENTED(FATAL);
+ UNIMPLEMENTED(FATAL) << instruction_set;
}
return method.get();
}
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 9d48631..557ba2c 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -61,6 +61,7 @@ class DexFile;
class InternTable;
struct JavaVMExt;
class MonitorList;
+class MonitorPool;
class SignalCatcher;
class ThreadList;
class Trace;
@@ -314,6 +315,10 @@ class Runtime {
return monitor_list_;
}
+ MonitorPool* GetMonitorPool() const {
+ return monitor_pool_;
+ }
+
mirror::Throwable* GetPreAllocatedOutOfMemoryError() const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -524,6 +529,7 @@ class Runtime {
// The number of spins that are done before thread suspension is used to forcibly inflate.
size_t max_spins_before_thin_lock_inflation_;
MonitorList* monitor_list_;
+ MonitorPool* monitor_pool_;
ThreadList* thread_list_;
diff --git a/runtime/runtime_linux.cc b/runtime/runtime_linux.cc
index 47b72e9..d8f408a 100644
--- a/runtime/runtime_linux.cc
+++ b/runtime/runtime_linux.cc
@@ -133,7 +133,7 @@ struct UContext {
void Dump(std::ostream& os) {
// TODO: support non-x86 hosts (not urgent because this code doesn't run on targets).
-#if defined(__APPLE__)
+#if defined(__APPLE__) && defined(__i386__)
DumpRegister32(os, "eax", context->__ss.__eax);
DumpRegister32(os, "ebx", context->__ss.__ebx);
DumpRegister32(os, "ecx", context->__ss.__ecx);
@@ -159,7 +159,7 @@ struct UContext {
os << '\n';
DumpRegister32(os, "gs", context->__ss.__gs);
DumpRegister32(os, "ss", context->__ss.__ss);
-#else
+#elif defined(__linux__) && defined(__i386__)
DumpRegister32(os, "eax", context.gregs[REG_EAX]);
DumpRegister32(os, "ebx", context.gregs[REG_EBX]);
DumpRegister32(os, "ecx", context.gregs[REG_ECX]);
@@ -185,6 +185,8 @@ struct UContext {
os << '\n';
DumpRegister32(os, "gs", context.gregs[REG_GS]);
DumpRegister32(os, "ss", context.gregs[REG_SS]);
+#else
+ os << "Unknown architecture/word size/OS in ucontext dump";
#endif
}
diff --git a/runtime/sirt_ref.h b/runtime/sirt_ref.h
index 56d81ec..3c5e4f8 100644
--- a/runtime/sirt_ref.h
+++ b/runtime/sirt_ref.h
@@ -35,13 +35,17 @@ class SirtRef {
DCHECK_EQ(top_sirt, &sirt_);
}
- T& operator*() const { return *get(); }
- T* operator->() const { return get(); }
- T* get() const {
+ T& operator*() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return *get();
+ }
+ T* operator->() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return get();
+ }
+ T* get() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return down_cast<T*>(sirt_.GetReference(0));
}
- void reset(T* object = NULL) {
+ void reset(T* object = nullptr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
sirt_.SetReference(0, object);
}
diff --git a/runtime/stack.cc b/runtime/stack.cc
index e583ced..fd7d981 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -75,7 +75,7 @@ size_t ManagedStack::NumJniShadowFrameReferences() const {
return count;
}
-bool ManagedStack::ShadowFramesContain(mirror::Object** shadow_frame_entry) const {
+bool ManagedStack::ShadowFramesContain(StackReference<mirror::Object>* shadow_frame_entry) const {
for (const ManagedStack* current_fragment = this; current_fragment != NULL;
current_fragment = current_fragment->GetLink()) {
for (ShadowFrame* current_frame = current_fragment->top_shadow_frame_; current_frame != NULL;
@@ -251,7 +251,7 @@ std::string StackVisitor::DescribeLocation() const {
return "upcall";
}
result += PrettyMethod(m);
- result += StringPrintf("' at dex PC 0x%04zx", GetDexPc());
+ result += StringPrintf("' at dex PC 0x%04x", GetDexPc());
if (!IsShadowFrame()) {
result += StringPrintf(" (native PC %p)", reinterpret_cast<void*>(GetCurrentQuickFramePc()));
}
@@ -264,23 +264,23 @@ instrumentation::InstrumentationStackFrame& StackVisitor::GetInstrumentationStac
}
void StackVisitor::SanityCheckFrame() const {
-#ifndef NDEBUG
- mirror::ArtMethod* method = GetMethod();
- CHECK(method->GetClass() == mirror::ArtMethod::GetJavaLangReflectArtMethod());
- if (cur_quick_frame_ != NULL) {
- method->AssertPcIsWithinCode(cur_quick_frame_pc_);
- // Frame sanity.
- size_t frame_size = method->GetFrameSizeInBytes();
- CHECK_NE(frame_size, 0u);
- // A rough guess at an upper size we expect to see for a frame. The 256 is
- // a dex register limit. The 16 incorporates callee save spills and
- // outgoing argument set up.
- const size_t kMaxExpectedFrameSize = 256 * sizeof(word) + 16;
- CHECK_LE(frame_size, kMaxExpectedFrameSize);
- size_t return_pc_offset = method->GetReturnPcOffsetInBytes();
- CHECK_LT(return_pc_offset, frame_size);
+ if (kIsDebugBuild) {
+ mirror::ArtMethod* method = GetMethod();
+ CHECK(method->GetClass() == mirror::ArtMethod::GetJavaLangReflectArtMethod());
+ if (cur_quick_frame_ != nullptr) {
+ method->AssertPcIsWithinQuickCode(cur_quick_frame_pc_);
+ // Frame sanity.
+ size_t frame_size = method->GetFrameSizeInBytes();
+ CHECK_NE(frame_size, 0u);
+ // A rough guess at an upper size we expect to see for a frame. The 256 is
+ // a dex register limit. The 16 incorporates callee save spills and
+ // outgoing argument set up.
+ const size_t kMaxExpectedFrameSize = 256 * sizeof(word) + 16;
+ CHECK_LE(frame_size, kMaxExpectedFrameSize);
+ size_t return_pc_offset = method->GetReturnPcOffsetInBytes();
+ CHECK_LT(return_pc_offset, frame_size);
+ }
}
-#endif
}
void StackVisitor::WalkStack(bool include_transitions) {
diff --git a/runtime/stack.h b/runtime/stack.h
index 0692390..8466069 100644
--- a/runtime/stack.h
+++ b/runtime/stack.h
@@ -19,8 +19,10 @@
#include "dex_file.h"
#include "instrumentation.h"
+#include "base/casts.h"
#include "base/macros.h"
#include "arch/context.h"
+#include "mirror/object_reference.h"
#include <stdint.h>
#include <string>
@@ -96,16 +98,33 @@ enum VRegBaseRegNum : int {
kVRegNonSpecialTempBaseReg = -3,
};
+// A reference from the shadow stack to a MirrorType object within the Java heap.
+template<class MirrorType>
+class MANAGED StackReference : public mirror::ObjectReference<false, MirrorType> {
+ public:
+ StackReference<MirrorType>() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : mirror::ObjectReference<false, MirrorType>(nullptr) {}
+
+ static StackReference<MirrorType> FromMirrorPtr(MirrorType* p)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return StackReference<MirrorType>(p);
+ }
+
+ private:
+ StackReference<MirrorType>(MirrorType* p) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : mirror::ObjectReference<false, MirrorType>(p) {}
+};
+
// ShadowFrame has 3 possible layouts:
// - portable - a unified array of VRegs and references. Precise references need GC maps.
// - interpreter - separate VRegs and reference arrays. References are in the reference array.
// - JNI - just VRegs, but where every VReg holds a reference.
class ShadowFrame {
public:
- // Compute size of ShadowFrame in bytes.
+ // Compute size of ShadowFrame in bytes assuming it has a reference array.
static size_t ComputeSize(uint32_t num_vregs) {
return sizeof(ShadowFrame) + (sizeof(uint32_t) * num_vregs) +
- (sizeof(mirror::Object*) * num_vregs);
+ (sizeof(StackReference<mirror::Object>) * num_vregs);
}
// Create ShadowFrame in heap for deoptimization.
@@ -195,22 +214,19 @@ class ShadowFrame {
}
template <bool kChecked = false>
- mirror::Object* GetVRegReference(size_t i) const {
+ mirror::Object* GetVRegReference(size_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK_LT(i, NumberOfVRegs());
if (HasReferenceArray()) {
- mirror::Object* ref = References()[i];
+ mirror::Object* ref = References()[i].AsMirrorPtr();
if (kChecked) {
CHECK(VerifyReference(ref)) << "VReg " << i << "(" << ref
<< ") is in protected space, reference array " << true;
}
- // If the vreg reference is not equal to the vreg then the vreg reference is stale.
- if (UNLIKELY(reinterpret_cast<uint32_t>(ref) != vregs_[i])) {
- return nullptr;
- }
return ref;
} else {
- const uint32_t* vreg = &vregs_[i];
- mirror::Object* ref = *reinterpret_cast<mirror::Object* const*>(vreg);
+ const uint32_t* vreg_ptr = &vregs_[i];
+ mirror::Object* ref =
+ reinterpret_cast<const StackReference<mirror::Object>*>(vreg_ptr)->AsMirrorPtr();
if (kChecked) {
CHECK(VerifyReference(ref)) << "VReg " << i
<< "(" << ref << ") is in protected space, reference array " << false;
@@ -231,7 +247,7 @@ class ShadowFrame {
// This is needed for moving collectors since these can update the vreg references if they
// happen to agree with references in the reference array.
if (kMovingCollector && HasReferenceArray()) {
- References()[i] = nullptr;
+ References()[i].Clear();
}
}
@@ -242,7 +258,7 @@ class ShadowFrame {
// This is needed for moving collectors since these can update the vreg references if they
// happen to agree with references in the reference array.
if (kMovingCollector && HasReferenceArray()) {
- References()[i] = nullptr;
+ References()[i].Clear();
}
}
@@ -255,8 +271,8 @@ class ShadowFrame {
// This is needed for moving collectors since these can update the vreg references if they
// happen to agree with references in the reference array.
if (kMovingCollector && HasReferenceArray()) {
- References()[i] = nullptr;
- References()[i + 1] = nullptr;
+ References()[i].Clear();
+ References()[i + 1].Clear();
}
}
@@ -269,24 +285,24 @@ class ShadowFrame {
// This is needed for moving collectors since these can update the vreg references if they
// happen to agree with references in the reference array.
if (kMovingCollector && HasReferenceArray()) {
- References()[i] = nullptr;
- References()[i + 1] = nullptr;
+ References()[i].Clear();
+ References()[i + 1].Clear();
}
}
- void SetVRegReference(size_t i, mirror::Object* val) {
+ void SetVRegReference(size_t i, mirror::Object* val) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK_LT(i, NumberOfVRegs());
DCHECK(!kMovingCollector || VerifyReference(val))
<< "VReg " << i << "(" << val << ") is in protected space";
uint32_t* vreg = &vregs_[i];
- *reinterpret_cast<mirror::Object**>(vreg) = val;
+ reinterpret_cast<StackReference<mirror::Object>*>(vreg)->Assign(val);
if (HasReferenceArray()) {
- References()[i] = val;
+ References()[i].Assign(val);
}
}
- mirror::ArtMethod* GetMethod() const {
- DCHECK_NE(method_, static_cast<void*>(NULL));
+ mirror::ArtMethod* GetMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(method_ != nullptr);
return method_;
}
@@ -298,7 +314,7 @@ class ShadowFrame {
void SetMethod(mirror::ArtMethod* method) {
#if defined(ART_USE_PORTABLE_COMPILER)
- DCHECK_NE(method, static_cast<void*>(NULL));
+ DCHECK(method != nullptr);
method_ = method;
#else
UNUSED(method);
@@ -306,7 +322,7 @@ class ShadowFrame {
#endif
}
- bool Contains(mirror::Object** shadow_frame_entry_obj) const {
+ bool Contains(StackReference<mirror::Object>* shadow_frame_entry_obj) const {
if (HasReferenceArray()) {
return ((&References()[0] <= shadow_frame_entry_obj) &&
(shadow_frame_entry_obj <= (&References()[NumberOfVRegs() - 1])));
@@ -346,22 +362,22 @@ class ShadowFrame {
CHECK_LT(num_vregs, static_cast<uint32_t>(kHasReferenceArray));
number_of_vregs_ |= kHasReferenceArray;
#endif
- memset(vregs_, 0, num_vregs * (sizeof(uint32_t) + sizeof(mirror::Object*)));
+ memset(vregs_, 0, num_vregs * (sizeof(uint32_t) + sizeof(StackReference<mirror::Object>)));
} else {
memset(vregs_, 0, num_vregs * sizeof(uint32_t));
}
}
- mirror::Object* const* References() const {
+ const StackReference<mirror::Object>* References() const {
DCHECK(HasReferenceArray());
const uint32_t* vreg_end = &vregs_[NumberOfVRegs()];
- return reinterpret_cast<mirror::Object* const*>(vreg_end);
+ return reinterpret_cast<const StackReference<mirror::Object>*>(vreg_end);
}
bool VerifyReference(const mirror::Object* val) const;
- mirror::Object** References() {
- return const_cast<mirror::Object**>(const_cast<const ShadowFrame*>(this)->References());
+ StackReference<mirror::Object>* References() {
+ return const_cast<StackReference<mirror::Object>*>(const_cast<const ShadowFrame*>(this)->References());
}
#if defined(ART_USE_PORTABLE_COMPILER)
@@ -470,9 +486,9 @@ class PACKED(4) ManagedStack {
return OFFSETOF_MEMBER(ManagedStack, top_shadow_frame_);
}
- size_t NumJniShadowFrameReferences() const;
+ size_t NumJniShadowFrameReferences() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool ShadowFramesContain(mirror::Object** shadow_frame_entry) const;
+ bool ShadowFramesContain(StackReference<mirror::Object>* shadow_frame_entry) const;
private:
ManagedStack* link_;
@@ -494,18 +510,18 @@ class StackVisitor {
void WalkStack(bool include_transitions = false)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- mirror::ArtMethod* GetMethod() const {
- if (cur_shadow_frame_ != NULL) {
+ mirror::ArtMethod* GetMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ if (cur_shadow_frame_ != nullptr) {
return cur_shadow_frame_->GetMethod();
- } else if (cur_quick_frame_ != NULL) {
+ } else if (cur_quick_frame_ != nullptr) {
return *cur_quick_frame_;
} else {
- return NULL;
+ return nullptr;
}
}
bool IsShadowFrame() const {
- return cur_shadow_frame_ != NULL;
+ return cur_shadow_frame_ != nullptr;
}
uint32_t GetDexPc() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -514,9 +530,10 @@ class StackVisitor {
size_t GetNativePcOffset() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- uintptr_t* CalleeSaveAddress(int num, size_t frame_size) const {
+ uintptr_t* CalleeSaveAddress(int num, size_t frame_size) const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Callee saves are held at the top of the frame
- DCHECK(GetMethod() != NULL);
+ DCHECK(GetMethod() != nullptr);
byte* save_addr =
reinterpret_cast<byte*>(cur_quick_frame_) + frame_size - ((num + 1) * kPointerSize);
#if defined(__i386__)
@@ -553,17 +570,17 @@ class StackVisitor {
// This is a fast-path for getting/setting values in a quick frame.
uint32_t* GetVRegAddr(mirror::ArtMethod** cur_quick_frame, const DexFile::CodeItem* code_item,
- uint32_t core_spills, uint32_t fp_spills, size_t frame_size,
- uint16_t vreg) const {
+ uint32_t core_spills, uint32_t fp_spills, size_t frame_size,
+ uint16_t vreg) const {
int offset = GetVRegOffset(code_item, core_spills, fp_spills, frame_size, vreg);
DCHECK_EQ(cur_quick_frame, GetCurrentQuickFrame());
byte* vreg_addr = reinterpret_cast<byte*>(cur_quick_frame) + offset;
return reinterpret_cast<uint32_t*>(vreg_addr);
}
- uintptr_t GetReturnPc() const;
+ uintptr_t GetReturnPc() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetReturnPc(uintptr_t new_ret_pc);
+ void SetReturnPc(uintptr_t new_ret_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
/*
* Return sp-relative offset for a Dalvik virtual register, compiler
diff --git a/runtime/stack_indirect_reference_table.h b/runtime/stack_indirect_reference_table.h
index 4c9b038..d22650b 100644
--- a/runtime/stack_indirect_reference_table.h
+++ b/runtime/stack_indirect_reference_table.h
@@ -19,6 +19,7 @@
#include "base/logging.h"
#include "base/macros.h"
+#include "stack.h"
namespace art {
namespace mirror {
@@ -33,7 +34,7 @@ class StackIndirectReferenceTable {
public:
explicit StackIndirectReferenceTable(mirror::Object* object) :
number_of_references_(1), link_(NULL) {
- references_[0] = object;
+ references_[0].Assign(object);
}
~StackIndirectReferenceTable() {}
@@ -53,17 +54,17 @@ class StackIndirectReferenceTable {
link_ = sirt;
}
- mirror::Object* GetReference(size_t i) const {
+ mirror::Object* GetReference(size_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK_LT(i, number_of_references_);
- return references_[i];
+ return references_[i].AsMirrorPtr();
}
- void SetReference(size_t i, mirror::Object* object) {
+ void SetReference(size_t i, mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK_LT(i, number_of_references_);
- references_[i] = object;
+ references_[i].Assign(object);
}
- bool Contains(mirror::Object** sirt_entry) const {
+ bool Contains(StackReference<mirror::Object>* sirt_entry) const {
// A SIRT should always contain something. One created by the
// jni_compiler should have a jobject/jclass as a native method is
// passed in a this pointer or a class
@@ -89,7 +90,7 @@ class StackIndirectReferenceTable {
StackIndirectReferenceTable* link_;
// number_of_references_ are available if this is allocated and filled in by jni_compiler.
- mirror::Object* references_[1];
+ StackReference<mirror::Object> references_[1];
DISALLOW_COPY_AND_ASSIGN(StackIndirectReferenceTable);
};
diff --git a/runtime/thread.cc b/runtime/thread.cc
index c3ef228..c649765 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -178,7 +178,7 @@ void* Thread::CreateCallback(void* arg) {
receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(soa.DecodeMethod(mid));
JValue result;
ArgArray arg_array(nullptr, 0);
- arg_array.Append(reinterpret_cast<uint32_t>(receiver));
+ arg_array.Append(receiver);
m->Invoke(self, arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'V');
}
// Detach and delete self.
@@ -190,7 +190,7 @@ void* Thread::CreateCallback(void* arg) {
Thread* Thread::FromManagedThread(const ScopedObjectAccessUnchecked& soa,
mirror::Object* thread_peer) {
mirror::ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_nativePeer);
- Thread* result = reinterpret_cast<Thread*>(static_cast<uintptr_t>(f->GetInt(thread_peer)));
+ Thread* result = reinterpret_cast<Thread*>(static_cast<uintptr_t>(f->GetLong(thread_peer)));
// Sanity check that if we have a result it is either suspended or we hold the thread_list_lock_
// to stop it from going away.
if (kIsDebugBuild) {
@@ -260,8 +260,8 @@ void Thread::CreateNativeThread(JNIEnv* env, jobject java_peer, size_t stack_siz
// Thread.start is synchronized, so we know that nativePeer is 0, and know that we're not racing to
// assign it.
- env->SetIntField(java_peer, WellKnownClasses::java_lang_Thread_nativePeer,
- reinterpret_cast<jint>(child_thread));
+ env->SetLongField(java_peer, WellKnownClasses::java_lang_Thread_nativePeer,
+ reinterpret_cast<jlong>(child_thread));
pthread_t new_pthread;
pthread_attr_t attr;
@@ -283,7 +283,7 @@ void Thread::CreateNativeThread(JNIEnv* env, jobject java_peer, size_t stack_siz
delete child_thread;
child_thread = nullptr;
// TODO: remove from thread group?
- env->SetIntField(java_peer, WellKnownClasses::java_lang_Thread_nativePeer, 0);
+ env->SetLongField(java_peer, WellKnownClasses::java_lang_Thread_nativePeer, 0);
{
std::string msg(StringPrintf("pthread_create (%s stack) failed: %s",
PrettySize(stack_size).c_str(), strerror(pthread_create_result)));
@@ -388,8 +388,8 @@ void Thread::CreatePeer(const char* name, bool as_daemon, jobject thread_group)
Thread* self = this;
DCHECK_EQ(self, Thread::Current());
- jni_env_->SetIntField(peer.get(), WellKnownClasses::java_lang_Thread_nativePeer,
- reinterpret_cast<jint>(self));
+ jni_env_->SetLongField(peer.get(), WellKnownClasses::java_lang_Thread_nativePeer,
+ reinterpret_cast<jlong>(self));
ScopedObjectAccess soa(self);
SirtRef<mirror::String> peer_thread_name(soa.Self(), GetThreadName(soa));
@@ -767,7 +767,7 @@ struct StackDumpVisitor : public StackVisitor {
}
const int kMaxRepetition = 3;
mirror::Class* c = m->GetDeclaringClass();
- const mirror::DexCache* dex_cache = c->GetDexCache();
+ mirror::DexCache* dex_cache = c->GetDexCache();
int line_number = -1;
if (dex_cache != nullptr) { // be tolerant of bad input
const DexFile& dex_file = *dex_cache->GetDexFile();
@@ -1017,7 +1017,7 @@ void Thread::Destroy() {
RemoveFromThreadGroup(soa);
// this.nativePeer = 0;
- soa.DecodeField(WellKnownClasses::java_lang_Thread_nativePeer)->SetInt(opeer_, 0);
+ soa.DecodeField(WellKnownClasses::java_lang_Thread_nativePeer)->SetLong(opeer_, 0);
Dbg::PostThreadDeath(self);
// Thread.join() is implemented as an Object.wait() on the Thread.lock object. Signal anyone
@@ -1133,7 +1133,8 @@ size_t Thread::NumSirtReferences() {
}
bool Thread::SirtContains(jobject obj) const {
- mirror::Object** sirt_entry = reinterpret_cast<mirror::Object**>(obj);
+ StackReference<mirror::Object>* sirt_entry =
+ reinterpret_cast<StackReference<mirror::Object>*>(obj);
for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->GetLink()) {
if (cur->Contains(sirt_entry)) {
return true;
@@ -1172,10 +1173,11 @@ mirror::Object* Thread::DecodeJObject(jobject obj) const {
IndirectReferenceTable& locals = jni_env_->locals;
result = const_cast<mirror::Object*>(locals.Get(ref));
} else if (kind == kSirtOrInvalid) {
- // TODO: make stack indirect reference table lookup more efficient
- // Check if this is a local reference in the SIRT
+ // TODO: make stack indirect reference table lookup more efficient.
+ // Check if this is a local reference in the SIRT.
if (LIKELY(SirtContains(obj))) {
- result = *reinterpret_cast<mirror::Object**>(obj); // Read from SIRT
+ // Read from SIRT.
+ result = reinterpret_cast<StackReference<mirror::Object>*>(obj)->AsMirrorPtr();
} else if (Runtime::Current()->GetJavaVM()->work_around_app_jni_bugs) {
// Assume an invalid local reference is actually a direct pointer.
result = reinterpret_cast<mirror::Object*>(obj);
@@ -1569,12 +1571,12 @@ void Thread::ThrowNewWrappedException(const ThrowLocation& throw_location,
SetException(gc_safe_throw_location, exception.get());
} else {
ArgArray args("VLL", 3);
- args.Append(reinterpret_cast<uint32_t>(exception.get()));
+ args.Append(exception.get());
if (msg != nullptr) {
- args.Append(reinterpret_cast<uint32_t>(msg_string.get()));
+ args.Append(msg_string.get());
}
if (cause.get() != nullptr) {
- args.Append(reinterpret_cast<uint32_t>(cause.get()));
+ args.Append(cause.get());
}
JValue result;
exception_init_method->Invoke(this, args.GetArray(), args.GetNumBytes(), &result, 'V');
@@ -1920,13 +1922,13 @@ class ReferenceMapVisitor : public StackVisitor {
}
}
} else {
- uint32_t* reg_addr =
- GetVRegAddr(cur_quick_frame, code_item, core_spills, fp_spills, frame_size, reg);
+ uintptr_t* reg_addr = reinterpret_cast<uintptr_t*>(
+ GetVRegAddr(cur_quick_frame, code_item, core_spills, fp_spills, frame_size, reg));
mirror::Object* ref = reinterpret_cast<mirror::Object*>(*reg_addr);
if (ref != nullptr) {
mirror::Object* new_ref = visitor_(ref, reg, this);
if (ref != new_ref) {
- *reg_addr = reinterpret_cast<uint32_t>(new_ref);
+ *reg_addr = reinterpret_cast<uintptr_t>(new_ref);
}
}
}
diff --git a/runtime/thread.h b/runtime/thread.h
index 4a37ca0..b7f8bb0 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -487,23 +487,23 @@ class PACKED(4) Thread {
ManagedStack::TopShadowFrameOffset());
}
- // Number of references allocated in JNI ShadowFrames on this thread
- size_t NumJniShadowFrameReferences() const {
+ // Number of references allocated in JNI ShadowFrames on this thread.
+ size_t NumJniShadowFrameReferences() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return managed_stack_.NumJniShadowFrameReferences();
}
- // Number of references in SIRTs on this thread
+ // Number of references in SIRTs on this thread.
size_t NumSirtReferences();
- // Number of references allocated in SIRTs & JNI shadow frames on this thread
- size_t NumStackReferences() {
+ // Number of references allocated in SIRTs & JNI shadow frames on this thread.
+ size_t NumStackReferences() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return NumSirtReferences() + NumJniShadowFrameReferences();
};
// Is the given obj in this thread's stack indirect reference table?
bool SirtContains(jobject obj) const;
- void SirtVisitRoots(RootVisitor* visitor, void* arg);
+ void SirtVisitRoots(RootVisitor* visitor, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void PushSirt(StackIndirectReferenceTable* sirt) {
sirt->SetLink(top_sirt_);
@@ -788,7 +788,7 @@ class PACKED(4) Thread {
// A positive value implies we're in a region where thread suspension isn't expected.
uint32_t no_thread_suspension_;
- // Cause for last suspension.
+ // If no_thread_suspension_ is > 0, what is causing that assertion.
const char* last_no_thread_suspension_cause_;
// Maximum number of checkpoint functions.
diff --git a/runtime/thread_pool.cc b/runtime/thread_pool.cc
index aca0561..e8c9ff8 100644
--- a/runtime/thread_pool.cc
+++ b/runtime/thread_pool.cc
@@ -31,7 +31,7 @@ ThreadPoolWorker::ThreadPoolWorker(ThreadPool* thread_pool, const std::string& n
name_(name) {
std::string error_msg;
stack_.reset(MemMap::MapAnonymous(name.c_str(), nullptr, stack_size, PROT_READ | PROT_WRITE,
- &error_msg));
+ false, &error_msg));
CHECK(stack_.get() != nullptr) << error_msg;
const char* reason = "new thread pool worker thread";
pthread_attr_t attr;
diff --git a/runtime/thread_pool_test.cc b/runtime/thread_pool_test.cc
index 2029d4b..c6f0e92 100644
--- a/runtime/thread_pool_test.cc
+++ b/runtime/thread_pool_test.cc
@@ -17,7 +17,7 @@
#include <string>
-#include "atomic_integer.h"
+#include "atomic.h"
#include "common_test.h"
#include "thread_pool.h"
diff --git a/runtime/trace.cc b/runtime/trace.cc
index b0f6e37..18185d4 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -89,7 +89,7 @@ class BuildStackTraceVisitor : public StackVisitor {
explicit BuildStackTraceVisitor(Thread* thread) : StackVisitor(thread, NULL),
method_trace_(Trace::AllocStackTrace()) {}
- bool VisitFrame() {
+ bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtMethod* m = GetMethod();
// Ignore runtime frames (in particular callee save).
if (!m->IsRuntimeMethod()) {
@@ -133,9 +133,9 @@ static TraceAction DecodeTraceAction(uint32_t tmid) {
return static_cast<TraceAction>(tmid & kTraceMethodActionMask);
}
-static uint32_t EncodeTraceMethodAndAction(const mirror::ArtMethod* method,
+static uint32_t EncodeTraceMethodAndAction(mirror::ArtMethod* method,
TraceAction action) {
- uint32_t tmid = reinterpret_cast<uint32_t>(method) | action;
+ uint32_t tmid = PointerToLowMemUInt32(method) | action;
DCHECK_EQ(method, DecodeTraceMethodId(tmid));
return tmid;
}
@@ -298,7 +298,7 @@ void Trace::CompareAndUpdateStackTrace(Thread* thread,
void* Trace::RunSamplingThread(void* arg) {
Runtime* runtime = Runtime::Current();
- int interval_us = reinterpret_cast<int>(arg);
+ intptr_t interval_us = reinterpret_cast<intptr_t>(arg);
CHECK_GE(interval_us, 0);
CHECK(runtime->AttachCurrentThread("Sampling Profiler", true, runtime->GetSystemThreadGroup(),
!runtime->IsCompiler()));
@@ -508,7 +508,7 @@ void Trace::FinishTracing() {
} else {
os << StringPrintf("clock=wall\n");
}
- os << StringPrintf("elapsed-time-usec=%llu\n", elapsed);
+ os << StringPrintf("elapsed-time-usec=%" PRIu64 "\n", elapsed);
size_t num_records = (final_offset - kTraceHeaderLength) / GetRecordSize(clock_source_);
os << StringPrintf("num-method-calls=%zd\n", num_records);
os << StringPrintf("clock-call-overhead-nsec=%d\n", clock_overhead_ns);
@@ -548,13 +548,13 @@ void Trace::FinishTracing() {
}
void Trace::DexPcMoved(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t new_dex_pc) {
+ mirror::ArtMethod* method, uint32_t new_dex_pc) {
// We're not recorded to listen to this kind of event, so complain.
LOG(ERROR) << "Unexpected dex PC event in tracing " << PrettyMethod(method) << " " << new_dex_pc;
};
void Trace::MethodEntered(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc) {
+ mirror::ArtMethod* method, uint32_t dex_pc) {
uint32_t thread_clock_diff = 0;
uint32_t wall_clock_diff = 0;
ReadClocks(thread, &thread_clock_diff, &wall_clock_diff);
@@ -563,7 +563,7 @@ void Trace::MethodEntered(Thread* thread, mirror::Object* this_object,
}
void Trace::MethodExited(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc,
+ mirror::ArtMethod* method, uint32_t dex_pc,
const JValue& return_value) {
UNUSED(return_value);
uint32_t thread_clock_diff = 0;
@@ -574,7 +574,7 @@ void Trace::MethodExited(Thread* thread, mirror::Object* this_object,
}
void Trace::MethodUnwind(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc) {
+ mirror::ArtMethod* method, uint32_t dex_pc) {
uint32_t thread_clock_diff = 0;
uint32_t wall_clock_diff = 0;
ReadClocks(thread, &thread_clock_diff, &wall_clock_diff);
@@ -605,7 +605,7 @@ void Trace::ReadClocks(Thread* thread, uint32_t* thread_clock_diff, uint32_t* wa
}
}
-void Trace::LogMethodTraceEvent(Thread* thread, const mirror::ArtMethod* method,
+void Trace::LogMethodTraceEvent(Thread* thread, mirror::ArtMethod* method,
instrumentation::Instrumentation::InstrumentationEvent event,
uint32_t thread_clock_diff, uint32_t wall_clock_diff) {
// Advance cur_offset_ atomically.
diff --git a/runtime/trace.h b/runtime/trace.h
index 9be015a..d810df0 100644
--- a/runtime/trace.h
+++ b/runtime/trace.h
@@ -73,17 +73,17 @@ class Trace : public instrumentation::InstrumentationListener {
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
virtual void MethodEntered(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc)
+ mirror::ArtMethod* method, uint32_t dex_pc)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
virtual void MethodExited(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc,
+ mirror::ArtMethod* method, uint32_t dex_pc,
const JValue& return_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
virtual void MethodUnwind(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t dex_pc)
+ mirror::ArtMethod* method, uint32_t dex_pc)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
virtual void DexPcMoved(Thread* thread, mirror::Object* this_object,
- const mirror::ArtMethod* method, uint32_t new_dex_pc)
+ mirror::ArtMethod* method, uint32_t new_dex_pc)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
virtual void ExceptionCaught(Thread* thread, const ThrowLocation& throw_location,
mirror::ArtMethod* catch_method, uint32_t catch_dex_pc,
@@ -105,7 +105,7 @@ class Trace : public instrumentation::InstrumentationListener {
void ReadClocks(Thread* thread, uint32_t* thread_clock_diff, uint32_t* wall_clock_diff);
- void LogMethodTraceEvent(Thread* thread, const mirror::ArtMethod* method,
+ void LogMethodTraceEvent(Thread* thread, mirror::ArtMethod* method,
instrumentation::Instrumentation::InstrumentationEvent event,
uint32_t thread_clock_diff, uint32_t wall_clock_diff);
diff --git a/runtime/utf.cc b/runtime/utf.cc
index 5ec2ea1..e48d6d2 100644
--- a/runtime/utf.cc
+++ b/runtime/utf.cc
@@ -68,7 +68,7 @@ void ConvertUtf16ToModifiedUtf8(char* utf8_out, const uint16_t* utf16_in, size_t
}
}
-int32_t ComputeUtf16Hash(const mirror::CharArray* chars, int32_t offset,
+int32_t ComputeUtf16Hash(mirror::CharArray* chars, int32_t offset,
size_t char_count) {
int32_t hash = 0;
for (size_t i = 0; i < char_count; i++) {
diff --git a/runtime/utf.h b/runtime/utf.h
index cc5e6d4..5b2289e 100644
--- a/runtime/utf.h
+++ b/runtime/utf.h
@@ -73,7 +73,7 @@ void ConvertUtf16ToModifiedUtf8(char* utf8_out, const uint16_t* utf16_in, size_t
/*
* The java.lang.String hashCode() algorithm.
*/
-int32_t ComputeUtf16Hash(const mirror::CharArray* chars, int32_t offset, size_t char_count)
+int32_t ComputeUtf16Hash(mirror::CharArray* chars, int32_t offset, size_t char_count)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
int32_t ComputeUtf16Hash(const uint16_t* chars, size_t char_count);
diff --git a/runtime/utils.cc b/runtime/utils.cc
index a293043..aad21bc 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -215,14 +215,14 @@ void InitTimeSpec(bool absolute, int clock, int64_t ms, int32_t ns, timespec* ts
}
}
-std::string PrettyDescriptor(const mirror::String* java_descriptor) {
+std::string PrettyDescriptor(mirror::String* java_descriptor) {
if (java_descriptor == NULL) {
return "null";
}
return PrettyDescriptor(java_descriptor->ToModifiedUtf8());
}
-std::string PrettyDescriptor(const mirror::Class* klass) {
+std::string PrettyDescriptor(mirror::Class* klass) {
if (klass == NULL) {
return "null";
}
@@ -283,7 +283,7 @@ std::string PrettyDescriptor(Primitive::Type type) {
return PrettyDescriptor(descriptor_string);
}
-std::string PrettyField(const mirror::ArtField* f, bool with_type) {
+std::string PrettyField(mirror::ArtField* f, bool with_type) {
if (f == NULL) {
return "null";
}
@@ -358,7 +358,7 @@ std::string PrettyReturnType(const char* signature) {
return PrettyDescriptor(return_type);
}
-std::string PrettyMethod(const mirror::ArtMethod* m, bool with_signature) {
+std::string PrettyMethod(mirror::ArtMethod* m, bool with_signature) {
if (m == nullptr) {
return "null";
}
@@ -401,7 +401,7 @@ std::string PrettyMethod(uint32_t method_idx, const DexFile& dex_file, bool with
return result;
}
-std::string PrettyTypeOf(const mirror::Object* obj) {
+std::string PrettyTypeOf(mirror::Object* obj) {
if (obj == NULL) {
return "null";
}
@@ -417,7 +417,7 @@ std::string PrettyTypeOf(const mirror::Object* obj) {
return result;
}
-std::string PrettyClass(const mirror::Class* c) {
+std::string PrettyClass(mirror::Class* c) {
if (c == NULL) {
return "null";
}
@@ -428,7 +428,7 @@ std::string PrettyClass(const mirror::Class* c) {
return result;
}
-std::string PrettyClassAndClassLoader(const mirror::Class* c) {
+std::string PrettyClassAndClassLoader(mirror::Class* c) {
if (c == NULL) {
return "null";
}
@@ -445,7 +445,7 @@ std::string PrettyClassAndClassLoader(const mirror::Class* c) {
std::string PrettySize(int64_t byte_count) {
// The byte thresholds at which we display amounts. A byte count is displayed
// in unit U when kUnitThresholds[U] <= bytes < kUnitThresholds[U+1].
- static const size_t kUnitThresholds[] = {
+ static const int64_t kUnitThresholds[] = {
0, // B up to...
3*1024, // KB up to...
2*1024*1024, // MB up to...
@@ -464,7 +464,7 @@ std::string PrettySize(int64_t byte_count) {
break;
}
}
- return StringPrintf("%s%lld%s", negative_str, byte_count / kBytesPerUnit[i], kUnitStrings[i]);
+ return StringPrintf("%s%" PRId64 "%s", negative_str, byte_count / kBytesPerUnit[i], kUnitStrings[i]);
}
std::string PrettyDuration(uint64_t nano_duration) {
@@ -534,18 +534,18 @@ std::string FormatDuration(uint64_t nano_duration, TimeUnit time_unit) {
uint64_t whole_part = nano_duration / divisor;
uint64_t fractional_part = nano_duration % divisor;
if (fractional_part == 0) {
- return StringPrintf("%llu%s", whole_part, unit);
+ return StringPrintf("%" PRIu64 "%s", whole_part, unit);
} else {
while ((fractional_part % 1000) == 0) {
zero_fill -= 3;
fractional_part /= 1000;
}
if (zero_fill == 3) {
- return StringPrintf("%llu.%03llu%s", whole_part, fractional_part, unit);
+ return StringPrintf("%" PRIu64 ".%03" PRIu64 "%s", whole_part, fractional_part, unit);
} else if (zero_fill == 6) {
- return StringPrintf("%llu.%06llu%s", whole_part, fractional_part, unit);
+ return StringPrintf("%" PRIu64 ".%06" PRIu64 "%s", whole_part, fractional_part, unit);
} else {
- return StringPrintf("%llu.%09llu%s", whole_part, fractional_part, unit);
+ return StringPrintf("%" PRIu64 ".%09" PRIu64 "%s", whole_part, fractional_part, unit);
}
}
}
@@ -627,7 +627,7 @@ std::string DescriptorToName(const char* descriptor) {
return descriptor;
}
-std::string JniShortName(const mirror::ArtMethod* m) {
+std::string JniShortName(mirror::ArtMethod* m) {
MethodHelper mh(m);
std::string class_name(mh.GetDeclaringClassDescriptor());
// Remove the leading 'L' and trailing ';'...
@@ -646,7 +646,7 @@ std::string JniShortName(const mirror::ArtMethod* m) {
return short_name;
}
-std::string JniLongName(const mirror::ArtMethod* m) {
+std::string JniLongName(mirror::ArtMethod* m) {
std::string long_name;
long_name += JniShortName(m);
long_name += "__";
diff --git a/runtime/utils.h b/runtime/utils.h
index f063c0a..e2d8966 100644
--- a/runtime/utils.h
+++ b/runtime/utils.h
@@ -166,8 +166,29 @@ static inline int CountOneBits(uint32_t x) {
return static_cast<int>(x & 0x0000003F);
}
-#define CLZ(x) __builtin_clz(x)
-#define CTZ(x) __builtin_ctz(x)
+template<typename T>
+static inline int CLZ(T x) {
+ if (sizeof(T) == sizeof(uint32_t)) {
+ return __builtin_clz(x);
+ } else {
+ return __builtin_clzll(x);
+ }
+}
+
+template<typename T>
+static inline int CTZ(T x) {
+ if (sizeof(T) == sizeof(uint32_t)) {
+ return __builtin_ctz(x);
+ } else {
+ return __builtin_ctzll(x);
+ }
+}
+
+static inline uint32_t PointerToLowMemUInt32(const void* p) {
+ uintptr_t intp = reinterpret_cast<uintptr_t>(p);
+ DCHECK_LE(intp, 0xFFFFFFFFU);
+ return intp & 0xFFFFFFFFU;
+}
static inline bool NeedsEscaping(uint16_t ch) {
return (ch < ' ' || ch > '~');
@@ -200,21 +221,22 @@ bool EndsWith(const std::string& s, const char* suffix);
// Returns a human-readable equivalent of 'descriptor'. So "I" would be "int",
// "[[I" would be "int[][]", "[Ljava/lang/String;" would be
// "java.lang.String[]", and so forth.
-std::string PrettyDescriptor(const mirror::String* descriptor);
+std::string PrettyDescriptor(mirror::String* descriptor)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
std::string PrettyDescriptor(const std::string& descriptor);
std::string PrettyDescriptor(Primitive::Type type);
-std::string PrettyDescriptor(const mirror::Class* klass)
+std::string PrettyDescriptor(mirror::Class* klass)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Returns a human-readable signature for 'f'. Something like "a.b.C.f" or
// "int a.b.C.f" (depending on the value of 'with_type').
-std::string PrettyField(const mirror::ArtField* f, bool with_type = true)
+std::string PrettyField(mirror::ArtField* f, bool with_type = true)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
std::string PrettyField(uint32_t field_idx, const DexFile& dex_file, bool with_type = true);
// Returns a human-readable signature for 'm'. Something like "a.b.C.m" or
// "a.b.C.m(II)V" (depending on the value of 'with_signature').
-std::string PrettyMethod(const mirror::ArtMethod* m, bool with_signature = true)
+std::string PrettyMethod(mirror::ArtMethod* m, bool with_signature = true)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
std::string PrettyMethod(uint32_t method_idx, const DexFile& dex_file, bool with_signature = true);
@@ -222,7 +244,7 @@ std::string PrettyMethod(uint32_t method_idx, const DexFile& dex_file, bool with
// So given an instance of java.lang.String, the output would
// be "java.lang.String". Given an array of int, the output would be "int[]".
// Given String.class, the output would be "java.lang.Class<java.lang.String>".
-std::string PrettyTypeOf(const mirror::Object* obj)
+std::string PrettyTypeOf(mirror::Object* obj)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Returns a human-readable form of the type at an index in the specified dex file.
@@ -231,11 +253,11 @@ std::string PrettyType(uint32_t type_idx, const DexFile& dex_file);
// Returns a human-readable form of the name of the given class.
// Given String.class, the output would be "java.lang.Class<java.lang.String>".
-std::string PrettyClass(const mirror::Class* c)
+std::string PrettyClass(mirror::Class* c)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Returns a human-readable form of the name of the given class with its class loader.
-std::string PrettyClassAndClassLoader(const mirror::Class* c)
+std::string PrettyClassAndClassLoader(mirror::Class* c)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Returns a human-readable size string such as "1MB".
@@ -278,10 +300,10 @@ bool IsValidDescriptor(const char* s); // "Ljava/lang/String;"
bool IsValidMemberName(const char* s);
// Returns the JNI native function name for the non-overloaded method 'm'.
-std::string JniShortName(const mirror::ArtMethod* m)
+std::string JniShortName(mirror::ArtMethod* m)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Returns the JNI native function name for the overloaded method 'm'.
-std::string JniLongName(const mirror::ArtMethod* m)
+std::string JniLongName(mirror::ArtMethod* m)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool ReadFileToString(const std::string& file_name, std::string* result);
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index d2681df..30be36c 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -85,7 +85,7 @@ PcToRegisterLineTable::~PcToRegisterLineTable() {
}
}
-MethodVerifier::FailureKind MethodVerifier::VerifyClass(const mirror::Class* klass,
+MethodVerifier::FailureKind MethodVerifier::VerifyClass(mirror::Class* klass,
bool allow_soft_failures,
std::string* error) {
if (klass->IsVerified()) {
@@ -837,7 +837,7 @@ bool MethodVerifier::CheckArrayData(uint32_t cur_offset) {
/* offset to array data table is a relative branch-style offset */
array_data = insns + array_data_offset;
/* make sure the table is 32-bit aligned */
- if ((((uint32_t) array_data) & 0x03) != 0) {
+ if ((reinterpret_cast<uintptr_t>(array_data) & 0x03) != 0) {
Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "unaligned array data table: at " << cur_offset
<< ", data offset " << array_data_offset;
return false;
@@ -941,7 +941,7 @@ bool MethodVerifier::CheckSwitchTargets(uint32_t cur_offset) {
/* offset to switch table is a relative branch-style offset */
const uint16_t* switch_insns = insns + switch_offset;
/* make sure the table is 32-bit aligned */
- if ((((uint32_t) switch_insns) & 0x03) != 0) {
+ if ((reinterpret_cast<uintptr_t>(switch_insns) & 0x03) != 0) {
Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "unaligned switch table: at " << cur_offset
<< ", switch offset " << switch_offset;
return false;
@@ -3616,10 +3616,9 @@ void MethodVerifier::VerifyISPut(const Instruction* inst, const RegType& insn_ty
// Look for an instance field with this offset.
// TODO: we may speed up the search if offsets are sorted by doing a quick search.
-static mirror::ArtField* FindInstanceFieldWithOffset(const mirror::Class* klass,
- uint32_t field_offset)
+static mirror::ArtField* FindInstanceFieldWithOffset(mirror::Class* klass, uint32_t field_offset)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- const mirror::ObjectArray<mirror::ArtField>* instance_fields = klass->GetIFields();
+ mirror::ObjectArray<mirror::ArtField>* instance_fields = klass->GetIFields();
if (instance_fields != NULL) {
for (int32_t i = 0, e = instance_fields->GetLength(); i < e; ++i) {
mirror::ArtField* field = instance_fields->Get(i);
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index 053cee5..7c75c9c 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -140,8 +140,7 @@ class MethodVerifier {
};
/* Verify a class. Returns "kNoFailure" on success. */
- static FailureKind VerifyClass(const mirror::Class* klass, bool allow_soft_failures,
- std::string* error)
+ static FailureKind VerifyClass(mirror::Class* klass, bool allow_soft_failures, std::string* error)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static FailureKind VerifyClass(const DexFile* dex_file, SirtRef<mirror::DexCache>& dex_cache,
SirtRef<mirror::ClassLoader>& class_loader,
diff --git a/runtime/verifier/reg_type.h b/runtime/verifier/reg_type.h
index 4be1d02..3818375 100644
--- a/runtime/verifier/reg_type.h
+++ b/runtime/verifier/reg_type.h
@@ -203,7 +203,7 @@ class RegType {
bool IsObjectArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
Primitive::Type GetPrimitiveType() const;
bool IsJavaLangObjectArray() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsInstantiableTypes() const;
+ bool IsInstantiableTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
const std::string& GetDescriptor() const {
DCHECK(HasClass() || (IsUnresolvedTypes() && !IsUnresolvedMergedReference() &&
!IsUnresolvedSuperClass()));
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index e3946f7..546eb40 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -179,7 +179,7 @@ void WellKnownClasses::Init(JNIEnv* env) {
java_lang_Thread_name = CacheField(env, java_lang_Thread, false, "name", "Ljava/lang/String;");
java_lang_Thread_priority = CacheField(env, java_lang_Thread, false, "priority", "I");
java_lang_Thread_uncaughtHandler = CacheField(env, java_lang_Thread, false, "uncaughtHandler", "Ljava/lang/Thread$UncaughtExceptionHandler;");
- java_lang_Thread_nativePeer = CacheField(env, java_lang_Thread, false, "nativePeer", "I");
+ java_lang_Thread_nativePeer = CacheField(env, java_lang_Thread, false, "nativePeer", "J");
java_lang_ThreadGroup_mainThreadGroup = CacheField(env, java_lang_ThreadGroup, true, "mainThreadGroup", "Ljava/lang/ThreadGroup;");
java_lang_ThreadGroup_name = CacheField(env, java_lang_ThreadGroup, false, "name", "Ljava/lang/String;");
java_lang_ThreadGroup_systemThreadGroup = CacheField(env, java_lang_ThreadGroup, true, "systemThreadGroup", "Ljava/lang/ThreadGroup;");
diff --git a/runtime/zip_archive.cc b/runtime/zip_archive.cc
index 8cb1993..ba0b91e 100644
--- a/runtime/zip_archive.cc
+++ b/runtime/zip_archive.cc
@@ -55,7 +55,7 @@ MemMap* ZipEntry::ExtractToMemMap(const char* entry_filename, std::string* error
name += entry_filename;
UniquePtr<MemMap> map(MemMap::MapAnonymous(name.c_str(),
NULL, GetUncompressedLength(),
- PROT_READ | PROT_WRITE, error_msg));
+ PROT_READ | PROT_WRITE, false, error_msg));
if (map.get() == nullptr) {
DCHECK(!error_msg->empty());
return nullptr;