Index: src/jump-target.cc |
=================================================================== |
--- src/jump-target.cc (revision 1481) |
+++ src/jump-target.cc (working copy) |
@@ -37,23 +37,48 @@ |
JumpTarget::JumpTarget(CodeGenerator* cgen, Directionality direction) |
: cgen_(cgen), |
- masm_(cgen == NULL ? NULL : cgen->masm()), |
direction_(direction), |
reaching_frames_(0), |
merge_labels_(0), |
entry_frame_(NULL), |
is_bound_(false), |
is_linked_(false) { |
+ ASSERT(cgen != NULL); |
+ Initialize(cgen, direction); |
} |
+JumpTarget::JumpTarget() |
+ : cgen_(NULL), |
+ masm_(NULL), |
+ direction_(FORWARD_ONLY), |
+ reaching_frames_(0), |
+ merge_labels_(0), |
+ entry_frame_(NULL), |
+ is_bound_(false), |
+ is_linked_(false) { |
+} |
+ |
+ |
+void JumpTarget::Initialize(CodeGenerator* cgen, Directionality direction) { |
+ ASSERT(cgen != NULL); |
+ ASSERT(cgen_ == NULL); |
+ cgen_ = cgen; |
+ masm_ = cgen->masm(); |
+ direction_ = direction; |
+} |
+ |
+ |
void JumpTarget::Unuse() { |
ASSERT(!is_linked()); |
- entry_label_.Unuse(); |
+#ifdef DEBUG |
+ for (int i = 0; i < reaching_frames_.length(); i++) { |
+ ASSERT(reaching_frames_[i] == NULL); |
+ } |
+#endif |
delete entry_frame_; |
- entry_frame_ = NULL; |
- is_bound_ = false; |
- is_linked_ = false; |
+ |
+ Reset(); |
} |
@@ -501,16 +526,10 @@ |
// ------------------------------------------------------------------------- |
// BreakTarget implementation. |
-BreakTarget::BreakTarget() : JumpTarget(NULL, FORWARD_ONLY) { |
-} |
- |
- |
void BreakTarget::Initialize(CodeGenerator* cgen, Directionality direction) { |
- ASSERT(cgen != NULL); |
- ASSERT(cgen_ == NULL); |
- cgen_ = cgen; |
- masm_ = cgen->masm(); |
- direction_ = direction; |
+ JumpTarget::Initialize(cgen, direction); |
+ ASSERT(cgen_->has_valid_frame()); |
+ expected_height_ = cgen_->frame()->height(); |
} |
@@ -530,9 +549,61 @@ |
destination->entry_label_ = entry_label_; |
destination->is_bound_ = is_bound_; |
destination->is_linked_ = is_linked_; |
+ destination->expected_height_ = expected_height_; |
} |
+void BreakTarget::Jump() { |
+ ASSERT(cgen_ != NULL); |
+ ASSERT(cgen_->has_valid_frame()); |
+ |
+ // This is a break target so drop leftover statement state from the |
+ // frame before merging. |
+ cgen_->frame()->ForgetElements(cgen_->frame()->height() - expected_height_); |
+ JumpTarget::Jump(); |
+} |
+ |
+ |
+void BreakTarget::Branch(Condition cc, Hint hint) { |
+ ASSERT(cgen_ != NULL); |
+ ASSERT(cgen_->has_valid_frame()); |
+ |
+ int count = cgen_->frame()->height() - expected_height_; |
+ if (count > 0) { |
+ // We negate and branch here rather than using |
+ // JumpTarget::Branch's negate and branch. This gives us a hook |
+ // to remove statement state from the frame. |
+ JumpTarget fall_through(cgen_); |
+ // Branch to fall through will not negate, because it is a |
+ // forward-only target. |
+ fall_through.Branch(NegateCondition(cc), NegateHint(hint)); |
+ Jump(); // May emit merge code here. |
+ fall_through.Bind(); |
+ } else { |
+ JumpTarget::Branch(cc, hint); |
+ } |
+} |
+ |
+ |
+void BreakTarget::Bind(int mergable_elements) { |
+#ifdef DEBUG |
+ ASSERT(mergable_elements == kAllElements); |
+ ASSERT(cgen_ != NULL); |
+ for (int i = 0; i < reaching_frames_.length(); i++) { |
+ ASSERT(reaching_frames_[i]->height() == expected_height_); |
+ } |
+#endif |
+ |
+ // This is a break target so drop leftover statement state from the |
+ // frame before merging. |
+ if (cgen_->has_valid_frame()) { |
+ int count = cgen_->frame()->height() - expected_height_; |
+ cgen_->frame()->ForgetElements(count); |
+ } |
+ JumpTarget::Bind(mergable_elements); |
+} |
+ |
+ |
// ------------------------------------------------------------------------- |
// ShadowTarget implementation. |
@@ -546,15 +617,19 @@ |
// While shadowing this shadow target saves the state of the original. |
shadowed->CopyTo(this); |
+ // The original's state is reset. We do not Unuse it because that |
+ // would delete the expected frame and assert that the target is not |
+ // linked. |
+ shadowed->Reset(); |
+ ASSERT(cgen_ != NULL); |
+ ASSERT(cgen_->has_valid_frame()); |
+ shadowed->set_expected_height(cgen_->frame()->height()); |
+ |
// Setting the code generator to null prevents the shadow target from |
// being used until shadowing stops. |
cgen_ = NULL; |
masm_ = NULL; |
- // The original's state is reset. We do not Unuse it because that |
- // would delete the expected frame and assert that the target is not |
- // linked. |
- shadowed->Reset(); |
} |