diff options
| author | 2012-04-09 16:29:25 -0700 | |
|---|---|---|
| committer | 2012-04-09 19:45:49 -0700 | |
| commit | d36c52ea6bc22883ef381f6da1ac05ef7524f63a (patch) | |
| tree | cc184142b857a666d4aca5d049852f123fa80dae /src | |
| parent | 82914b6164fd0109531391975389e4f0ff6832c8 (diff) | |
Check for null array assignments inline. Tidy asm macros.
Tidy/fix array object stores to not pass incremented register to card
mark. Fix x86 register allocator clobbers. Clean runtime support
assembler macros to be more macrotized. Extra X86 shift assert.
Add X86 thread suspension down call.
Change-Id: Ida765dcba32404519fe7eb478f5628d46caf41f7
Diffstat (limited to 'src')
| -rw-r--r-- | src/compiler/codegen/GenCommon.cc | 93 | ||||
| -rw-r--r-- | src/compiler/codegen/x86/X86/Factory.cc | 8 | ||||
| -rw-r--r-- | src/compiler/codegen/x86/X86RallocUtil.cc | 2 | ||||
| -rw-r--r-- | src/oat/runtime/arm/runtime_support_arm.S | 2 | ||||
| -rw-r--r-- | src/oat/runtime/mips/runtime_support_mips.S | 5 | ||||
| -rw-r--r-- | src/oat/runtime/x86/runtime_support_x86.S | 166 |
6 files changed, 119 insertions, 157 deletions
diff --git a/src/compiler/codegen/GenCommon.cc b/src/compiler/codegen/GenCommon.cc index aeacab8514..d2628bb19c 100644 --- a/src/compiler/codegen/GenCommon.cc +++ b/src/compiler/codegen/GenCommon.cc @@ -1392,8 +1392,8 @@ void genCheckCast(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) #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 genCheckCast(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) 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); - - /* null array object? */ - genNullCheck(cUnit, rlArray.sRegLow, rARG1, mir); - /* Get the array's class */ - loadWordDisp(cUnit, rARG1, Object::ClassOffset().Int32Value(), rARG1); - callRuntimeHelperRegReg(cUnit, ENTRYPOINT_OFFSET(pCanPutArrayElementFromCode), - rARG0, rARG1); - oatFreeTemp(cUnit, rARG0); - oatFreeTemp(cUnit, rARG1); + oatFlushAllRegs(cUnit); // Use explicit registers + oatLockCallTemps(cUnit); - // Now, redo loadValues in case they didn't survive the call + 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 - rlArray = loadValue(cUnit, rlArray, kCoreReg); - rlIndex = loadValue(cUnit, rlIndex, kCoreReg); + 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), + 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; + + // 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 9421744f69..2bd5b42458 100644 --- a/src/compiler/codegen/x86/X86/Factory.cc +++ b/src/compiler/codegen/x86/X86/Factory.cc @@ -173,6 +173,7 @@ LIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1, int value) { 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 @@ LIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1, int rSrc2) // 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 @@ LIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1, int rSrc2) 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 297163250b..a85cb8af63 100644 --- a/src/compiler/codegen/x86/X86RallocUtil.cc +++ b/src/compiler/codegen/x86/X86RallocUtil.cc @@ -134,6 +134,7 @@ extern void oatLockCallTemps(CompilationUnit* cUnit) oatLockTemp(cUnit, rARG0); oatLockTemp(cUnit, rARG1); oatLockTemp(cUnit, rARG2); + oatLockTemp(cUnit, rARG3); } /* To be used when explicitly managing register use */ @@ -142,6 +143,7 @@ extern void oatFreeCallTemps(CompilationUnit* cUnit) 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 9c55e661e9..e1323d6cba 100644 --- a/src/oat/runtime/arm/runtime_support_arm.S +++ b/src/oat/runtime/arm/runtime_support_arm.S @@ -313,8 +313,6 @@ art_check_cast_from_code: */ 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 12cebfd011..9b082bf84e 100644 --- a/src/oat/runtime/mips/runtime_support_mips.S +++ b/src/oat/runtime/mips/runtime_support_mips.S @@ -473,11 +473,6 @@ art_check_cast_from_code: */ 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 4f3d3349b5..fd413761e2 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,106 +270,105 @@ INVOKE_TRAMPOLINE art_invoke_direct_trampoline_with_access_check, artInvokeDirec 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() - 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(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(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, %ebx // remember SP - // Outgoing argument set up - subl MACRO_LITERAL(12), %esp // alignment padding - pushl %ebx // pass SP - pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() - pushl %edx // pass arg3 - pushl %ecx // pass arg2 - pushl %eax // pass arg1 - call VAR(cxx_name, 1) // cxx_name(arg1, arg2, Thread*, SP) - addl MACRO_LITERAL(32), %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 -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 %eax // push 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 + 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 - ret + VAR(return_macro, 2) // return or deliver exception +END_MACRO -DEFINE_FUNCTION art_unlock_object_from_code +MACRO3(TWO_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 // alignment padding pushl %edx // pass SP pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() + pushl %ecx // pass arg2 pushl %eax // pass arg1 - call SYMBOL(artUnlockObjectFromCode) // (Object*, Thread*, SP) - addl LITERAL(16), %esp // pop arguments + 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 ? - jnz 1f - ret -1: - DELIVER_PENDING_EXCEPTION + VAR(return_macro, 2) // return or deliver exception +END_MACRO -DEFINE_FUNCTION art_handle_fill_data_from_code +MACRO3(THREE_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 + mov %esp, %ebx // remember SP // Outgoing argument set up - pushl %edx // pass SP + subl MACRO_LITERAL(12), %esp // alignment padding + pushl %ebx // pass SP pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() + pushl %edx // pass arg3 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 + 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 - testl %eax, %eax // eax == 0 ? - jnz 1f - ret -1: + VAR(return_macro, 2) // return or deliver exception +END_MACRO + +MACRO0(RETURN_IF_EAX_NOT_ZERO) + 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) + 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 + +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 @@ DEFINE_FUNCTION art_memcpy 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 @@ DEFINE_FUNCTION art_lushr_from_code 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 @@ END_MACRO // 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 |