// unknown pc location. Assembler::bind() is used to bind a label to the
// current pc. A label can be bound only once.
-class Label : public ZoneObject { // ShadowLables are dynamically allocated.
+class Label : public ZoneObject { // LabelShadows are dynamically allocated.
public:
INLINE(Label()) { Unuse(); }
INLINE(~Label()) { ASSERT(!is_linked()); }
};
-// A LabelShadow is a label that temporarily shadows another label. It
-// is used to catch linking and binding of labels in certain scopes,
-// e.g. try blocks. LabelShadows are themselves labels which can be
-// used (only) after they are not shadowing anymore.
-class LabelShadow: public Label {
+// A LabelShadow represents a label that is temporarily shadowed by another
+// label (represented by the original label during shadowing). They are used
+// to catch jumps to labels in certain contexts, e.g. try blocks. After
+// shadowing ends, the formerly shadowed label is again represented by the
+// original label and the LabelShadow can be used as a label in its own
+// right, representing the formerly shadowing label.
+class LabelShadow : public Label {
public:
- explicit LabelShadow(Label* shadowed) {
- ASSERT(shadowed != NULL);
- shadowed_ = shadowed;
- shadowed_pos_ = shadowed->pos_;
- shadowed->Unuse();
+ explicit LabelShadow(Label* original) {
+ ASSERT(original != NULL);
+ original_label_ = original;
+ original_pos_ = original->pos_;
+ original->Unuse();
#ifdef DEBUG
is_shadowing_ = true;
#endif
void StopShadowing() {
ASSERT(is_shadowing_ && is_unused());
- pos_ = shadowed_->pos_;
- shadowed_->pos_ = shadowed_pos_;
+ pos_ = original_label_->pos_;
+ original_label_->pos_ = original_pos_;
#ifdef DEBUG
is_shadowing_ = false;
#endif
}
- Label* shadowed() const { return shadowed_; }
+ Label* original_label() const { return original_label_; }
private:
- Label* shadowed_;
- int shadowed_pos_;
+ // During shadowing, the currently shadowing label. After shadowing, the
+ // label that was shadowed.
+ Label* original_label_;
+
+ // During shadowing, the saved state of the original label.
+ int original_pos_;
+
#ifdef DEBUG
bool is_shadowing_;
#endif
__ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER);
- // Introduce shadow labels for all escapes from the try block,
- // including returns. We should probably try to unify the escaping
- // labels and the return label.
+ // Shadow the labels for all escapes from the try block, including
+ // returns. During shadowing, the original label is hidden as the
+ // LabelShadow and operations on the original actually affect the
+ // shadowing label.
+ //
+ // We should probably try to unify the escaping labels and the return
+ // label.
int nof_escapes = node->escaping_labels()->length();
List<LabelShadow*> shadows(1 + nof_escapes);
shadows.Add(new LabelShadow(&function_return_));
__ pop(r0); // Discard the result.
// Stop the introduced shadowing and count the number of required unlinks.
+ // After shadowing stops, the original labels are unshadowed and the
+ // LabelShadows represent the formerly shadowing labels.
int nof_unlinks = 0;
for (int i = 0; i <= nof_escapes; i++) {
shadows[i]->StopShadowing();
// Code slot popped.
if (nof_unlinks > 0) __ b(&exit);
- // Generate unlink code for all used shadow labels.
+ // Generate unlink code for the (formerly) shadowing labels that have been
+ // jumped to.
for (int i = 0; i <= nof_escapes; i++) {
if (shadows[i]->is_linked()) {
// Unlink from try chain;
__ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
// Code slot popped.
- __ b(shadows[i]->shadowed());
+ __ b(shadows[i]->original_label());
}
}
__ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER);
- // Introduce shadow labels for all escapes from the try block,
- // including returns. We should probably try to unify the escaping
- // labels and the return label.
+ // Shadow the labels for all escapes from the try block, including
+ // returns. Shadowing hides the original label as the LabelShadow and
+ // operations on the original actually affect the shadowing label.
+ //
+ // We should probably try to unify the escaping labels and the return
+ // label.
int nof_escapes = node->escaping_labels()->length();
List<LabelShadow*> shadows(1 + nof_escapes);
shadows.Add(new LabelShadow(&function_return_));
// Generate code for the statements in the try block.
VisitStatements(node->try_block()->statements());
- // Stop the introduced shadowing and count the number of required
- // unlinks.
+ // Stop the introduced shadowing and count the number of required unlinks.
+ // After shadowing stops, the original labels are unshadowed and the
+ // LabelShadows represent the formerly shadowing labels.
int nof_unlinks = 0;
for (int i = 0; i <= nof_escapes; i++) {
shadows[i]->StopShadowing();
__ mov(r2, Operand(Smi::FromInt(FALLING)));
if (nof_unlinks > 0) __ b(&unlink);
- // Generate code that sets the state for all used shadow labels.
+ // Generate code to set the state for the (formerly) shadowing labels that
+ // have been jumped to.
for (int i = 0; i <= nof_escapes; i++) {
if (shadows[i]->is_linked()) {
__ bind(shadows[i]);
- if (shadows[i]->shadowed() == &function_return_) {
- __ push(r0); // Materialize the return value on the stack
+ if (shadows[i]->original_label() == &function_return_) {
+ // If this label shadowed the function return, materialize the
+ // return value on the stack.
+ __ push(r0);
} else {
- // Fake TOS for break and continue (not return).
+ // Fake TOS for labels that shadowed breaks and continues.
__ mov(r0, Operand(Factory::undefined_value()));
__ push(r0);
}
__ pop(r0);
break_stack_height_ -= kFinallyStackSize;
- // Generate code that jumps to the right destination for all used
- // shadow labels.
+ // Generate code to jump to the right destination for all used (formerly)
+ // shadowing labels.
for (int i = 0; i <= nof_escapes; i++) {
if (shadows[i]->is_bound()) {
__ cmp(r2, Operand(Smi::FromInt(JUMPING + i)));
- if (shadows[i]->shadowed() != &function_return_) {
+ if (shadows[i]->original_label() != &function_return_) {
Label next;
__ b(ne, &next);
- __ b(shadows[i]->shadowed());
+ __ b(shadows[i]->original_label());
__ bind(&next);
} else {
- __ b(eq, shadows[i]->shadowed());
+ __ b(eq, shadows[i]->original_label());
}
}
}
// TODO(1222589): remove the reliance of PushTryHandler on a cached TOS
frame_->Push(eax); //
- // Introduce shadow labels for all escapes from the try block,
- // including returns. We should probably try to unify the escaping
- // labels and the return label.
+ // Shadow the labels for all escapes from the try block, including
+ // returns. During shadowing, the original label is hidden as the
+ // LabelShadow and operations on the original actually affect the
+ // shadowing label.
+ //
+ // We should probably try to unify the escaping labels and the return
+ // label.
int nof_escapes = node->escaping_labels()->length();
List<LabelShadow*> shadows(1 + nof_escapes);
shadows.Add(new LabelShadow(&function_return_));
is_inside_try_ = was_inside_try;
// Stop the introduced shadowing and count the number of required unlinks.
+ // After shadowing stops, the original labels are unshadowed and the
+ // LabelShadows represent the formerly shadowing labels.
int nof_unlinks = 0;
for (int i = 0; i <= nof_escapes; i++) {
shadows[i]->StopShadowing();
// next_sp popped.
if (nof_unlinks > 0) __ jmp(&exit);
- // Generate unlink code for all used shadow labels.
+ // Generate unlink code for the (formerly) shadowing labels that have been
+ // jumped to.
for (int i = 0; i <= nof_escapes; i++) {
if (shadows[i]->is_linked()) {
// Unlink from try chain; be careful not to destroy the TOS.
frame_->Pop(Operand::StaticVariable(handler_address));
frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
// next_sp popped.
- __ jmp(shadows[i]->shadowed());
+ __ jmp(shadows[i]->original_label());
}
}
// TODO(1222589): remove the reliance of PushTryHandler on a cached TOS
frame_->Push(eax);
- // Introduce shadow labels for all escapes from the try block,
- // including returns. We should probably try to unify the escaping
- // labels and the return label.
+ // Shadow the labels for all escapes from the try block, including
+ // returns. During shadowing, the original label is hidden as the
+ // LabelShadow and operations on the original actually affect the
+ // shadowing label.
+ //
+ // We should probably try to unify the escaping labels and the return
+ // label.
int nof_escapes = node->escaping_labels()->length();
List<LabelShadow*> shadows(1 + nof_escapes);
shadows.Add(new LabelShadow(&function_return_));
VisitStatements(node->try_block()->statements());
is_inside_try_ = was_inside_try;
- // Stop the introduced shadowing and count the number of required
- // unlinks.
+ // Stop the introduced shadowing and count the number of required unlinks.
+ // After shadowing stops, the original labels are unshadowed and the
+ // LabelShadows represent the formerly shadowing labels.
int nof_unlinks = 0;
for (int i = 0; i <= nof_escapes; i++) {
shadows[i]->StopShadowing();
__ Set(ecx, Immediate(Smi::FromInt(FALLING)));
if (nof_unlinks > 0) __ jmp(&unlink);
- // Generate code that sets the state for all used shadow labels.
+ // Generate code to set the state for the (formerly) shadowing labels that
+ // have been jumped to.
for (int i = 0; i <= nof_escapes; i++) {
if (shadows[i]->is_linked()) {
__ bind(shadows[i]);
- if (shadows[i]->shadowed() == &function_return_) {
- // Materialize the return value on the stack.
+ if (shadows[i]->original_label() == &function_return_) {
+ // If this label shadowed the function return, materialize the
+ // return value on the stack.
frame_->Push(eax);
} else {
- // Fake TOS for break and continue.
+ // Fake TOS for labels that shadowed breaks and continues.
frame_->Push(Immediate(Factory::undefined_value()));
}
__ Set(ecx, Immediate(Smi::FromInt(JUMPING + i)));
frame_->Pop(eax);
break_stack_height_ -= kFinallyStackSize;
- // Generate code that jumps to the right destination for all used
- // shadow labels.
+ // Generate code to jump to the right destination for all used (formerly)
+ // shadowing labels.
for (int i = 0; i <= nof_escapes; i++) {
if (shadows[i]->is_bound()) {
__ cmp(Operand(ecx), Immediate(Smi::FromInt(JUMPING + i)));
- __ j(equal, shadows[i]->shadowed());
+ __ j(equal, shadows[i]->original_label());
}
}