Remove CodeAllocator and the extra copy of generated code.

The code used to copy the final generated code twice: from assembler to
CodeAllocator, and then to CodeAllocator to SwapAllocator/JitMemory.

The assemblers never depended on the exact location of the generated
code, so just drop that feature.

Test: test.py
Change-Id: I8dc82e4926097092b9aac336a5a5d40f79dc62ca
diff --git a/compiler/jni/jni_cfi_test.cc b/compiler/jni/jni_cfi_test.cc
index 70cf2d4..ae5f2d0 100644
--- a/compiler/jni/jni_cfi_test.cc
+++ b/compiler/jni/jni_cfi_test.cc
@@ -99,7 +99,7 @@
     jni_asm->FinalizeCode();
     std::vector<uint8_t> actual_asm(jni_asm->CodeSize());
     MemoryRegion code(&actual_asm[0], actual_asm.size());
-    jni_asm->FinalizeInstructions(code);
+    jni_asm->CopyInstructions(code);
     ASSERT_EQ(jni_asm->cfi().GetCurrentCFAOffset(), frame_size);
     const std::vector<uint8_t>& actual_cfi = *(jni_asm->cfi().data());
 
diff --git a/compiler/jni/quick/jni_compiler.cc b/compiler/jni/quick/jni_compiler.cc
index 763d379..1e3852a 100644
--- a/compiler/jni/quick/jni_compiler.cc
+++ b/compiler/jni/quick/jni_compiler.cc
@@ -724,7 +724,7 @@
   size_t cs = __ CodeSize();
   std::vector<uint8_t> managed_code(cs);
   MemoryRegion code(&managed_code[0], managed_code.size());
-  __ FinalizeInstructions(code);
+  __ CopyInstructions(code);
 
   return JniCompiledMethod(instruction_set,
                            std::move(managed_code),
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index 78aa328..d6d9009 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -263,7 +263,7 @@
   code_generation_data_ = CodeGenerationData::Create(graph_->GetArenaStack(), GetInstructionSet());
 }
 
-void CodeGenerator::Compile(CodeAllocator* allocator) {
+void CodeGenerator::Compile() {
   InitializeCodeGenerationData();
 
   // The register allocator already called `InitializeCodeGeneration`,
@@ -328,17 +328,13 @@
   }
 
   // Finalize instructions in assember;
-  Finalize(allocator);
+  Finalize();
 
   GetStackMapStream()->EndMethod(GetAssembler()->CodeSize());
 }
 
-void CodeGenerator::Finalize(CodeAllocator* allocator) {
-  size_t code_size = GetAssembler()->CodeSize();
-  uint8_t* buffer = allocator->Allocate(code_size);
-
-  MemoryRegion code(buffer, code_size);
-  GetAssembler()->FinalizeInstructions(code);
+void CodeGenerator::Finalize() {
+  GetAssembler()->FinalizeCode();
 }
 
 void CodeGenerator::EmitLinkerPatches(
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index 5f4f377..bcbffe4 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -87,18 +87,6 @@
 class LinkerPatch;
 }  // namespace linker
 
-class CodeAllocator {
- public:
-  CodeAllocator() {}
-  virtual ~CodeAllocator() {}
-
-  virtual uint8_t* Allocate(size_t size) = 0;
-  virtual ArrayRef<const uint8_t> GetMemory() const = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CodeAllocator);
-};
-
 class SlowPathCode : public DeletableArenaObject<kArenaAllocSlowPaths> {
  public:
   explicit SlowPathCode(HInstruction* instruction) : instruction_(instruction) {
@@ -205,7 +193,7 @@
 class CodeGenerator : public DeletableArenaObject<kArenaAllocCodeGenerator> {
  public:
   // Compiles the graph to executable instructions.
-  void Compile(CodeAllocator* allocator);
+  void Compile();
   static std::unique_ptr<CodeGenerator> Create(HGraph* graph,
                                                const CompilerOptions& compiler_options,
                                                OptimizingCompilerStats* stats = nullptr);
@@ -226,7 +214,7 @@
   }
 
   virtual void Initialize() = 0;
-  virtual void Finalize(CodeAllocator* allocator);
+  virtual void Finalize();
   virtual void EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches);
   virtual bool NeedsThunkCode(const linker::LinkerPatch& patch) const;
   virtual void EmitThunkCode(const linker::LinkerPatch& patch,
@@ -736,6 +724,11 @@
   static QuickEntrypointEnum GetArrayAllocationEntrypoint(HNewArray* new_array);
   static ScaleFactor ScaleFactorForType(DataType::Type type);
 
+  ArrayRef<const uint8_t> GetCode() const {
+    return ArrayRef<const uint8_t>(GetAssembler().CodeBufferBaseAddress(),
+                                   GetAssembler().CodeSize());
+  }
+
  protected:
   // Patch info used for recording locations of required linker patches and their targets,
   // i.e. target method, string, type or code identified by their dex file and index,
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index fe81b31..130d9bb 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -1040,7 +1040,7 @@
   }
 }
 
