diff options
| -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 |