diff options
| author | 2012-01-14 03:43:35 +0800 | |
|---|---|---|
| committer | 2012-02-18 00:09:20 -0800 | |
| commit | 27b3025d4127137bb144864e30514958e836d5cb (patch) | |
| tree | 232f8ef8e835a21816f2ead1a7b56041c21f2088 /src/compiler_llvm/method_compiler.cc | |
| parent | 15377ddda5314e55ede6ebeaefc3e867ff5062ee (diff) | |
Implement const-class instruction.
Change-Id: If95d9eceff27c226312dcb3560323c7aee54fe66
Diffstat (limited to 'src/compiler_llvm/method_compiler.cc')
| -rw-r--r-- | src/compiler_llvm/method_compiler.cc | 81 |
1 files changed, 80 insertions, 1 deletions
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc index 7253cada70..cdd237820e 100644 --- a/src/compiler_llvm/method_compiler.cc +++ b/src/compiler_llvm/method_compiler.cc @@ -1237,9 +1237,88 @@ void MethodCompiler::EmitInsn_LoadConstantString(uint32_t dex_pc, } +llvm::Value* MethodCompiler::EmitLoadConstantClass(uint32_t dex_pc, + uint32_t type_idx) { + if (!compiler_->CanAccessTypeWithoutChecks(method_idx_, dex_cache_, + *dex_file_, type_idx)) { + llvm::Value* type_idx_value = irb_.getInt32(type_idx); + + llvm::Value* method_object_addr = EmitLoadMethodObjectAddr(); + + llvm::Function* runtime_func = + irb_.GetRuntime(InitializeTypeAndVerifyAccess); + + llvm::Value* type_object_addr = + irb_.CreateCall2(runtime_func, type_idx_value, method_object_addr); + + EmitGuard_ExceptionLandingPad(dex_pc); + + return type_object_addr; + + } else { + // Try to load the class (type) object from the test cache. + llvm::Value* type_field_addr = + EmitLoadDexCacheResolvedTypeFieldAddr(type_idx); + + llvm::Value* type_object_addr = irb_.CreateLoad(type_field_addr); + + if (compiler_->CanAssumeTypeIsPresentInDexCache(dex_cache_, type_idx)) { + return type_object_addr; + } + + llvm::BasicBlock* block_original = irb_.GetInsertBlock(); + + // Test whether class (type) object is in the dex cache or not + llvm::Value* equal_null = + irb_.CreateICmpEQ(type_object_addr, irb_.getJNull()); + + llvm::BasicBlock* block_cont = + CreateBasicBlockWithDexPC(dex_pc, "cont"); + + llvm::BasicBlock* block_load_class = + CreateBasicBlockWithDexPC(dex_pc, "load_class"); + + irb_.CreateCondBr(equal_null, block_load_class, block_cont); + + // Failback routine to load the class object + irb_.SetInsertPoint(block_load_class); + + llvm::Function* runtime_func = irb_.GetRuntime(InitializeType); + + llvm::Constant* type_idx_value = irb_.getInt32(type_idx); + + llvm::Value* method_object_addr = EmitLoadMethodObjectAddr(); + + llvm::Value* loaded_type_object_addr = + irb_.CreateCall2(runtime_func, type_idx_value, method_object_addr); + + EmitGuard_ExceptionLandingPad(dex_pc); + + llvm::BasicBlock* block_after_load_class = irb_.GetInsertBlock(); + + irb_.CreateBr(block_cont); + + // Now the class object must be loaded + irb_.SetInsertPoint(block_cont); + + llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2); + + phi->addIncoming(type_object_addr, block_original); + phi->addIncoming(loaded_type_object_addr, block_after_load_class); + + return phi; + } +} + + void MethodCompiler::EmitInsn_LoadConstantClass(uint32_t dex_pc, Instruction const* insn) { - // UNIMPLEMENTED(WARNING); + + Instruction::DecodedInstruction dec_insn(insn); + + llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, dec_insn.vB_); + EmitStoreDalvikReg(dec_insn.vA_, kObject, kAccurate, type_object_addr); + irb_.CreateBr(GetNextBasicBlock(dex_pc)); } |