Implement const-class instruction.
Change-Id: If95d9eceff27c226312dcb3560323c7aee54fe66
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 7253cad..cdd2378 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -1237,9 +1237,88 @@
}
+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));
}