-void CodeGeneratorARM64::Finalize(CodeAllocator* allocator) {
+void CodeGeneratorARM64::Finalize() {
   EmitJumpTables();
 
   // Emit JIT baker read barrier slow paths.
@@ -1055,11 +1055,11 @@
   // Ensure we emit the literal pool.
   __ FinalizeCode();
 
-  CodeGenerator::Finalize(allocator);
+  CodeGenerator::Finalize();
 
   // Verify Baker read barrier linker patches.
   if (kIsDebugBuild) {
-    ArrayRef<const uint8_t> code = allocator->GetMemory();
+    ArrayRef<const uint8_t> code(GetCode());
     for (const BakerReadBarrierPatchInfo& info : baker_read_barrier_patches_) {
       DCHECK(info.label.IsBound());
       uint32_t literal_offset = info.label.GetLocation();
@@ -5371,7 +5371,7 @@
   assembler.FinalizeCode();
   code->resize(assembler.CodeSize());
   MemoryRegion code_region(code->data(), code->size());
-  assembler.FinalizeInstructions(code_region);
+  assembler.CopyInstructions(code_region);
 }
 
 vixl::aarch64::Literal<uint32_t>* CodeGeneratorARM64::DeduplicateUint32Literal(uint32_t value) {
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index b256307..52c5377 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -698,7 +698,7 @@
     return jump_tables_.back().get();
   }
 
-  void Finalize(CodeAllocator* allocator) override;
+  void Finalize() override;
 
   // Code generation helpers.
   void MoveConstant(vixl::aarch64::CPURegister destination, HConstant* constant);
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index b61f6b5..36bf421 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -2025,7 +2025,7 @@
 
 #define __ reinterpret_cast<ArmVIXLAssembler*>(GetAssembler())->GetVIXLAssembler()->  // NOLINT
 
-void CodeGeneratorARMVIXL::Finalize(CodeAllocator* allocator) {
+void CodeGeneratorARMVIXL::Finalize() {
   FixJumpTables();
 
   // Emit JIT baker read barrier slow paths.
@@ -2038,11 +2038,11 @@
   }
 
   GetAssembler()->FinalizeCode();
-  CodeGenerator::Finalize(allocator);
+  CodeGenerator::Finalize();
 
   // Verify Baker read barrier linker patches.
   if (kIsDebugBuild) {
-    ArrayRef<const uint8_t> code = allocator->GetMemory();
+    ArrayRef<const uint8_t> code(GetCode());
     for (const BakerReadBarrierPatchInfo& info : baker_read_barrier_patches_) {
       DCHECK(info.label.IsBound());
       uint32_t literal_offset = info.label.GetLocation();
@@ -9874,7 +9874,7 @@
   assembler.FinalizeCode();
   code->resize(assembler.CodeSize());
   MemoryRegion code_region(code->data(), code->size());
-  assembler.FinalizeInstructions(code_region);
+  assembler.CopyInstructions(code_region);
 }
 
 VIXLUInt32Literal* CodeGeneratorARMVIXL::DeduplicateUint32Literal(
diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h
index f5abe69..0175448 100644
--- a/compiler/optimizing/code_generator_arm_vixl.h
+++ b/compiler/optimizing/code_generator_arm_vixl.h
@@ -620,7 +620,7 @@
     block_labels_.resize(GetGraph()->GetBlocks().size());
   }
 
-  void Finalize(CodeAllocator* allocator) override;
+  void Finalize() override;
 
   bool NeedsTwoRegisters(DataType::Type type) const override {
     return type == DataType::Type::kFloat64 || type == DataType::Type::kInt64;
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 3ae6515..da943bf 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -8930,7 +8930,7 @@
   const HX86PackedSwitch* switch_instr_;
 };
 
-void CodeGeneratorX86::Finalize(CodeAllocator* allocator) {
+void CodeGeneratorX86::Finalize() {
   // Generate the constant area if needed.
   X86Assembler* assembler = GetAssembler();
 
@@ -8950,7 +8950,7 @@
   }
 
   // And finish up.
-  CodeGenerator::Finalize(allocator);
+  CodeGenerator::Finalize();
 }
 
 Address CodeGeneratorX86::LiteralDoubleAddress(double v,
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index 0905f32..aa25528 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -635,7 +635,7 @@
 
   Address LiteralCaseTable(HX86PackedSwitch* switch_instr, Register reg, Register value);
 
-  void Finalize(CodeAllocator* allocator) override;
+  void Finalize() override;
 
   // Fast path implementation of ReadBarrier::Barrier for a heap
   // reference field load when Baker's read barriers are used.
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 7c61519..93b9660 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -8170,7 +8170,7 @@
   const HPackedSwitch* switch_instr_;
 };
 
-void CodeGeneratorX86_64::Finalize(CodeAllocator* allocator) {
+void CodeGeneratorX86_64::Finalize() {
   // Generate the constant area if needed.
   X86_64Assembler* assembler = GetAssembler();
   if (!assembler->IsConstantAreaEmpty() || !fixups_to_jump_tables_.empty()) {
@@ -8188,7 +8188,7 @@
   }
 
   // And finish up.
-  CodeGenerator::Finalize(allocator);
+  CodeGenerator::Finalize();
 }
 
 Address CodeGeneratorX86_64::LiteralDoubleAddress(double v) {
diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h
index e1ce3a9..5a940c1 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -468,7 +468,7 @@
   void SetupBlockedRegisters() const override;
   void DumpCoreRegister(std::ostream& stream, int reg) const override;
   void DumpFloatingPointRegister(std::ostream& stream, int reg) const override;
-  void Finalize(CodeAllocator* allocator) override;
+  void Finalize() override;
 
   InstructionSet GetInstructionSet() const override {
     return InstructionSet::kX86_64;
diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc
index 2d9acc4..f890ba9 100644
--- a/compiler/optimizing/codegen_test.cc
+++ b/compiler/optimizing/codegen_test.cc
@@ -733,8 +733,7 @@
   move->AddMove(Location::StackSlot(8192), Location::StackSlot(0), DataType::Type::kInt32, nullptr);
   codegen.GetMoveResolver()->EmitNativeCode(move);
 
-  InternalCodeAllocator code_allocator;
-  codegen.Finalize(&code_allocator);
+  codegen.Finalize();
 }
 #endif
 
@@ -785,8 +784,7 @@
                 nullptr);
   codegen.GetMoveResolver()->EmitNativeCode(move);
 
-  InternalCodeAllocator code_allocator;
-  codegen.Finalize(&code_allocator);
+  codegen.Finalize();
 }
 
 // Check that ParallelMoveResolver works fine for ARM64 for both cases when SIMD is on and off.
@@ -821,8 +819,7 @@
     graph->SetHasSIMD(false);
   }
 
-  InternalCodeAllocator code_allocator;
-  codegen.Finalize(&code_allocator);
+  codegen.Finalize();
 }
 
 // Check that ART ISA Features are propagated to VIXL for arm64 (using cortex-a75 as example).
diff --git a/compiler/optimizing/codegen_test_utils.h b/compiler/optimizing/codegen_test_utils.h
index 53163da..a8425c9 100644
--- a/compiler/optimizing/codegen_test_utils.h
+++ b/compiler/optimizing/codegen_test_utils.h
@@ -167,28 +167,6 @@
 };
 #endif
 
-class InternalCodeAllocator : public CodeAllocator {
- public:
-  InternalCodeAllocator() : size_(0) { }
-
-  uint8_t* Allocate(size_t size) override {
-    size_ = size;
-    memory_.reset(new uint8_t[size]);
-    return memory_.get();
-  }
-
-  size_t GetSize() const { return size_; }
-  ArrayRef<const uint8_t> GetMemory() const override {
-    return ArrayRef<const uint8_t>(memory_.get(), size_);
-  }
-
- private:
-  size_t size_;
-  std::unique_ptr<uint8_t[]> memory_;
-
-  DISALLOW_COPY_AND_ASSIGN(InternalCodeAllocator);
-};
-
 static bool CanExecuteOnHardware(InstructionSet target_isa) {
   return (target_isa == kRuntimeISA)
       // Handle the special case of ARM, with two instructions sets (ARM32 and Thumb-2).
@@ -247,8 +225,7 @@
 }
 
 template <typename Expected>
-static void Run(const InternalCodeAllocator& allocator,
-                const CodeGenerator& codegen,
+static void Run(const CodeGenerator& codegen,
                 bool has_result,
                 Expected expected) {
   InstructionSet target_isa = codegen.GetInstructionSet();
@@ -260,7 +237,7 @@
   };
   CodeHolder code_holder;
   const void* method_code =
-      code_holder.MakeExecutable(allocator.GetMemory(), ArrayRef<const uint8_t>(), target_isa);
+      code_holder.MakeExecutable(codegen.GetCode(), ArrayRef<const uint8_t>(), target_isa);
 
   using fptr = Expected (*)();
   fptr f = reinterpret_cast<fptr>(reinterpret_cast<uintptr_t>(method_code));
@@ -294,9 +271,8 @@
     register_allocator->AllocateRegisters();
   }
   hook_before_codegen(graph);
-  InternalCodeAllocator allocator;
-  codegen->Compile(&allocator);
-  Run(allocator, *codegen, has_result, expected);
+  codegen->Compile();
+  Run(*codegen, has_result, expected);
 }
 
 template <typename Expected>
diff --git a/compiler/optimizing/optimizing_cfi_test.cc b/compiler/optimizing/optimizing_cfi_test.cc
index f12e748..632c32a 100644
--- a/compiler/optimizing/optimizing_cfi_test.cc
+++ b/compiler/optimizing/optimizing_cfi_test.cc
@@ -89,7 +89,7 @@
 
   void Finish() {
     code_gen_->GenerateFrameExit();
-    code_gen_->Finalize(&code_allocator_);
+    code_gen_->Finalize();
   }
 
   void Check(InstructionSet isa,
@@ -97,7 +97,7 @@
              const std::vector<uint8_t>& expected_asm,
              const std::vector<uint8_t>& expected_cfi) {
     // Get the outputs.
-    ArrayRef<const uint8_t> actual_asm = code_allocator_.GetMemory();
+    ArrayRef<const uint8_t> actual_asm = code_gen_->GetCode();
     Assembler* opt_asm = code_gen_->GetAssembler();
     ArrayRef<const uint8_t> actual_cfi(*(opt_asm->cfi().data()));
 
@@ -123,27 +123,9 @@
   }
 
  private:
-  class InternalCodeAllocator : public CodeAllocator {
-   public:
-    InternalCodeAllocator() {}
-
-    uint8_t* Allocate(size_t size) override {
-      memory_.resize(size);
-      return memory_.data();
-    }
-
-    ArrayRef<const uint8_t> GetMemory() const override { return ArrayRef<const uint8_t>(memory_); }
-
-   private:
-    std::vector<uint8_t> memory_;
-
-    DISALLOW_COPY_AND_ASSIGN(InternalCodeAllocator);
-  };
-
   HGraph* graph_;
   std::unique_ptr<CodeGenerator> code_gen_;
   ArenaVector<HBasicBlock*> blocks_;
-  InternalCodeAllocator code_allocator_;
 };
 
 #define TEST_ISA(isa)                                                 \
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 8207501..e4c9b27 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -69,28 +69,6 @@
 static constexpr const char* kPassNameSeparator = "$";
 
 /**
- * Used by the code generator, to allocate the code in a vector.
- */
-class CodeVectorAllocator final : public CodeAllocator {
- public:
-  explicit CodeVectorAllocator(ArenaAllocator* allocator)
-      : memory_(allocator->Adapter(kArenaAllocCodeBuffer)) {}
-
-  uint8_t* Allocate(size_t size) override {
-    memory_.resize(size);
-    return &memory_[0];
-  }
-
-  ArrayRef<const uint8_t> GetMemory() const override { return ArrayRef<const uint8_t>(memory_); }
-  uint8_t* GetData() { return memory_.data(); }
-
- private:
-  ArenaVector<uint8_t> memory_;
-
-  DISALLOW_COPY_AND_ASSIGN(CodeVectorAllocator);
-};
-
-/**
  * Filter to apply to the visualizer. Methods whose name contain that filter will
  * be dumped.
  */
