Index: src/mips/assembler-mips.h |
diff --git a/src/mips/assembler-mips.h b/src/mips/assembler-mips.h |
index aeecee616bc9ebcd71568416ebaf36b106ce94e9..92c958b9620d605db52731b03b4e8a6a2a6f62e0 100644 |
--- a/src/mips/assembler-mips.h |
+++ b/src/mips/assembler-mips.h |
@@ -481,6 +481,9 @@ class Assembler : public AssemblerBase { |
// Note: The same Label can be used for forward and backward branches |
// but it may be bound only once. |
void bind(Label* L); // Binds an unbound label L to current code position. |
+ // Determines if Label is bound and near enough so that branch instruction |
+ // can be used to reach it, instead of jump instruction. |
+ bool is_near(Label* L); |
// Returns the branch offset to the given label from the current code |
// position. Links the label to the current position if it is still unbound. |
@@ -491,6 +494,7 @@ class Assembler : public AssemblerBase { |
ASSERT((o & 3) == 0); // Assert the offset is aligned. |
return o >> 2; |
} |
+ uint32_t jump_address(Label* L); |
// Puts a labels target address at the given position. |
// The high 8 bits are set to zero. |
@@ -795,6 +799,25 @@ class Assembler : public AssemblerBase { |
DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope); |
}; |
+ // Class for postponing the assembly buffer growth. Typically used for |
+ // sequences of instructions that must be emitted as a unit, before |
+ // buffer growth (and relocation) can occur. |
+ // This blocking scope is not nestable. |
+ class BlockGrowBufferScope { |
+ public: |
+ explicit BlockGrowBufferScope(Assembler* assem) : assem_(assem) { |
+ assem_->StartBlockGrowBuffer(); |
+ } |
+ ~BlockGrowBufferScope() { |
+ assem_->EndBlockGrowBuffer(); |
+ } |
+ |
+ private: |
+ Assembler* assem_; |
+ |
+ DISALLOW_IMPLICIT_CONSTRUCTORS(BlockGrowBufferScope); |
+ }; |
+ |
// Debugging. |
// Mark address of the ExitJSFrame code. |
@@ -811,6 +834,8 @@ class Assembler : public AssemblerBase { |
// Use --code-comments to enable. |
void RecordComment(const char* msg); |
+ static int RelocateInternalReference(byte* pc, intptr_t pc_delta); |
+ |
// Writes a single byte or word of data in the code stream. Used for |
// inline tables, e.g., jump-tables. |
void db(uint8_t data); |
@@ -847,6 +872,11 @@ class Assembler : public AssemblerBase { |
static bool IsBeq(Instr instr); |
static bool IsBne(Instr instr); |
+ static bool IsJump(Instr instr); |
+ static bool IsJ(Instr instr); |
+ static bool IsLui(Instr instr); |
+ static bool IsOri(Instr instr); |
+ |
static bool IsNop(Instr instr, unsigned int type); |
static bool IsPop(Instr instr); |
static bool IsPush(Instr instr); |
@@ -868,6 +898,8 @@ class Assembler : public AssemblerBase { |
static uint32_t GetSa(Instr instr); |
static uint32_t GetSaField(Instr instr); |
static uint32_t GetOpcodeField(Instr instr); |
+ static uint32_t GetFunction(Instr instr); |
+ static uint32_t GetFunctionField(Instr instr); |
static uint32_t GetImmediate16(Instr instr); |
static uint32_t GetLabelConst(Instr instr); |
@@ -883,7 +915,7 @@ class Assembler : public AssemblerBase { |
static bool IsAndImmediate(Instr instr); |
- void CheckTrampolinePool(bool force_emit = false); |
+ void CheckTrampolinePool(); |
protected: |
// Relocation for a type-recording IC has the AST id added to it. This |
@@ -916,6 +948,7 @@ class Assembler : public AssemblerBase { |
void StartBlockTrampolinePool() { |
trampoline_pool_blocked_nesting_++; |
} |
+ |
void EndBlockTrampolinePool() { |
trampoline_pool_blocked_nesting_--; |
} |
@@ -928,6 +961,25 @@ class Assembler : public AssemblerBase { |
return internal_trampoline_exception_; |
} |
+ bool is_trampoline_emitted() const { |
+ return trampoline_emitted_; |
+ } |
+ |
+ // Temporarily block automatic assembly buffer growth. |
+ void StartBlockGrowBuffer() { |
+ ASSERT(!block_buffer_growth_); |
+ block_buffer_growth_ = true; |
+ } |
+ |
+ void EndBlockGrowBuffer() { |
+ ASSERT(block_buffer_growth_); |
+ block_buffer_growth_ = false; |
+ } |
+ |
+ bool is_buffer_growth_blocked() const { |
+ return block_buffer_growth_; |
+ } |
+ |
private: |
// Code buffer: |
// The buffer into which code and relocation info are generated. |
@@ -964,6 +1016,9 @@ class Assembler : public AssemblerBase { |
// Keep track of the last emitted pool to guarantee a maximal distance. |
int last_trampoline_pool_end_; // pc offset of the end of the last pool. |
+ // Automatic growth of the assembly buffer may be blocked for some sequences. |
+ bool block_buffer_growth_; // Block growth when true. |
+ |
// Relocation information generation. |
// Each relocation is encoded as a variable size value. |
static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; |
@@ -1044,7 +1099,6 @@ class Assembler : public AssemblerBase { |
// Labels. |
void print(Label* L); |
void bind_to(Label* L, int pos); |
- void link_to(Label* L, Label* appendix); |
void next(Label* L); |
// One trampoline consists of: |
@@ -1057,13 +1111,17 @@ class Assembler : public AssemblerBase { |
// label_count * kInstrSize. |
class Trampoline { |
public: |
- Trampoline(int start, int slot_count, int label_count) { |
+ Trampoline() { |
+ start_ = 0; |
+ next_slot_ = 0; |
+ free_slot_count_ = 0; |
+ end_ = 0; |
+ } |
+ Trampoline(int start, int slot_count) { |
start_ = start; |
next_slot_ = start; |
free_slot_count_ = slot_count; |
- next_label_ = start + slot_count * 2 * kInstrSize; |
- free_label_count_ = label_count; |
- end_ = next_label_ + (label_count - 1) * kInstrSize; |
+ end_ = start + slot_count * kTrampolineSlotsSize; |
} |
int start() { |
return start_; |
@@ -1082,41 +1140,30 @@ class Assembler : public AssemblerBase { |
} else { |
trampoline_slot = next_slot_; |
free_slot_count_--; |
- next_slot_ += 2*kInstrSize; |
+ next_slot_ += kTrampolineSlotsSize; |
} |
return trampoline_slot; |
} |
- int take_label() { |
- int label_pos = next_label_; |
- ASSERT(free_label_count_ > 0); |
- free_label_count_--; |
- next_label_ += kInstrSize; |
- return label_pos; |
- } |
- |
private: |
int start_; |
int end_; |
int next_slot_; |
int free_slot_count_; |
- int next_label_; |
- int free_label_count_; |
}; |
- int32_t get_label_entry(int32_t pos, bool next_pool = true); |
- int32_t get_trampoline_entry(int32_t pos, bool next_pool = true); |
- |
- static const int kSlotsPerTrampoline = 2304; |
- static const int kLabelsPerTrampoline = 8; |
- static const int kTrampolineInst = |
- 2 * kSlotsPerTrampoline + kLabelsPerTrampoline; |
- static const int kTrampolineSize = kTrampolineInst * kInstrSize; |
+ int32_t get_trampoline_entry(int32_t pos); |
+ int unbound_labels_count_; |
+ // If trampoline is emitted, generated code is becoming large. As this is |
+ // already a slow case which can possibly break our code generation for the |
+ // extreme case, we use this information to trigger different mode of |
+ // branch instruction generation, where we use jump instructions rather |
+ // than regular branch instructions. |
+ bool trampoline_emitted_; |
+ static const int kTrampolineSlotsSize = 4 * kInstrSize; |
static const int kMaxBranchOffset = (1 << (18 - 1)) - 1; |
- static const int kMaxDistBetweenPools = |
- kMaxBranchOffset - 2 * kTrampolineSize; |
static const int kInvalidSlotPos = -1; |
- List<Trampoline> trampolines_; |
+ Trampoline trampoline_; |
bool internal_trampoline_exception_; |
friend class RegExpMacroAssemblerMIPS; |