Merge "Disassemble x86 opcode 0xc7." into ics-mr1-plus-art
diff --git a/src/compiler/codegen/GenCommon.cc b/src/compiler/codegen/GenCommon.cc
index aeacab8..d2628bb 100644
--- a/src/compiler/codegen/GenCommon.cc
+++ b/src/compiler/codegen/GenCommon.cc
@@ -1392,8 +1392,8 @@
#endif
/* branch target here */
LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
- branch1->target = (LIR*)target;
- branch2->target = (LIR*)target;
+ branch1->target = target;
+ branch2->target = target;
}
/*
@@ -1403,73 +1403,70 @@
void genArrayObjPut(CompilationUnit* cUnit, MIR* mir, RegLocation rlArray,
RegLocation rlIndex, RegLocation rlSrc, int scale)
{
- RegisterClass regClass = oatRegClassBySize(kWord);
int lenOffset = Array::LengthOffset().Int32Value();
int dataOffset = Array::DataOffset(sizeof(Object*)).Int32Value();
- oatFlushAllRegs(cUnit);
- /* Make sure it's a legal object Put. Use direct regs at first */
- loadValueDirectFixed(cUnit, rlArray, rARG1);
- loadValueDirectFixed(cUnit, rlSrc, rARG0);
+ oatFlushAllRegs(cUnit); // Use explicit registers
+ oatLockCallTemps(cUnit);
- /* null array object? */
- genNullCheck(cUnit, rlArray.sRegLow, rARG1, mir);
- /* Get the array's class */
- loadWordDisp(cUnit, rARG1, Object::ClassOffset().Int32Value(), rARG1);
+ int rValue = rARG0; // Register holding value
+ int rArrayClass = rARG1; // Register holding array's Class
+ int rArray = rARG2; // Register holding array
+ int rIndex = rARG3; // Register holding index into array
+
+ loadValueDirectFixed(cUnit, rlArray, rArray); // Grab array
+ loadValueDirectFixed(cUnit, rlSrc, rValue); // Grab value
+ loadValueDirectFixed(cUnit, rlIndex, rIndex); // Grab index
+
+ genNullCheck(cUnit, rlArray.sRegLow, rArray, mir); // NPE?
+
+ // Store of null?
+ LIR* null_value_check = opCmpImmBranch(cUnit, kCondEq, rValue, 0, NULL);
+
+ // Get the array's class.
+ loadWordDisp(cUnit, rArray, Object::ClassOffset().Int32Value(), rArrayClass);
callRuntimeHelperRegReg(cUnit, ENTRYPOINT_OFFSET(pCanPutArrayElementFromCode),
- rARG0, rARG1);
- oatFreeTemp(cUnit, rARG0);
- oatFreeTemp(cUnit, rARG1);
+ rValue, rArrayClass);
+ // Redo loadValues in case they didn't survive the call.
+ loadValueDirectFixed(cUnit, rlArray, rArray); // Reload array
+ loadValueDirectFixed(cUnit, rlIndex, rIndex); // Reload index
+ loadValueDirectFixed(cUnit, rlSrc, rValue); // Reload value
+ rArrayClass = INVALID_REG;
- // Now, redo loadValues in case they didn't survive the call
-
- rlArray = loadValue(cUnit, rlArray, kCoreReg);
- rlIndex = loadValue(cUnit, rlIndex, kCoreReg);
+ // Branch here if value to be stored == null
+ LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
+ null_value_check->target = target;
#if defined(TARGET_X86)
+ // make an extra temp available for card mark below
+ oatFreeTemp(cUnit, rARG1);
if (!(mir->optimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
/* if (rlIndex >= [rlArray + lenOffset]) goto kThrowArrayBounds */
- genRegMemCheck(cUnit, kCondUge, rlIndex.lowReg, rlArray.lowReg,
+ genRegMemCheck(cUnit, kCondUge, rIndex, rArray,
lenOffset, mir, kThrowArrayBounds);
}
- rlSrc = loadValue(cUnit, rlSrc, regClass);
- storeBaseIndexedDisp(cUnit, NULL, rlArray.lowReg, rlIndex.lowReg, scale,
- dataOffset, rlSrc.lowReg, INVALID_REG, kWord,
+ storeBaseIndexedDisp(cUnit, NULL, rArray, rIndex, scale,
+ dataOffset, rValue, INVALID_REG, kWord,
INVALID_SREG);
- if (oatIsTemp(cUnit, rlIndex.lowReg)) {
- oatFreeTemp(cUnit, rlIndex.lowReg);
- }
#else
- int regPtr;
- if (oatIsTemp(cUnit, rlArray.lowReg)) {
- oatClobber(cUnit, rlArray.lowReg);
- regPtr = rlArray.lowReg;
- } else {
- regPtr = oatAllocTemp(cUnit);
- opRegCopy(cUnit, regPtr, rlArray.lowReg);
- }
-
bool needsRangeCheck = (!(mir->optimizationFlags & MIR_IGNORE_RANGE_CHECK));
int regLen = INVALID_REG;
if (needsRangeCheck) {
- regLen = oatAllocTemp(cUnit);
- //NOTE: max live temps(4) here.
- /* Get len */
- loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen);
+ regLen = rARG1;
+ loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen); // Get len
}
- /* regPtr -> array data */
- opRegImm(cUnit, kOpAdd, regPtr, dataOffset);
- /* at this point, regPtr points to array, 2 live temps */
- rlSrc = loadValue(cUnit, rlSrc, regClass);
+ /* rPtr -> array data */
+ int rPtr = oatAllocTemp(cUnit);
+ opRegRegImm(cUnit, kOpAdd, rPtr, rArray, dataOffset);
if (needsRangeCheck) {
- genRegRegCheck(cUnit, kCondCs, rlIndex.lowReg, regLen, mir,
+ genRegRegCheck(cUnit, kCondCs, rIndex, regLen, mir,
kThrowArrayBounds);
- oatFreeTemp(cUnit, regLen);
}
- storeBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlSrc.lowReg,
- scale, kWord);
+ storeBaseIndexed(cUnit, rPtr, rIndex, rValue, scale, kWord);
+ oatFreeTemp(cUnit, rPtr);
#endif
- markGCCard(cUnit, rlSrc.lowReg, rlArray.lowReg);
+ oatFreeTemp(cUnit, rIndex);
+ markGCCard(cUnit, rValue, rArray);
}
/*
diff --git a/src/compiler/codegen/x86/X86/Factory.cc b/src/compiler/codegen/x86/X86/Factory.cc
index 9421744..2bd5b42 100644
--- a/src/compiler/codegen/x86/X86/Factory.cc
+++ b/src/compiler/codegen/x86/X86/Factory.cc
@@ -173,6 +173,7 @@
LIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1, int rSrc2)
{
X86OpCode opcode = kX86Nop;
+ bool src2_must_be_cx = false;
switch (op) {
// X86 unary opcodes
case kOpMvn:
@@ -184,9 +185,9 @@
// X86 binary opcodes
case kOpSub: opcode = kX86Sub32RR; break;
case kOpSbc: opcode = kX86Sbb32RR; break;
- case kOpLsl: opcode = kX86Sal32RC; break;
- case kOpLsr: opcode = kX86Shr32RC; break;
- case kOpAsr: opcode = kX86Sar32RC; break;
+ case kOpLsl: opcode = kX86Sal32RC; src2_must_be_cx = true; break;
+ case kOpLsr: opcode = kX86Shr32RC; src2_must_be_cx = true; break;
+ case kOpAsr: opcode = kX86Sar32RC; src2_must_be_cx = true; break;
case kOpMov: opcode = kX86Mov32RR; break;
case kOpCmp: opcode = kX86Cmp32RR; break;
case kOpAdd: opcode = kX86Add32RR; break;
@@ -202,6 +203,7 @@
LOG(FATAL) << "Bad case in opRegReg " << op;
break;
}
+ CHECK(!src2_must_be_cx || rSrc2 == rCX);
return newLIR2(cUnit, opcode, rDestSrc1, rSrc2);
}
diff --git a/src/compiler/codegen/x86/X86RallocUtil.cc b/src/compiler/codegen/x86/X86RallocUtil.cc
index 2971632..a85cb8a 100644
--- a/src/compiler/codegen/x86/X86RallocUtil.cc
+++ b/src/compiler/codegen/x86/X86RallocUtil.cc
@@ -134,6 +134,7 @@
oatLockTemp(cUnit, rARG0);
oatLockTemp(cUnit, rARG1);
oatLockTemp(cUnit, rARG2);
+ oatLockTemp(cUnit, rARG3);
}
/* To be used when explicitly managing register use */
@@ -142,6 +143,7 @@
oatFreeTemp(cUnit, rARG0);
oatFreeTemp(cUnit, rARG1);
oatFreeTemp(cUnit, rARG2);
+ oatFreeTemp(cUnit, rARG3);
}
/* Convert an instruction to a NOP */
diff --git a/src/oat/runtime/arm/runtime_support_arm.S b/src/oat/runtime/arm/runtime_support_arm.S
index 9c55e66..e1323d6 100644
--- a/src/oat/runtime/arm/runtime_support_arm.S
+++ b/src/oat/runtime/arm/runtime_support_arm.S
@@ -313,8 +313,6 @@
*/
ALIGN_FUNCTION_ENTRY
art_can_put_array_element_from_code:
- cmp r0, #0 @ return if element == NULL
- bxeq lr
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case exception allocation triggers GC
mov r2, r9 @ pass Thread::Current
mov r3, sp @ pass SP
diff --git a/src/oat/runtime/mips/runtime_support_mips.S b/src/oat/runtime/mips/runtime_support_mips.S
index 12cebfd..9b082bf 100644
--- a/src/oat/runtime/mips/runtime_support_mips.S
+++ b/src/oat/runtime/mips/runtime_support_mips.S
@@ -473,11 +473,6 @@
*/
ALIGN_FUNCTION_ENTRY
art_can_put_array_element_from_code:
- bnez a0, 1f @ return if element == NULL
- nop
- jr ra
- nop
-1:
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case exception allocation triggers GC
move a2, rSELF @ pass Thread::Current
jal artCanPutArrayElementFromCode @ (Object* element, Class* array_class, Thread*, SP)
diff --git a/src/oat/runtime/x86/runtime_support_x86.S b/src/oat/runtime/x86/runtime_support_x86.S
index 4f3d334..fd41376 100644
--- a/src/oat/runtime/x86/runtime_support_x86.S
+++ b/src/oat/runtime/x86/runtime_support_x86.S
@@ -21,6 +21,7 @@
#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
@@ -35,6 +36,7 @@
#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.
@@ -268,7 +270,40 @@
INVOKE_TRAMPOLINE art_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck
INVOKE_TRAMPOLINE art_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
-MACRO2(TWO_ARG_ALLOC, c_name, cxx_name)
+MACRO3(NO_ARG_DOWNCALL, c_name, cxx_name, return_macro)
+ .globl VAR(c_name, 0)
+ ALIGN_FUNCTION_ENTRY
+VAR(c_name, 0):
+ SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC
+ mov %esp, %edx // remember SP
+ // Outgoing argument set up
+ subl MACRO_LITERAL(8), %esp // push padding
+ pushl %edx // pass SP
+ pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current()
+ call VAR(cxx_name, 1) // cxx_name(Thread*, SP)
+ addl MACRO_LITERAL(16), %esp // pop arguments
+ RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
+ VAR(return_macro, 2) // return or deliver exception
+END_MACRO
+
+MACRO3(ONE_ARG_DOWNCALL, c_name, cxx_name, return_macro)
+ .globl VAR(c_name, 0)
+ ALIGN_FUNCTION_ENTRY
+VAR(c_name, 0):
+ SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC
+ mov %esp, %edx // remember SP
+ // Outgoing argument set up
+ pushl %eax // push padding
+ pushl %edx // pass SP
+ pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current()
+ pushl %eax // pass arg1
+ call VAR(cxx_name, 1) // cxx_name(arg1, Thread*, SP)
+ addl MACRO_LITERAL(16), %esp // pop arguments
+ RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
+ VAR(return_macro, 2) // return or deliver exception
+END_MACRO
+
+MACRO3(TWO_ARG_DOWNCALL, c_name, cxx_name, return_macro)
.globl VAR(c_name, 0)
ALIGN_FUNCTION_ENTRY
VAR(c_name, 0):
@@ -279,17 +314,13 @@
pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current()
pushl %ecx // pass arg2
pushl %eax // pass arg1
- call VAR(cxx_name, 1) // cxx_name(arg1, arg2, arg3, Thread*, SP)
+ call VAR(cxx_name, 1) // cxx_name(arg1, arg2, Thread*, SP)
addl MACRO_LITERAL(16), %esp // pop arguments
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
- testl %eax, %eax // eax == 0 ?
- jz 1f
- ret
-1:
- DELIVER_PENDING_EXCEPTION
+ VAR(return_macro, 2) // return or deliver exception
END_MACRO
-MACRO2(THREE_ARG_ALLOC, c_name, cxx_name)
+MACRO3(THREE_ARG_DOWNCALL, c_name, cxx_name, return_macro)
.globl VAR(c_name, 0)
ALIGN_FUNCTION_ENTRY
VAR(c_name, 0):
@@ -302,72 +333,42 @@
pushl %edx // pass arg3
pushl %ecx // pass arg2
pushl %eax // pass arg1
- call VAR(cxx_name, 1) // cxx_name(arg1, arg2, Thread*, SP)
+ call VAR(cxx_name, 1) // cxx_name(arg1, arg2, arg3, Thread*, SP)
addl MACRO_LITERAL(32), %esp // pop arguments
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
+ VAR(return_macro, 2) // return or deliver exception
+END_MACRO
+
+MACRO0(RETURN_IF_EAX_NOT_ZERO)
testl %eax, %eax // eax == 0 ?
- jz 1f
- ret
-1:
+ jz 1f // if eax == 0 goto 1
+ ret // return
+1: // deliver exception on current thread
DELIVER_PENDING_EXCEPTION
END_MACRO
-TWO_ARG_ALLOC art_alloc_object_from_code, artAllocObjectFromCode
-TWO_ARG_ALLOC art_alloc_object_from_code_with_access_check, artAllocObjectFromCodeWithAccessCheck
-THREE_ARG_ALLOC art_alloc_array_from_code, artAllocArrayFromCode
-THREE_ARG_ALLOC art_alloc_array_from_code_with_access_check, artAllocArrayFromCodeWithAccessCheck
-THREE_ARG_ALLOC art_check_and_alloc_array_from_code, artCheckAndAllocArrayFromCode
-THREE_ARG_ALLOC art_check_and_alloc_array_from_code_with_access_check, artCheckAndAllocArrayFromCodeWithAccessCheck
-
-TWO_ARG_ALLOC art_resolve_string_from_code, artResolveStringFromCode
-TWO_ARG_ALLOC art_initialize_static_storage_from_code, artInitializeStaticStorageFromCode
-
-DEFINE_FUNCTION art_lock_object_from_code
- SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC
- mov %esp, %edx // remember SP
- // Outgoing argument set up
- pushl %eax // alignment padding
- pushl %edx // pass SP
- pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current()
- pushl %eax // pass arg1
- call SYMBOL(artLockObjectFromCode) // (Object*, Thread*, SP)
- addl LITERAL(16), %esp // pop arguments
- RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
- ret
-
-DEFINE_FUNCTION art_unlock_object_from_code
- SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC
- mov %esp, %edx // remember SP
- // Outgoing argument set up
- pushl %eax // alignment padding
- pushl %edx // pass SP
- pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current()
- pushl %eax // pass arg1
- call SYMBOL(artUnlockObjectFromCode) // (Object*, Thread*, SP)
- addl LITERAL(16), %esp // pop arguments
- RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
- testl %eax, %eax // eax == 0 ?
- jnz 1f
- ret
-1:
+MACRO0(RETURN_IF_EAX_ZERO)
+ 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
-DEFINE_FUNCTION art_handle_fill_data_from_code
- SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC
- mov %esp, %edx // remember SP
- // Outgoing argument set up
- pushl %edx // pass SP
- pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current()
- pushl %ecx // pass arg2
- pushl %eax // pass arg1
- call SYMBOL(artHandleFillArrayDataFromCode) // (Array* array, const uint16_t* table, Thread*, SP)
- addl LITERAL(16), %esp // pop arguments
- RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
- testl %eax, %eax // eax == 0 ?
- jnz 1f
- ret
-1:
- DELIVER_PENDING_EXCEPTION
+TWO_ARG_DOWNCALL art_alloc_object_from_code, artAllocObjectFromCode, RETURN_IF_EAX_NOT_ZERO
+TWO_ARG_DOWNCALL art_alloc_object_from_code_with_access_check, artAllocObjectFromCodeWithAccessCheck, RETURN_IF_EAX_NOT_ZERO
+THREE_ARG_DOWNCALL art_alloc_array_from_code, artAllocArrayFromCode, RETURN_IF_EAX_NOT_ZERO
+THREE_ARG_DOWNCALL art_alloc_array_from_code_with_access_check, artAllocArrayFromCodeWithAccessCheck, RETURN_IF_EAX_NOT_ZERO
+THREE_ARG_DOWNCALL art_check_and_alloc_array_from_code, artCheckAndAllocArrayFromCode, RETURN_IF_EAX_NOT_ZERO
+THREE_ARG_DOWNCALL art_check_and_alloc_array_from_code_with_access_check, artCheckAndAllocArrayFromCodeWithAccessCheck, RETURN_IF_EAX_NOT_ZERO
+
+TWO_ARG_DOWNCALL art_resolve_string_from_code, artResolveStringFromCode, RETURN_IF_EAX_NOT_ZERO
+TWO_ARG_DOWNCALL art_initialize_static_storage_from_code, artInitializeStaticStorageFromCode, RETURN_IF_EAX_NOT_ZERO
+
+ONE_ARG_DOWNCALL art_lock_object_from_code, artLockObjectFromCode, ret
+ONE_ARG_DOWNCALL art_unlock_object_from_code, artUnlockObjectFromCode, RETURN_IF_EAX_ZERO
+
+TWO_ARG_DOWNCALL art_handle_fill_data_from_code, artHandleFillArrayDataFromCode, RETURN_IF_EAX_ZERO
DEFINE_FUNCTION art_is_assignable_from_code
pushl %eax // alignment padding
@@ -385,22 +386,10 @@
addl LITERAL(12), %esp // pop arguments
ret
-DEFINE_FUNCTION art_check_cast_from_code
- SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC
- mov %esp, %edx // remember SP
- // Outgoing argument set up
- pushl %edx // pass SP
- pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current()
- pushl %ecx // pass arg2
- pushl %eax // pass arg1
- call SYMBOL(artCheckCastFromCode) // (Class* a, Class* b, Thread*, SP)
- addl LITERAL(16), %esp // pop arguments
- RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
- testl %eax, %eax // eax == 0 ?
- jnz 1f
- ret
-1:
- DELIVER_PENDING_EXCEPTION
+TWO_ARG_DOWNCALL art_check_cast_from_code, artCheckCastFromCode, RETURN_IF_EAX_ZERO
+TWO_ARG_DOWNCALL art_can_put_array_element_from_code, artCanPutArrayElementFromCode, RETURN_IF_EAX_ZERO
+
+NO_ARG_DOWNCALL art_test_suspend, artTestSuspendFromCode, ret
DEFINE_FUNCTION art_idiv_from_code
cdq // edx:eax = sign extend eax
@@ -469,26 +458,6 @@
1:
ret
-DEFINE_FUNCTION art_can_put_array_element_from_code
- test %eax, %eax // Null is trivially storable
- jz 1f
- SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC
- mov %esp, %edx // remember SP
- // Outgoing argument set up
- pushl %edx // pass SP
- pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current()
- pushl %ecx // pass arg2
- pushl %eax // pass arg1
- call SYMBOL(artCanPutArrayElementFromCode) // (Object* element, Class* array_class, Thread*, SP)
- addl LITERAL(16), %esp // pop arguments
- RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
- testl %eax, %eax // eax == 0 ?
- jnz 2f
-1:
- ret
-2:
- DELIVER_PENDING_EXCEPTION
-
MACRO1(UNIMPLEMENTED,name)
.globl VAR(name, 0)
ALIGN_FUNCTION_ENTRY
@@ -499,7 +468,6 @@
// TODO: implement these!
UNIMPLEMENTED art_proxy_invoke_handler
UNIMPLEMENTED art_update_debugger
-UNIMPLEMENTED art_test_suspend
UNIMPLEMENTED art_initialize_type_and_verify_access_from_code
UNIMPLEMENTED art_initialize_type_from_code
UNIMPLEMENTED art_set32_instance_from_code