@@ -361,7 +339,6 @@
 
   // Create a 'CompiledMethod' for an optimized graph.
   CompiledMethod* Emit(ArenaAllocator* allocator,
-                       CodeVectorAllocator* code_allocator,
                        CodeGenerator* codegen,
                        bool is_intrinsic,
                        const dex::CodeItem* item) const;
@@ -372,10 +349,8 @@
   // 1) Builds the graph. Returns null if it failed to build it.
   // 2) Transforms the graph to SSA. Returns null if it failed.
   // 3) Runs optimizations on the graph, including register allocator.
-  // 4) Generates code with the `code_allocator` provided.
   CodeGenerator* TryCompile(ArenaAllocator* allocator,
                             ArenaStack* arena_stack,
-                            CodeVectorAllocator* code_allocator,
                             const DexCompilationUnit& dex_compilation_unit,
                             ArtMethod* method,
                             CompilationKind compilation_kind,
@@ -383,7 +358,6 @@
 
   CodeGenerator* TryCompileIntrinsic(ArenaAllocator* allocator,
                                      ArenaStack* arena_stack,
-                                     CodeVectorAllocator* code_allocator,
                                      const DexCompilationUnit& dex_compilation_unit,
                                      ArtMethod* method,
                                      VariableSizedHandleScope* handles) const;
@@ -719,7 +693,6 @@
 }
 
 CompiledMethod* OptimizingCompiler::Emit(ArenaAllocator* allocator,
-                                         CodeVectorAllocator* code_allocator,
                                          CodeGenerator* codegen,
                                          bool is_intrinsic,
                                          const dex::CodeItem* code_item_for_osr_check) const {
@@ -729,7 +702,7 @@
   CompiledCodeStorage* storage = GetCompiledCodeStorage();
   CompiledMethod* compiled_method = storage->CreateCompiledMethod(
       codegen->GetInstructionSet(),
-      code_allocator->GetMemory(),
+      codegen->GetCode(),
       ArrayRef<const uint8_t>(stack_map),
       ArrayRef<const uint8_t>(*codegen->GetAssembler()->cfi().data()),
       ArrayRef<const linker::LinkerPatch>(linker_patches),
@@ -749,7 +722,6 @@
 
 CodeGenerator* OptimizingCompiler::TryCompile(ArenaAllocator* allocator,
                                               ArenaStack* arena_stack,
-                                              CodeVectorAllocator* code_allocator,
                                               const DexCompilationUnit& dex_compilation_unit,
                                               ArtMethod* method,
                                               CompilationKind compilation_kind,
@@ -914,7 +886,7 @@
                     regalloc_strategy,
                     compilation_stats_.get());
 
-  codegen->Compile(code_allocator);
+  codegen->Compile();
   pass_observer.DumpDisassembly();
 
   MaybeRecordStat(compilation_stats_.get(), MethodCompilationStat::kCompiledBytecode);
@@ -924,7 +896,6 @@
 CodeGenerator* OptimizingCompiler::TryCompileIntrinsic(
     ArenaAllocator* allocator,
     ArenaStack* arena_stack,
-    CodeVectorAllocator* code_allocator,
     const DexCompilationUnit& dex_compilation_unit,
     ArtMethod* method,
     VariableSizedHandleScope* handles) const {
@@ -1013,7 +984,7 @@
     return nullptr;
   }
 
-  codegen->Compile(code_allocator);
+  codegen->Compile();
   pass_observer.DumpDisassembly();
 
   VLOG(compiler) << "Compiled intrinsic: " << method->GetIntrinsic()
@@ -1037,7 +1008,6 @@
   DCHECK(runtime->IsAotCompiler());
   ArenaAllocator allocator(runtime->GetArenaPool());
   ArenaStack arena_stack(runtime->GetArenaPool());
-  CodeVectorAllocator code_allocator(&allocator);
   std::unique_ptr<CodeGenerator> codegen;
   bool compiled_intrinsic = false;
   {
@@ -1071,7 +1041,6 @@
       codegen.reset(
           TryCompileIntrinsic(&allocator,
                               &arena_stack,
-                              &code_allocator,
                               dex_compilation_unit,
                               method,
                               &handles));
@@ -1083,7 +1052,6 @@
       codegen.reset(
           TryCompile(&allocator,
                      &arena_stack,
-                     &code_allocator,
                      dex_compilation_unit,
                      method,
                      compiler_options.IsBaseline()
@@ -1094,7 +1062,6 @@
   }
   if (codegen.get() != nullptr) {
     compiled_method = Emit(&allocator,
-                           &code_allocator,
                            codegen.get(),
                            compiled_intrinsic,
                            compiled_intrinsic ? nullptr : code_item);
@@ -1177,19 +1144,16 @@
           /*verified_method=*/ nullptr,
           dex_cache,
           compiling_class);
-      CodeVectorAllocator code_allocator(&allocator);
       // Go to native so that we don't block GC during compilation.
       ScopedThreadSuspension sts(soa.Self(), ThreadState::kNative);
       std::unique_ptr<CodeGenerator> codegen(
           TryCompileIntrinsic(&allocator,
                               &arena_stack,
-                              &code_allocator,
                               dex_compilation_unit,
                               method,
                               &handles));
       if (codegen != nullptr) {
         return Emit(&allocator,
-                    &code_allocator,
                     codegen.get(),
                     /*is_intrinsic=*/ true,
                     /*item=*/ nullptr);
@@ -1342,7 +1306,6 @@
   }
 
   ArenaStack arena_stack(runtime->GetJitArenaPool());
-  CodeVectorAllocator code_allocator(&allocator);
   VariableSizedHandleScope handles(self);
 
   std::unique_ptr<CodeGenerator> codegen;
@@ -1365,7 +1328,6 @@
     codegen.reset(
         TryCompile(&allocator,
                    &arena_stack,
-                   &code_allocator,
                    dex_compilation_unit,
                    method,
                    compilation_kind,
@@ -1381,7 +1343,7 @@
   ArrayRef<const uint8_t> reserved_data;
   if (!code_cache->Reserve(self,
                            region,
-                           code_allocator.GetMemory().size(),
+                           codegen->GetAssembler()->CodeSize(),
                            stack_map.size(),
                            /*number_of_roots=*/codegen->GetNumberOfJitRoots(),
                            method,
@@ -1394,7 +1356,9 @@
   const uint8_t* roots_data = reserved_data.data();
 
   std::vector<Handle<mirror::Object>> roots;
-  codegen->EmitJitRoots(code_allocator.GetData(), roots_data, &roots);
+  codegen->EmitJitRoots(const_cast<uint8_t*>(codegen->GetAssembler()->CodeBufferBaseAddress()),
+                        roots_data,
+                        &roots);
   // The root Handle<>s filled by the codegen reference entries in the VariableSizedHandleScope.
   DCHECK(std::all_of(roots.begin(),
                      roots.end(),
@@ -1418,7 +1382,7 @@
     info.is_optimized = true;
     info.is_code_address_text_relative = false;
     info.code_address = reinterpret_cast<uintptr_t>(code);
-    info.code_size = code_allocator.GetMemory().size();
+    info.code_size = codegen->GetAssembler()->CodeSize(),
     info.frame_size_in_bytes = codegen->GetFrameSize();
     info.code_info = stack_map.size() == 0 ? nullptr : stack_map.data();
     info.cfi = ArrayRef<const uint8_t>(*codegen->GetAssembler()->cfi().data());
@@ -1429,7 +1393,7 @@
                           region,
                           method,
                           reserved_code,
-                          code_allocator.GetMemory(),
+                          codegen->GetCode(),
                           reserved_data,
                           roots,
                           ArrayRef<const uint8_t>(stack_map),
@@ -1444,7 +1408,7 @@
 
   Runtime::Current()->GetJit()->AddMemoryUsage(method, allocator.BytesUsed());
   if (jit_logger != nullptr) {
-    jit_logger->WriteLog(code, code_allocator.GetMemory().size(), method);
+    jit_logger->WriteLog(code, codegen->GetAssembler()->CodeSize(), method);
   }
 
   if (kArenaAllocatorCountAllocations) {
diff --git a/compiler/trampolines/trampoline_compiler.cc b/compiler/trampolines/trampoline_compiler.cc
index e542763..d128a9e 100644
--- a/compiler/trampolines/trampoline_compiler.cc
+++ b/compiler/trampolines/trampoline_compiler.cc
@@ -78,7 +78,7 @@
   size_t cs = __ CodeSize();
   std::unique_ptr<std::vector<uint8_t>> entry_stub(new std::vector<uint8_t>(cs));
   MemoryRegion code(entry_stub->data(), entry_stub->size());
-  __ FinalizeInstructions(code);
+  __ CopyInstructions(code);
 
   return std::move(entry_stub);
 }
@@ -120,7 +120,7 @@
   size_t cs = __ CodeSize();
   std::unique_ptr<std::vector<uint8_t>> entry_stub(new std::vector<uint8_t>(cs));
   MemoryRegion code(entry_stub->data(), entry_stub->size());
-  __ FinalizeInstructions(code);
+  __ CopyInstructions(code);
 
   return std::move(entry_stub);
 }
@@ -189,7 +189,7 @@
   size_t cs = __ CodeSize();
   std::unique_ptr<std::vector<uint8_t>> entry_stub(new std::vector<uint8_t>(cs));
   MemoryRegion code(entry_stub->data(), entry_stub->size());
-  __ FinalizeInstructions(code);
+  __ CopyInstructions(code);
 
   return std::move(entry_stub);
 }
@@ -210,7 +210,7 @@
   size_t cs = __ CodeSize();
   std::unique_ptr<std::vector<uint8_t>> entry_stub(new std::vector<uint8_t>(cs));
   MemoryRegion code(entry_stub->data(), entry_stub->size());
-  __ FinalizeInstructions(code);
+  __ CopyInstructions(code);
 
   return std::move(entry_stub);
 }
diff --git a/compiler/utils/arm/assembler_arm_vixl.cc b/compiler/utils/arm/assembler_arm_vixl.cc
index c7ca003..d64de09 100644
--- a/compiler/utils/arm/assembler_arm_vixl.cc
+++ b/compiler/utils/arm/assembler_arm_vixl.cc
@@ -52,7 +52,7 @@
   return vixl_masm_.GetBuffer().GetStartAddress<const uint8_t*>();
 }
 
-void ArmVIXLAssembler::FinalizeInstructions(const MemoryRegion& region) {
+void ArmVIXLAssembler::CopyInstructions(const MemoryRegion& region) {
   // Copy the instructions from the buffer.
   MemoryRegion from(vixl_masm_.GetBuffer()->GetStartAddress<void*>(), CodeSize());
   region.CopyFrom(0, from);
diff --git a/compiler/utils/arm/assembler_arm_vixl.h b/compiler/utils/arm/assembler_arm_vixl.h
index 025bba0..50dc06f 100644
--- a/compiler/utils/arm/assembler_arm_vixl.h
+++ b/compiler/utils/arm/assembler_arm_vixl.h
@@ -218,7 +218,7 @@
   const uint8_t* CodeBufferBaseAddress() const override;
 
   // Copy instructions out of assembly buffer into the given region of memory.
-  void FinalizeInstructions(const MemoryRegion& region) override;
+  void CopyInstructions(const MemoryRegion& region) override;
 
   void Bind([[maybe_unused]] Label* label) override {
     UNIMPLEMENTED(FATAL) << "Do not use Bind(Label*) for ARM";
diff --git a/compiler/utils/arm64/assembler_arm64.cc b/compiler/utils/arm64/assembler_arm64.cc
index 26dce7c..13acc7c 100644
--- a/compiler/utils/arm64/assembler_arm64.cc
+++ b/compiler/utils/arm64/assembler_arm64.cc
@@ -79,7 +79,7 @@
   return vixl_masm_.GetBuffer().GetStartAddress<const uint8_t*>();
 }
 
-void Arm64Assembler::FinalizeInstructions(const MemoryRegion& region) {
+void Arm64Assembler::CopyInstructions(const MemoryRegion& region) {
   // Copy the instructions from the buffer.
   MemoryRegion from(vixl_masm_.GetBuffer()->GetStartAddress<void*>(), CodeSize());
   region.CopyFrom(0, from);
diff --git a/compiler/utils/arm64/assembler_arm64.h b/compiler/utils/arm64/assembler_arm64.h
index 5eff8ca..ad6a8ed 100644
--- a/compiler/utils/arm64/assembler_arm64.h
+++ b/compiler/utils/arm64/assembler_arm64.h
@@ -91,7 +91,7 @@
   const uint8_t* CodeBufferBaseAddress() const override;
 
   // Copy instructions out of assembly buffer into the given region of memory.
-  void FinalizeInstructions(const MemoryRegion& region) override;
+  void CopyInstructions(const MemoryRegion& region) override;
 
   void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs);
 
diff --git a/compiler/utils/assembler.cc b/compiler/utils/assembler.cc
index b82f0dc..1c04a3d 100644
--- a/compiler/utils/assembler.cc
+++ b/compiler/utils/assembler.cc
@@ -57,21 +57,24 @@
     fixup->Process(region, fixup->position());
     fixup = fixup->previous();
   }
-}
-
-
-void AssemblerBuffer::FinalizeInstructions(const MemoryRegion& instructions) {
-  // Copy the instructions from the buffer.
-  MemoryRegion from(reinterpret_cast<void*>(contents()), Size());
-  instructions.CopyFrom(0, from);
-  // Process fixups in the instructions.
-  ProcessFixups(instructions);
 #ifndef NDEBUG
   fixups_processed_ = true;
 #endif
 }
 
 
+void AssemblerBuffer::ProcessFixups() {
+  MemoryRegion from(reinterpret_cast<void*>(contents()), Size());
+  ProcessFixups(from);
+}
+
+
+void AssemblerBuffer::CopyInstructions(const MemoryRegion& instructions) {
+  MemoryRegion from(reinterpret_cast<void*>(contents()), Size());
+  instructions.CopyFrom(0, from);
+}
+
+
 void AssemblerBuffer::ExtendCapacity(size_t min_capacity) {
   size_t old_size = Size();
   size_t old_capacity = Capacity();
diff --git a/compiler/utils/assembler.h b/compiler/utils/assembler.h
index 63747be..f3fa711 100644
--- a/compiler/utils/assembler.h
+++ b/compiler/utils/assembler.h
@@ -163,9 +163,8 @@
 
   uint8_t* contents() const { return contents_; }
 
-  // Copy the assembled instructions into the specified memory block
-  // and apply all fixups.
-  void FinalizeInstructions(const MemoryRegion& region);
+  // Copy the assembled instructions into the specified memory block.
+  void CopyInstructions(const MemoryRegion& region);
 
   // To emit an instruction to the assembler buffer, the EnsureCapacity helper
   // must be used to guarantee that the underlying data area is big enough to
@@ -246,6 +245,8 @@
   // The provided `min_capacity` must be higher than current `Capacity()`.
   void ExtendCapacity(size_t min_capacity);
 
+  void ProcessFixups();
+
  private:
   // The limit is set to kMinimumGap bytes before the end of the data area.
   // This leaves enough space for the longest possible instruction and allows
@@ -357,7 +358,10 @@
 class Assembler : public DeletableArenaObject<kArenaAllocAssembler> {
  public:
   // Finalize the code; emit slow paths, fixup branches, add literal pool, etc.
-  virtual void FinalizeCode() { buffer_.EmitSlowPaths(this); }
+  virtual void FinalizeCode() {
+    buffer_.EmitSlowPaths(this);
+    buffer_.ProcessFixups();
+  }
 
   // Size of generated code
   virtual size_t CodeSize() const { return buffer_.Size(); }
@@ -375,8 +379,8 @@
   virtual size_t CodePosition() { return CodeSize(); }
 
   // Copy instructions out of assembly buffer into the given region of memory
-  virtual void FinalizeInstructions(const MemoryRegion& region) {
-    buffer_.FinalizeInstructions(region);
+  virtual void CopyInstructions(const MemoryRegion& region) {
+    buffer_.CopyInstructions(region);
   }
 
   // TODO: Implement with disassembler.
diff --git a/compiler/utils/assembler_test.h b/compiler/utils/assembler_test.h
index 810c843..c2e5064 100644
--- a/compiler/utils/assembler_test.h
+++ b/compiler/utils/assembler_test.h
@@ -1583,7 +1583,7 @@
     size_t cs = assembler_->CodeSize();
     std::unique_ptr<std::vector<uint8_t>> data(new std::vector<uint8_t>(cs));
     MemoryRegion code(&(*data)[0], data->size());
-    assembler_->FinalizeInstructions(code);
+    assembler_->CopyInstructions(code);
     Pad(*data);
     Driver(*data, assembly_text, test_name);
   }
diff --git a/compiler/utils/assembler_thumb_test.cc b/compiler/utils/assembler_thumb_test.cc
index 672cd3d..53cb3d6 100644
--- a/compiler/utils/assembler_thumb_test.cc
+++ b/compiler/utils/assembler_thumb_test.cc
@@ -79,7 +79,7 @@
     size_t cs = __ CodeSize();
     std::vector<uint8_t> managed_code(cs);
     MemoryRegion code(&managed_code[0], managed_code.size());
-    __ FinalizeInstructions(code);
+    __ CopyInstructions(code);
 
     DumpAndCheck(managed_code, testname, expected);
   }
diff --git a/compiler/utils/jni_macro_assembler.h b/compiler/utils/jni_macro_assembler.h
index 0c72970..286c378 100644
--- a/compiler/utils/jni_macro_assembler.h
+++ b/compiler/utils/jni_macro_assembler.h
@@ -92,7 +92,7 @@
   virtual size_t CodeSize() const = 0;
 
   // Copy instructions out of assembly buffer into the given region of memory
-  virtual void FinalizeInstructions(const MemoryRegion& region) = 0;
+  virtual void CopyInstructions(const MemoryRegion& region) = 0;
 
   // Emit code that will create an activation on the stack
   virtual void BuildFrame(size_t frame_size,
@@ -266,8 +266,8 @@
     return asm_.CodeSize();
   }
 
-  void FinalizeInstructions(const MemoryRegion& region) override {
-    asm_.FinalizeInstructions(region);
+  void CopyInstructions(const MemoryRegion& region) override {
+    asm_.CopyInstructions(region);
   }
 
   DebugFrameOpCodeWriterForAssembler& cfi() override {
diff --git a/compiler/utils/jni_macro_assembler_test.h b/compiler/utils/jni_macro_assembler_test.h
index 0d0a992..ff182e6 100644
--- a/compiler/utils/jni_macro_assembler_test.h
+++ b/compiler/utils/jni_macro_assembler_test.h
@@ -84,7 +84,7 @@
     size_t cs = assembler_->CodeSize();
     std::unique_ptr<std::vector<uint8_t>> data(new std::vector<uint8_t>(cs));
     MemoryRegion code(&(*data)[0], data->size());
-    assembler_->FinalizeInstructions(code);
+    assembler_->CopyInstructions(code);
     Pad(*data);
     Driver(*data, assembly_text, test_name);
   }
diff --git a/compiler/utils/riscv64/assembler_riscv64.cc b/compiler/utils/riscv64/assembler_riscv64.cc
index 4df3a7e..a09a23e 100644
--- a/compiler/utils/riscv64/assembler_riscv64.cc
+++ b/compiler/utils/riscv64/assembler_riscv64.cc
@@ -50,15 +50,12 @@
 }
 
 void Riscv64Assembler::FinalizeCode() {
+  Assembler::FinalizeCode();
   ReserveJumpTableSpace();
   EmitLiterals();
   PromoteBranches();
-}
-
-void Riscv64Assembler::FinalizeInstructions(const MemoryRegion& region) {
   EmitBranches();
   EmitJumpTables();
-  Assembler::FinalizeInstructions(region);
   PatchCFI();
 }
 
diff --git a/compiler/utils/riscv64/assembler_riscv64.h b/compiler/utils/riscv64/assembler_riscv64.h
index d94433f..fc0b442 100644
--- a/compiler/utils/riscv64/assembler_riscv64.h
+++ b/compiler/utils/riscv64/assembler_riscv64.h
@@ -593,12 +593,10 @@
   JumpTable* CreateJumpTable(ArenaVector<Riscv64Label*>&& labels);
 
  public:
-  // Emit slow paths queued during assembly and promote short branches to long if needed.
+  // Emit slow paths queued during assembly, promote short branches to long if needed,
+  // and emit branches.
   void FinalizeCode() override;
 
-  // Emit branches and finalize all instructions.
-  void FinalizeInstructions(const MemoryRegion& region) override;
-
   // Returns the current location of a label.
   //
   // This function must be used instead of `Riscv64Label::GetPosition()`
diff --git a/compiler/utils/riscv64/jni_macro_assembler_riscv64_test.cc b/compiler/utils/riscv64/jni_macro_assembler_riscv64_test.cc
index 3dc9f62..6a27885 100644
--- a/compiler/utils/riscv64/jni_macro_assembler_riscv64_test.cc
+++ b/compiler/utils/riscv64/jni_macro_assembler_riscv64_test.cc
@@ -47,7 +47,7 @@
     size_t cs = assembler_.CodeSize();
     std::vector<uint8_t> data(cs);
     MemoryRegion code(&data[0], data.size());
-    assembler_.FinalizeInstructions(code);
+    assembler_.CopyInstructions(code);
     Driver(data, assembly_text, test_name);
   }