A64: Force emission of the veneer pool emission when required.
authoralexandre.rames@arm.com <alexandre.rames@arm.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 18 Mar 2014 14:26:26 +0000 (14:26 +0000)
committeralexandre.rames@arm.com <alexandre.rames@arm.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 18 Mar 2014 14:26:26 +0000 (14:26 +0000)
R=ulan@chromium.org

Review URL: https://codereview.chromium.org/203443003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20036 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/a64/assembler-a64-inl.h
src/a64/assembler-a64.cc
src/a64/assembler-a64.h
src/a64/full-codegen-a64.cc
src/a64/lithium-codegen-a64.cc
src/a64/macro-assembler-a64-inl.h

index 2a930b2..feb6bbb 100644 (file)
@@ -1207,7 +1207,7 @@ inline void Assembler::CheckBuffer() {
     GrowBuffer();
   }
   if (pc_offset() >= next_veneer_pool_check_) {
-    CheckVeneerPool(true);
+    CheckVeneerPool(false, true);
   }
   if (pc_offset() >= next_constant_pool_check_) {
     CheckConstPool(false, true);
index 2323214..a571741 100644 (file)
@@ -2566,7 +2566,7 @@ void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
 
   // Emit veneers for branches that would go out of range during emission of the
   // constant pool.
-  CheckVeneerPool(require_jump, kVeneerDistanceMargin + pool_size);
+  CheckVeneerPool(false, require_jump, kVeneerDistanceMargin + pool_size);
 
   Label size_check;
   bind(&size_check);
@@ -2659,7 +2659,7 @@ void Assembler::RecordVeneerPool(int location_offset, int size) {
 }
 
 
-void Assembler::EmitVeneers(bool need_protection, int margin) {
+void Assembler::EmitVeneers(bool force_emit, bool need_protection, int margin) {
   BlockPoolsScope scope(this);
   RecordComment("[ Veneers");
 
@@ -2685,7 +2685,7 @@ void Assembler::EmitVeneers(bool need_protection, int margin) {
 
   it = unresolved_branches_.begin();
   while (it != unresolved_branches_.end()) {
-    if (ShouldEmitVeneer(it->first, margin)) {
+    if (force_emit || ShouldEmitVeneer(it->first, margin)) {
       Instruction* branch = InstructionAt(it->second.pc_offset_);
       Label* label = it->second.label_;
 
@@ -2728,7 +2728,7 @@ void Assembler::EmitVeneers(bool need_protection, int margin) {
 }
 
 
-void Assembler::CheckVeneerPool(bool require_jump,
+void Assembler::CheckVeneerPool(bool force_emit, bool require_jump,
                                 int margin) {
   // There is nothing to do if there are no pending veneer pool entries.
   if (unresolved_branches_.empty())  {
@@ -2742,6 +2742,7 @@ void Assembler::CheckVeneerPool(bool require_jump,
   // emission, such sequences are protected by calls to BlockVeneerPoolFor and
   // BlockVeneerPoolScope.
   if (is_veneer_pool_blocked()) {
+    ASSERT(!force_emit);
     return;
   }
 
@@ -2749,8 +2750,8 @@ void Assembler::CheckVeneerPool(bool require_jump,
     // Prefer emitting veneers protected by an existing instruction.
     margin *= kVeneerNoProtectionFactor;
   }
-  if (ShouldEmitVeneers(margin)) {
-    EmitVeneers(require_jump, margin);
+  if (force_emit || ShouldEmitVeneers(margin)) {
+    EmitVeneers(force_emit, require_jump, margin);
   } else {
     next_veneer_pool_check_ =
       unresolved_branches_first_limit() - kVeneerDistanceCheckMargin;
index 31d7f17..47f9694 100644 (file)
@@ -1808,10 +1808,13 @@ class Assembler : public AssemblerBase {
   // Emits veneers for branches that are approaching their maximum range.
   // If need_protection is true, the veneers are protected by a branch jumping
   // over the code.
-  void EmitVeneers(bool need_protection, int margin = kVeneerDistanceMargin);
+  void EmitVeneers(bool force_emit, bool need_protection,
+                   int margin = kVeneerDistanceMargin);
   void EmitVeneersGuard() { EmitPoolGuard(); }
   // Checks whether veneers need to be emitted at this point.
-  void CheckVeneerPool(bool require_jump, int margin = kVeneerDistanceMargin);
+  // If force_emit is set, a veneer is generated for *all* unresolved branches.
+  void CheckVeneerPool(bool force_emit, bool require_jump,
+                       int margin = kVeneerDistanceMargin);
 
 
   class BlockPoolsScope {
index 09eb492..8c3c88d 100644 (file)
@@ -314,8 +314,9 @@ void FullCodeGenerator::Generate() {
   }
   EmitReturnSequence();
 
-  // Force emit the constant pool, so it doesn't get emitted in the middle
+  // Force emission of the pools, so they don't get emitted in the middle
   // of the back edge table.
+  masm()->CheckVeneerPool(true, false);
   masm()->CheckConstPool(true, false);
 }
 
index 48f8ea6..f39addb 100644 (file)
@@ -895,6 +895,9 @@ bool LCodeGen::GenerateDeoptJumpTable() {
 
 bool LCodeGen::GenerateSafepointTable() {
   ASSERT(is_done());
+  // We do not know how much data will be emitted for the safepoint table, so
+  // force emission of the veneer pool.
+  masm()->CheckVeneerPool(true, true);
   safepoints_.Emit(masm(), GetStackSlotCount());
   return !is_aborted();
 }
index b205e6e..1fd12b0 100644 (file)
@@ -346,7 +346,7 @@ void MacroAssembler::Asr(const Register& rd,
 
 void MacroAssembler::B(Label* label) {
   b(label);
-  CheckVeneerPool(false);
+  CheckVeneerPool(false, false);
 }
 
 
@@ -1036,7 +1036,7 @@ void MacroAssembler::Ret(const Register& xn) {
   ASSERT(allow_macro_instructions_);
   ASSERT(!xn.IsZero());
   ret(xn);
-  CheckVeneerPool(false);
+  CheckVeneerPool(false, false);
 }