225 lines
5.5 KiB
ArmAsm
225 lines
5.5 KiB
ArmAsm
%def op_check_cast():
|
|
% slow_path = add_slow_path(op_check_cast_slow_path)
|
|
// Fast-path which gets the class from thread-local cache.
|
|
% fetch_from_thread_cache("%rsi", miss_label="2f")
|
|
1:
|
|
GET_VREG %edi, rINSTq
|
|
testl %edi, %edi
|
|
je .L${opcode}_resume
|
|
// Fast path without read barriers.
|
|
cmpl MIRROR_OBJECT_CLASS_OFFSET(%edi), %esi
|
|
jne ${slow_path}
|
|
.L${opcode}_resume:
|
|
ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
|
|
2:
|
|
EXPORT_PC
|
|
movq rSELF:THREAD_SELF_OFFSET, %rdi
|
|
movq 0(%rsp), %rsi
|
|
movq rPC, %rdx
|
|
call nterp_get_class_or_allocate_object
|
|
movq %rax, %rsi
|
|
jmp 1b
|
|
|
|
%def op_check_cast_slow_path():
|
|
testl $$MIRROR_CLASS_IS_INTERFACE_FLAG, MIRROR_CLASS_ACCESS_FLAGS_OFFSET(%rsi)
|
|
jne 2f
|
|
movl MIRROR_OBJECT_CLASS_OFFSET(%edi), %eax
|
|
cmpl $$0, MIRROR_CLASS_COMPONENT_TYPE_OFFSET(%rsi)
|
|
jne 2f
|
|
1:
|
|
movl MIRROR_CLASS_SUPER_CLASS_OFFSET(%eax), %eax
|
|
cmpl %eax, %esi
|
|
je .L${opcode}_resume
|
|
testl %eax, %eax
|
|
jne 1b
|
|
2:
|
|
cmpq $$0, rSELF:THREAD_READ_BARRIER_MARK_REG00_OFFSET
|
|
jne 4f
|
|
3:
|
|
EXPORT_PC
|
|
call art_quick_check_instance_of
|
|
jmp .L${opcode}_resume
|
|
4:
|
|
// 06 is %rsi
|
|
call art_quick_read_barrier_mark_reg06
|
|
jmp 3b
|
|
5:
|
|
movl MIRROR_CLASS_COMPONENT_TYPE_OFFSET(%eax), %eax
|
|
// Check if object is an array.
|
|
testl %eax, %eax
|
|
je 2b
|
|
movl MIRROR_CLASS_COMPONENT_TYPE_OFFSET(%esi), %ecx
|
|
cmpl $$0, MIRROR_CLASS_SUPER_CLASS_OFFSET(%ecx)
|
|
jne 2b
|
|
cmpw $$0, MIRROR_CLASS_OBJECT_PRIMITIVE_TYPE_OFFSET(%ecx)
|
|
jne 2b
|
|
// %ecx is Object[]
|
|
// Check if the object is a primitive array.
|
|
cmpw $$0, MIRROR_CLASS_OBJECT_PRIMITIVE_TYPE_OFFSET(%eax)
|
|
je .L${opcode}_resume
|
|
jmp 2b
|
|
|
|
%def op_iget_boolean():
|
|
jmp NterpGetBooleanInstanceField
|
|
|
|
%def op_iget_byte():
|
|
jmp NterpGetByteInstanceField
|
|
|
|
%def op_iget_char():
|
|
jmp NterpGetCharInstanceField
|
|
|
|
%def op_iget_object():
|
|
jmp NterpGetObjectInstanceField
|
|
|
|
%def op_iget_short():
|
|
jmp NterpGetShortInstanceField
|
|
|
|
%def op_iget_wide():
|
|
jmp NterpGetWideInstanceField
|
|
|
|
%def op_instance_of():
|
|
% slow_path = add_slow_path(op_instance_of_slow_path)
|
|
/* instance-of vA, vB, class@CCCC */
|
|
// Fast-path which gets the class from thread-local cache.
|
|
% fetch_from_thread_cache("%rsi", miss_label=".L"+opcode+"_init")
|
|
.L${opcode}_start:
|
|
movzbl rINSTbl,%edi
|
|
sarl $$4,%edi # edi<- B
|
|
GET_VREG %edi %rdi # edi<- vB (object)
|
|
andb $$0xf,rINSTbl # rINST<- A
|
|
testl %edi, %edi
|
|
je .L${opcode}_set_vreg
|
|
// Fast path without read barriers.
|
|
cmpl MIRROR_OBJECT_CLASS_OFFSET(%edi), %esi
|
|
jne ${slow_path}
|
|
.L${opcode}_set_one:
|
|
movl $$1, %edi
|
|
.L${opcode}_set_vreg:
|
|
SET_VREG %edi, rINSTq
|
|
.L${opcode}_resume:
|
|
ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
|
|
|
|
%def op_instance_of_slow_path():
|
|
// Go slow path if we are marking. Checking now allows
|
|
// not going to slow path if the super class hierarchy check fails.
|
|
cmpq $$0, rSELF:THREAD_READ_BARRIER_MARK_REG00_OFFSET
|
|
jne 4f
|
|
testl $$MIRROR_CLASS_IS_INTERFACE_FLAG, MIRROR_CLASS_ACCESS_FLAGS_OFFSET(%rsi)
|
|
jne 5f
|
|
movl MIRROR_OBJECT_CLASS_OFFSET(%edi), %eax
|
|
cmpl $$0, MIRROR_CLASS_COMPONENT_TYPE_OFFSET(%rsi)
|
|
jne 3f
|
|
1:
|
|
movl MIRROR_CLASS_SUPER_CLASS_OFFSET(%eax), %eax
|
|
cmpl %eax, %esi
|
|
je .L${opcode}_set_one
|
|
testl %eax, %eax
|
|
jne 1b
|
|
2:
|
|
SET_VREG $$0, rINSTq # fp[A] <- value
|
|
jmp .L${opcode}_resume
|
|
3:
|
|
movl MIRROR_CLASS_COMPONENT_TYPE_OFFSET(%eax), %eax
|
|
// Check if object is an array.
|
|
testl %eax, %eax
|
|
je 2b
|
|
movl MIRROR_CLASS_COMPONENT_TYPE_OFFSET(%esi), %ecx
|
|
cmpl $$0, MIRROR_CLASS_SUPER_CLASS_OFFSET(%ecx)
|
|
jne 5f
|
|
cmpw $$0, MIRROR_CLASS_OBJECT_PRIMITIVE_TYPE_OFFSET(%ecx)
|
|
jne 2b
|
|
// %ecx is Object[]
|
|
// Check if the object is a primitive array.
|
|
xorl %ecx, %ecx
|
|
cmpw $$0, MIRROR_CLASS_OBJECT_PRIMITIVE_TYPE_OFFSET(%eax)
|
|
sete %cl
|
|
SET_VREG %ecx, rINSTq
|
|
jmp .L${opcode}_resume
|
|
4:
|
|
// 06 is %rsi
|
|
call art_quick_read_barrier_mark_reg06
|
|
5:
|
|
EXPORT_PC
|
|
call artInstanceOfFromCode
|
|
SET_VREG %eax, rINSTq # fp[A] <- value
|
|
jmp .L${opcode}_resume
|
|
|
|
.L${opcode}_init:
|
|
EXPORT_PC
|
|
movq rSELF:THREAD_SELF_OFFSET, %rdi
|
|
movq 0(%rsp), %rsi
|
|
movq rPC, %rdx
|
|
call nterp_get_class_or_allocate_object
|
|
movq %rax, %rsi
|
|
jmp .L${opcode}_start
|
|
|
|
%def op_iget():
|
|
jmp NterpGetInstanceField
|
|
|
|
%def op_iput():
|
|
jmp NterpPutInstanceField
|
|
|
|
%def op_iput_boolean():
|
|
jmp NterpPutBooleanInstanceField
|
|
|
|
%def op_iput_byte():
|
|
jmp NterpPutByteInstanceField
|
|
|
|
%def op_iput_char():
|
|
jmp NterpPutCharInstanceField
|
|
|
|
%def op_iput_object():
|
|
jmp NterpPutObjectInstanceField
|
|
|
|
%def op_iput_short():
|
|
jmp NterpPutShortInstanceField
|
|
|
|
%def op_iput_wide():
|
|
jmp NterpPutWideInstanceField
|
|
|
|
%def op_sget(load="movl", wide="0"):
|
|
jmp NterpGetIntStaticField
|
|
|
|
%def op_sget_boolean():
|
|
jmp NterpGetBooleanStaticField
|
|
|
|
%def op_sget_byte():
|
|
jmp NterpGetByteStaticField
|
|
|
|
%def op_sget_char():
|
|
jmp NterpGetCharStaticField
|
|
|
|
%def op_sget_object():
|
|
jmp NterpGetObjectStaticField
|
|
|
|
%def op_sget_short():
|
|
jmp NterpGetShortStaticField
|
|
|
|
%def op_sget_wide():
|
|
jmp NterpGetWideStaticField
|
|
|
|
%def op_sput():
|
|
jmp NterpPutStaticField
|
|
|
|
%def op_sput_boolean():
|
|
jmp NterpPutBooleanStaticField
|
|
|
|
%def op_sput_byte():
|
|
jmp NterpPutByteStaticField
|
|
|
|
%def op_sput_char():
|
|
jmp NterpPutCharStaticField
|
|
|
|
%def op_sput_object():
|
|
jmp NterpPutObjectStaticField
|
|
|
|
%def op_sput_short():
|
|
jmp NterpPutShortStaticField
|
|
|
|
%def op_sput_wide():
|
|
jmp NterpPutWideStaticField
|
|
|
|
%def op_new_instance():
|
|
// The routine is too big to fit in a handler, so jump to it.
|
|
jmp NterpNewInstance
|