diff options
| author | 2012-04-24 13:08:45 +0800 | |
|---|---|---|
| committer | 2012-05-02 04:19:59 -0700 | |
| commit | 86f5067d92f380e3a167d9c786b5f5c15d8dd0db (patch) | |
| tree | c155994f51b722aad1d75717865985b291845271 | |
| parent | 19c350a9197411d427b71b7ab15b18417701de10 (diff) | |
Change to implement fill-array-data with runtime function.
We can get the array data payload from the DexFile, thus
we don't have to duplicate it in the ELF image. As the
result we can reduce the size of the Oat file.
Change-Id: I08e241a43e2d7fb1b20638da68b5dfae61b120bb
| -rw-r--r-- | src/compiler_llvm/art_module.ll | 4 | ||||
| -rw-r--r-- | src/compiler_llvm/generated/art_module.cc | 57 | ||||
| -rw-r--r-- | src/compiler_llvm/method_compiler.cc | 68 | ||||
| -rw-r--r-- | src/compiler_llvm/runtime_support_func_list.h | 1 | ||||
| -rw-r--r-- | src/compiler_llvm/runtime_support_llvm.cc | 38 |
5 files changed, 99 insertions, 69 deletions
diff --git a/src/compiler_llvm/art_module.ll b/src/compiler_llvm/art_module.ll index 6d4b56b6a1..a2da2b6376 100644 --- a/src/compiler_llvm/art_module.ll +++ b/src/compiler_llvm/art_module.ll @@ -144,6 +144,10 @@ declare %JavaObject* @art_decode_jobject_in_thread(%JavaObject*, %JavaObject*) +declare void @art_fill_array_data_from_code(%JavaObject*, i32, + %JavaObject*, i32) + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Type Checking, in the nature of casting ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/src/compiler_llvm/generated/art_module.cc b/src/compiler_llvm/generated/art_module.cc index 1237ec05be..b3963ef8dd 100644 --- a/src/compiler_llvm/generated/art_module.cc +++ b/src/compiler_llvm/generated/art_module.cc @@ -1,4 +1,4 @@ -// Generated with tools/gen_art_module_cc.sh +// Generated with ../tools/gen_art_module_cc.sh #pragma GCC diagnostic ignored "-Wframe-larger-than=" @@ -278,52 +278,62 @@ FunctionType* FuncTy_28 = FunctionType::get( std::vector<Type*>FuncTy_29_args; FuncTy_29_args.push_back(PointerTy_1); +FuncTy_29_args.push_back(IntegerType::get(mod->getContext(), 32)); FuncTy_29_args.push_back(PointerTy_1); +FuncTy_29_args.push_back(IntegerType::get(mod->getContext(), 32)); FunctionType* FuncTy_29 = FunctionType::get( - /*Result=*/IntegerType::get(mod->getContext(), 32), + /*Result=*/Type::getVoidTy(mod->getContext()), /*Params=*/FuncTy_29_args, /*isVarArg=*/false); std::vector<Type*>FuncTy_30_args; -FuncTy_30_args.push_back(Type::getDoubleTy(mod->getContext())); +FuncTy_30_args.push_back(PointerTy_1); +FuncTy_30_args.push_back(PointerTy_1); FunctionType* FuncTy_30 = FunctionType::get( - /*Result=*/IntegerType::get(mod->getContext(), 64), + /*Result=*/IntegerType::get(mod->getContext(), 32), /*Params=*/FuncTy_30_args, /*isVarArg=*/false); std::vector<Type*>FuncTy_31_args; FuncTy_31_args.push_back(Type::getDoubleTy(mod->getContext())); FunctionType* FuncTy_31 = FunctionType::get( - /*Result=*/IntegerType::get(mod->getContext(), 32), + /*Result=*/IntegerType::get(mod->getContext(), 64), /*Params=*/FuncTy_31_args, /*isVarArg=*/false); std::vector<Type*>FuncTy_32_args; -FuncTy_32_args.push_back(Type::getFloatTy(mod->getContext())); +FuncTy_32_args.push_back(Type::getDoubleTy(mod->getContext())); FunctionType* FuncTy_32 = FunctionType::get( - /*Result=*/IntegerType::get(mod->getContext(), 64), + /*Result=*/IntegerType::get(mod->getContext(), 32), /*Params=*/FuncTy_32_args, /*isVarArg=*/false); std::vector<Type*>FuncTy_33_args; FuncTy_33_args.push_back(Type::getFloatTy(mod->getContext())); FunctionType* FuncTy_33 = FunctionType::get( - /*Result=*/IntegerType::get(mod->getContext(), 32), + /*Result=*/IntegerType::get(mod->getContext(), 64), /*Params=*/FuncTy_33_args, /*isVarArg=*/false); std::vector<Type*>FuncTy_34_args; -FuncTy_34_args.push_back(PointerTy_1); +FuncTy_34_args.push_back(Type::getFloatTy(mod->getContext())); FunctionType* FuncTy_34 = FunctionType::get( - /*Result=*/PointerTy_1, + /*Result=*/IntegerType::get(mod->getContext(), 32), /*Params=*/FuncTy_34_args, /*isVarArg=*/false); std::vector<Type*>FuncTy_35_args; FuncTy_35_args.push_back(PointerTy_1); FunctionType* FuncTy_35 = FunctionType::get( - /*Result=*/Type::getVoidTy(mod->getContext()), + /*Result=*/PointerTy_1, /*Params=*/FuncTy_35_args, + /*isVarArg=*/false); + +std::vector<Type*>FuncTy_36_args; +FuncTy_36_args.push_back(PointerTy_1); +FunctionType* FuncTy_36 = FunctionType::get( + /*Result=*/Type::getVoidTy(mod->getContext()), + /*Params=*/FuncTy_36_args, /*isVarArg=*/true); @@ -857,10 +867,21 @@ func_art_decode_jobject_in_thread->setCallingConv(CallingConv::C); AttrListPtr func_art_decode_jobject_in_thread_PAL; func_art_decode_jobject_in_thread->setAttributes(func_art_decode_jobject_in_thread_PAL); +Function* func_art_fill_array_data_from_code = mod->getFunction("art_fill_array_data_from_code"); +if (!func_art_fill_array_data_from_code) { +func_art_fill_array_data_from_code = Function::Create( + /*Type=*/FuncTy_29, + /*Linkage=*/GlobalValue::ExternalLinkage, + /*Name=*/"art_fill_array_data_from_code", mod); // (external, no body) +func_art_fill_array_data_from_code->setCallingConv(CallingConv::C); +} +AttrListPtr func_art_fill_array_data_from_code_PAL; +func_art_fill_array_data_from_code->setAttributes(func_art_fill_array_data_from_code_PAL); + Function* func_art_is_assignable_from_code = mod->getFunction("art_is_assignable_from_code"); if (!func_art_is_assignable_from_code) { func_art_is_assignable_from_code = Function::Create( - /*Type=*/FuncTy_29, + /*Type=*/FuncTy_30, /*Linkage=*/GlobalValue::ExternalLinkage, /*Name=*/"art_is_assignable_from_code", mod); // (external, no body) func_art_is_assignable_from_code->setCallingConv(CallingConv::C); @@ -893,7 +914,7 @@ func_art_check_put_array_element_from_code->setAttributes(func_art_check_put_arr Function* func_D2L = mod->getFunction("D2L"); if (!func_D2L) { func_D2L = Function::Create( - /*Type=*/FuncTy_30, + /*Type=*/FuncTy_31, /*Linkage=*/GlobalValue::ExternalLinkage, /*Name=*/"D2L", mod); // (external, no body) func_D2L->setCallingConv(CallingConv::C); @@ -904,7 +925,7 @@ func_D2L->setAttributes(func_D2L_PAL); Function* func_D2I = mod->getFunction("D2I"); if (!func_D2I) { func_D2I = Function::Create( - /*Type=*/FuncTy_31, + /*Type=*/FuncTy_32, /*Linkage=*/GlobalValue::ExternalLinkage, /*Name=*/"D2I", mod); // (external, no body) func_D2I->setCallingConv(CallingConv::C); @@ -915,7 +936,7 @@ func_D2I->setAttributes(func_D2I_PAL); Function* func_F2L = mod->getFunction("F2L"); if (!func_F2L) { func_F2L = Function::Create( - /*Type=*/FuncTy_32, + /*Type=*/FuncTy_33, /*Linkage=*/GlobalValue::ExternalLinkage, /*Name=*/"F2L", mod); // (external, no body) func_F2L->setCallingConv(CallingConv::C); @@ -926,7 +947,7 @@ func_F2L->setAttributes(func_F2L_PAL); Function* func_F2I = mod->getFunction("F2I"); if (!func_F2I) { func_F2I = Function::Create( - /*Type=*/FuncTy_33, + /*Type=*/FuncTy_34, /*Linkage=*/GlobalValue::ExternalLinkage, /*Name=*/"F2I", mod); // (external, no body) func_F2I->setCallingConv(CallingConv::C); @@ -948,7 +969,7 @@ func_art_mark_gc_card_from_code->setAttributes(func_art_mark_gc_card_from_code_P Function* func_art_fix_stub_from_code = mod->getFunction("art_fix_stub_from_code"); if (!func_art_fix_stub_from_code) { func_art_fix_stub_from_code = Function::Create( - /*Type=*/FuncTy_34, + /*Type=*/FuncTy_35, /*Linkage=*/GlobalValue::ExternalLinkage, /*Name=*/"art_fix_stub_from_code", mod); // (external, no body) func_art_fix_stub_from_code->setCallingConv(CallingConv::C); @@ -959,7 +980,7 @@ func_art_fix_stub_from_code->setAttributes(func_art_fix_stub_from_code_PAL); Function* func_art_proxy_invoke_handler_from_code = mod->getFunction("art_proxy_invoke_handler_from_code"); if (!func_art_proxy_invoke_handler_from_code) { func_art_proxy_invoke_handler_from_code = Function::Create( - /*Type=*/FuncTy_35, + /*Type=*/FuncTy_36, /*Linkage=*/GlobalValue::ExternalLinkage, /*Name=*/"art_proxy_invoke_handler_from_code", mod); // (external, no body) func_art_proxy_invoke_handler_from_code->setCallingConv(CallingConv::C); diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc index 2c0fef146e..e44481182f 100644 --- a/src/compiler_llvm/method_compiler.cc +++ b/src/compiler_llvm/method_compiler.cc @@ -1893,65 +1893,31 @@ void MethodCompiler::EmitInsn_FillArrayData(uint32_t dex_pc, reinterpret_cast<const Instruction::ArrayDataPayload*>( code_item_->insns_ + payload_offset); - uint32_t size_in_bytes = payload->element_width * payload->element_count; - - // Load and check the array + // Load array object llvm::Value* array_addr = EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate); - EmitGuard_NullPointerException(dex_pc, array_addr); + if (payload->element_count == 0) { + // When the number of the elements in the payload is zero, we don't have + // to copy any numbers. However, we should check whether the array object + // address is equal to null or not. + EmitGuard_NullPointerException(dex_pc, array_addr); + } else { + // To save the code size, we are going to call the runtime function to + // copy the content from DexFile. - if (payload->element_count > 0) { - // Test: Is array length big enough? - llvm::Constant* last_index = irb_.getJInt(payload->element_count - 1); + // NOTE: We will check for the NullPointerException in the runtime. - EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array_addr, last_index); + llvm::Function* runtime_func = irb_.GetRuntime(FillArrayData); - // Get array data field - llvm::Value* data_field_offset_value = - irb_.getPtrEquivInt(Array::DataOffset(payload->element_width).Int32Value()); + llvm::Value* method_object_addr = EmitLoadMethodObjectAddr(); - llvm::Value* data_field_addr = - irb_.CreatePtrDisp(array_addr, data_field_offset_value, - irb_.getInt8Ty()->getPointerTo()); + EmitUpdateDexPC(dex_pc); - // Emit payload to bitcode constant pool - std::vector<llvm::Constant*> const_pool_data; - for (uint32_t i = 0; i < size_in_bytes; ++i) { - const_pool_data.push_back(irb_.getInt8(payload->data[i])); - } + irb_.CreateCall4(runtime_func, + method_object_addr, irb_.getInt32(dex_pc), + array_addr, irb_.getInt32(payload_offset)); - llvm::Constant* const_pool_data_array_value = llvm::ConstantArray::get( - llvm::ArrayType::get(irb_.getInt8Ty(), size_in_bytes), const_pool_data); - - llvm::Value* const_pool_data_array_addr = - new llvm::GlobalVariable(*module_, - const_pool_data_array_value->getType(), - false, llvm::GlobalVariable::InternalLinkage, - const_pool_data_array_value, - "array_data_payload"); - - // Find the memcpy intrinsic - llvm::Type* memcpy_arg_types[] = { - llvm::Type::getInt8Ty(*context_)->getPointerTo(), - llvm::Type::getInt8Ty(*context_)->getPointerTo(), - llvm::Type::getInt32Ty(*context_) - }; - - llvm::Function* memcpy_intrinsic = - llvm::Intrinsic::getDeclaration(module_, - llvm::Intrinsic::memcpy, - memcpy_arg_types); - - // Copy now! - llvm::Value *args[] = { - data_field_addr, - irb_.CreateConstGEP2_32(const_pool_data_array_addr, 0, 0), - irb_.getInt32(size_in_bytes), - irb_.getInt32(0), // alignment: no guarantee - irb_.getFalse() // is_volatile: false - }; - - irb_.CreateCall(memcpy_intrinsic, args); + EmitGuard_ExceptionLandingPad(dex_pc); } irb_.CreateBr(GetNextBasicBlock(dex_pc)); diff --git a/src/compiler_llvm/runtime_support_func_list.h b/src/compiler_llvm/runtime_support_func_list.h index 7a51b90f89..5cf237401d 100644 --- a/src/compiler_llvm/runtime_support_func_list.h +++ b/src/compiler_llvm/runtime_support_func_list.h @@ -59,6 +59,7 @@ V(Get64Instance, art_get64_instance_from_code) \ V(GetObjectInstance, art_get_obj_instance_from_code) \ V(InitializeStaticStorage, art_initialize_static_storage_from_code) \ + V(FillArrayData, art_fill_array_data_from_code) \ V(IsExceptionPending, art_is_exception_pending_from_code) \ V(FindCatchBlock, art_find_catch_block_from_code) \ V(MarkGCCard, art_mark_gc_card_from_code) \ diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc index bdfd222a44..d0f6e8c7ed 100644 --- a/src/compiler_llvm/runtime_support_llvm.cc +++ b/src/compiler_llvm/runtime_support_llvm.cc @@ -15,6 +15,8 @@ */ #include "class_linker.h" +#include "dex_file.h" +#include "dex_instruction.h" #include "nth_caller_visitor.h" #include "object.h" #include "object_utils.h" @@ -496,6 +498,42 @@ Object* art_decode_jobject_in_thread(Thread* thread, jobject obj) { return thread->DecodeJObject(obj); } +void art_fill_array_data_from_code(Method* method, uint32_t dex_pc, + Array* array, uint32_t payload_offset) { + // Test: Is array equal to null? (Guard NullPointerException) + if (UNLIKELY(array == NULL)) { + art_throw_null_pointer_exception_from_code(dex_pc); + return; + } + + // Find the payload from the CodeItem + MethodHelper mh(method); + const DexFile::CodeItem* code_item = mh.GetCodeItem(); + + DCHECK_GT(code_item->insns_size_in_code_units_, payload_offset); + + const Instruction::ArrayDataPayload* payload = + reinterpret_cast<const Instruction::ArrayDataPayload*>( + code_item->insns_ + payload_offset); + + DCHECK_EQ(payload->ident, + static_cast<uint16_t>(Instruction::kArrayDataSignature)); + + // Test: Is array big enough? + uint32_t array_len = static_cast<uint32_t>(array->GetLength()); + if (UNLIKELY(array_len < payload->element_count)) { + int32_t last_index = payload->element_count - 1; + art_throw_array_bounds_from_code(array_len, last_index); + return; + } + + // Copy the data + size_t size = payload->element_width * payload->element_count; + memcpy(array->GetRawData(payload->element_width), payload->data, size); +} + + + //---------------------------------------------------------------------------- // Type checking, in the nature of casting //---------------------------------------------------------------------------- |