Index: src/jump-target.cc |
=================================================================== |
--- src/jump-target.cc (revision 1913) |
+++ src/jump-target.cc (working copy) |
@@ -101,16 +101,27 @@ |
if (!left->is_valid()) return left; |
if (!right->is_valid()) return right; |
- // If they have the same value, the result is the same. If either |
- // is unsynced, the result is. |
+ // If they have the exact same location, the result is in that |
+ // location, otherwise we reallocate. If either is unsynced, the |
+ // result is. The result static type is the merge of the static |
+ // types. It's safe to set it on one of the frame elements, and |
+ // harmless too (because we are only going to merge the reaching |
+ // frames and will ensure that the types are coherent, and changing |
+ // the static type does not emit code). |
- if (left->is_memory() && right->is_memory()) return left; |
+ StaticType type = left->static_type().merge(right->static_type()); |
+ if (left->is_memory() && right->is_memory()) { |
+ left->set_static_type(type); |
+ return left; |
+ } |
if (left->is_register() && right->is_register() && |
Lasse Reichstein
2009/05/12 14:45:38
This function looks like a lot of duplicated code.
|
left->reg().is(right->reg())) { |
if (!left->is_synced()) { |
+ left->set_static_type(type); |
return left; |
} else { |
+ right->set_static_type(type); |
return right; |
} |
} |
@@ -119,8 +130,10 @@ |
right->is_constant() && |
left->handle().is_identical_to(right->handle())) { |
if (!left->is_synced()) { |
+ left->set_static_type(type); |
return left; |
} else { |
+ right->set_static_type(type); |
return right; |
} |
} |
@@ -129,8 +142,10 @@ |
right->is_copy() && |
left->index() == right->index()) { |
if (!left->is_synced()) { |
+ left->set_static_type(type); |
return left; |
} else { |
+ right->set_static_type(type); |
return right; |
} |
} |
@@ -165,13 +180,19 @@ |
// frame. |
for (int i = 0; i < length; i++) { |
FrameElement element = initial_frame->elements_[i]; |
Lasse Reichstein
2009/05/12 14:45:38
If we look this element up again later, would it p
|
- // We do not allow copies or constants in bidirectional frames. |
- if (direction_ == BIDIRECTIONAL && i > high_water_mark && |
- (element.is_constant() || element.is_copy())) { |
- elements.Add(NULL); |
- } else { |
- elements.Add(&initial_frame->elements_[i]); |
+ // We do not allow copies or constants in bidirectional frames. All |
+ // elements above the water mark on bidirectional frames have |
+ // unknown static types. |
+ if (direction_ == BIDIRECTIONAL && i > high_water_mark) { |
+ if (element.is_constant() || element.is_copy()) { |
+ elements.Add(NULL); |
+ continue; |
+ } |
+ // It's safe to change the static type on the initial frame |
+ // element, see comment in JumpTarget::Combine. |
+ initial_frame->elements_[i].set_static_type(StaticType::unknown()); |
} |
+ elements.Add(&initial_frame->elements_[i]); |
} |
// Compute elements based on the other reaching frames. |
@@ -229,36 +250,45 @@ |
// memory, from the top down. |
for (int i = length - 1; i >= 0; i--) { |
if (elements[i] == NULL) { |
- // If the value is synced on all frames, put it in memory. This |
- // costs nothing at the merge code but will incur a |
- // memory-to-register move when the value is needed later. |
+ // Loop over all the reaching frames to check whether the element |
+ // is synced on all frames, to count the registers it occupies, |
+ // and to compute a merged static type. |
bool is_synced = true; |
- for (int j = 0; is_synced && j < reaching_frames_.length(); j++) { |
- is_synced = reaching_frames_[j]->elements_[i].is_synced(); |
- } |
- |
- // There is nothing to be done if the elements are all synced. |
- // It is already recorded as a memory element. |
- if (is_synced) continue; |
- |
- // Choose an available register. Prefer ones that the element |
- // is already occupying on some reaching frame. |
RegisterFile candidate_registers; |
- int max_count = kMinInt; |
+ int best_count = kMinInt; |
int best_reg_code = no_reg.code_; |
+ StaticType type; // Initially invalid. |
+ if (direction_ != BIDIRECTIONAL || i < high_water_mark) { |
+ type = reaching_frames_[0]->elements_[i].static_type(); |
+ } |
+ |
for (int j = 0; j < reaching_frames_.length(); j++) { |
FrameElement element = reaching_frames_[j]->elements_[i]; |
- if (element.is_register() && |
- !entry_frame_->is_used(element.reg())) { |
+ is_synced = is_synced && element.is_synced(); |
+ if (element.is_register() && !entry_frame_->is_used(element.reg())) { |
+ // Count the register occurrence and remember it if better |
+ // than the previous best. |
candidate_registers.Use(element.reg()); |
- if (candidate_registers.count(element.reg()) > max_count) { |
- max_count = candidate_registers.count(element.reg()); |
+ if (candidate_registers.count(element.reg()) > best_count) { |
+ best_count = candidate_registers.count(element.reg()); |
best_reg_code = element.reg().code(); |
} |
} |
+ type = type.merge(element.static_type()); |
} |
- // If there was no preferred choice consider any free register. |
+ |
+ // If the value is synced on all frames, put it in memory. This |
+ // costs nothing at the merge code but will incur a |
+ // memory-to-register move when the value is needed later. |
+ if (is_synced) { |
+ // Already recorded as a memory element. |
+ entry_frame_->elements_[i].set_static_type(type); |
+ continue; |
+ } |
+ |
+ // Try to put it in a register. If there was no best choice |
+ // consider any free register. |
if (best_reg_code == no_reg.code_) { |
for (int j = 0; j < kNumRegisters; j++) { |
if (!entry_frame_->is_used(j) && !RegisterAllocator::IsReserved(j)) { |
@@ -268,39 +298,25 @@ |
} |
} |
- if (best_reg_code != no_reg.code_) { |
+ if (best_reg_code == no_reg.code_) { |
+ // If there was no register found, the element is already |
+ // recorded as in memory. |
+ entry_frame_->elements_[i].set_static_type(type); |
+ } else { |
// If there was a register choice, use it. Preserve the copied |
- // flag on the element. |
+ // flag on the element. Set the static type as computed. |
bool is_copied = entry_frame_->elements_[i].is_copied(); |
Register reg = { best_reg_code }; |
entry_frame_->elements_[i] = |
FrameElement::RegisterElement(reg, |
FrameElement::NOT_SYNCED); |
if (is_copied) entry_frame_->elements_[i].set_copied(); |
+ entry_frame_->elements_[i].set_static_type(type); |
entry_frame_->register_locations_[best_reg_code] = i; |
} |
- // If there was no register found, the element is already |
- // recorded as in memory. |
} |
} |
- // Set the static type of frame elements. |
- for (int i = 0; i < length; i++) { |
- FrameElement* current = &entry_frame_->elements_[i]; |
- if (direction_ == BIDIRECTIONAL && i >= high_water_mark) { |
- current->set_static_type(StaticType::unknown()); |
- } else { |
- StaticType merged_type = reaching_frames_[0]->elements_[i].static_type(); |
- for (int j = 1, n = reaching_frames_.length(); |
- !merged_type.is_unknown() && j < n; |
- j++) { |
- merged_type = |
- merged_type.merge(reaching_frames_[j]->elements_[i].static_type()); |
- } |
- current->set_static_type(merged_type); |
- } |
- } |
- |
// Fill in the other fields of the entry frame. |
entry_frame_->local_count_ = initial_frame->local_count_; |
entry_frame_->frame_pointer_ = initial_frame->frame_pointer_; |