Author: kmilli...@chromium.org Date: Tue Mar 10 05:11:56 2009 New Revision: 1475
Modified: branches/bleeding_edge/src/ast.cc branches/bleeding_edge/src/ast.h branches/bleeding_edge/src/codegen-arm.cc branches/bleeding_edge/src/codegen-arm.h branches/bleeding_edge/src/codegen-ia32.cc branches/bleeding_edge/src/codegen-ia32.h branches/bleeding_edge/src/jump-target.cc branches/bleeding_edge/src/jump-target.h branches/bleeding_edge/src/parser.cc Log: Introduce a BreakTarget subclass of JumpTarget used to represent the blocks labeled by "break", "continue", and "return". BreakTargets are the only jump targets that appear in the AST, the only ones that can be uninitialized, and the only ones that can be shadowed. Review URL: http://codereview.chromium.org/42008 Modified: branches/bleeding_edge/src/ast.cc ============================================================================== --- branches/bleeding_edge/src/ast.cc (original) +++ branches/bleeding_edge/src/ast.cc Tue Mar 10 05:11:56 2009 @@ -152,7 +152,7 @@ } -void TargetCollector::AddTarget(JumpTarget* target) { +void TargetCollector::AddTarget(BreakTarget* target) { // Add the label to the collector, but discard duplicates. int length = targets_->length(); for (int i = 0; i < length; i++) { Modified: branches/bleeding_edge/src/ast.h ============================================================================== --- branches/bleeding_edge/src/ast.h (original) +++ branches/bleeding_edge/src/ast.h Tue Mar 10 05:11:56 2009 @@ -200,7 +200,7 @@ virtual BreakableStatement* AsBreakableStatement() { return this; } // Code generation - JumpTarget* break_target() { return &break_target_; } + BreakTarget* break_target() { return &break_target_; } // Used during code generation for restoring the stack when a // break/continue crosses a statement that keeps stuff on the stack. @@ -219,7 +219,7 @@ private: ZoneStringList* labels_; Type type_; - JumpTarget break_target_; + BreakTarget break_target_; int break_stack_height_; }; @@ -276,7 +276,7 @@ Statement* body() const { return body_; } // Code generation - JumpTarget* continue_target() { return &continue_target_; } + BreakTarget* continue_target() { return &continue_target_; } protected: explicit IterationStatement(ZoneStringList* labels) @@ -288,7 +288,7 @@ private: Statement* body_; - JumpTarget continue_target_; + BreakTarget continue_target_; }; @@ -451,12 +451,12 @@ CHECK(!is_default()); return label_; } - JumpTarget* body_target() { return &body_target_; } + BreakTarget* body_target() { return &body_target_; } ZoneList<Statement*>* statements() const { return statements_; } private: Expression* label_; - JumpTarget body_target_; + BreakTarget body_target_; ZoneList<Statement*>* statements_; }; @@ -517,23 +517,23 @@ // stack in the compiler; this should probably be reworked. class TargetCollector: public Node { public: - explicit TargetCollector(ZoneList<JumpTarget*>* targets) + explicit TargetCollector(ZoneList<BreakTarget*>* targets) : targets_(targets) { } // Adds a jump target to the collector. The collector stores a pointer not // a copy of the target to make binding work, so make sure not to pass in // references to something on the stack. - void AddTarget(JumpTarget* target); + void AddTarget(BreakTarget* target); // Virtual behaviour. TargetCollectors are never part of the AST. virtual void Accept(AstVisitor* v) { UNREACHABLE(); } virtual TargetCollector* AsTargetCollector() { return this; } - ZoneList<JumpTarget*>* targets() { return targets_; } + ZoneList<BreakTarget*>* targets() { return targets_; } private: - ZoneList<JumpTarget*>* targets_; + ZoneList<BreakTarget*>* targets_; }; @@ -542,16 +542,16 @@ explicit TryStatement(Block* try_block) : try_block_(try_block), escaping_targets_(NULL) { } - void set_escaping_targets(ZoneList<JumpTarget*>* targets) { + void set_escaping_targets(ZoneList<BreakTarget*>* targets) { escaping_targets_ = targets; } Block* try_block() const { return try_block_; } - ZoneList<JumpTarget*>* escaping_targets() const { return escaping_targets_; } + ZoneList<BreakTarget*>* escaping_targets() const { return escaping_targets_; } private: Block* try_block_; - ZoneList<JumpTarget*>* escaping_targets_; + ZoneList<BreakTarget*>* escaping_targets_; }; Modified: branches/bleeding_edge/src/codegen-arm.cc ============================================================================== --- branches/bleeding_edge/src/codegen-arm.cc (original) +++ branches/bleeding_edge/src/codegen-arm.cc Tue Mar 10 05:11:56 2009 @@ -4020,11 +4020,6 @@ #endif -bool CodeGenerator::IsActualFunctionReturn(JumpTarget* target) { - return (target == &function_return_ && !function_return_is_shadowed_); -} - - #undef __ #define __ masm-> Modified: branches/bleeding_edge/src/codegen-arm.h ============================================================================== --- branches/bleeding_edge/src/codegen-arm.h (original) +++ branches/bleeding_edge/src/codegen-arm.h Tue Mar 10 05:11:56 2009 @@ -427,10 +427,6 @@ void CodeForStatementPosition(Node* node); void CodeForSourcePosition(int pos); - // Is the given jump target the actual (ie, non-shadowed) function return - // target? - bool IsActualFunctionReturn(JumpTarget* target); - #ifdef DEBUG // True if the registers are valid for entry to a block. bool HasValidEntryRegisters(); @@ -453,7 +449,7 @@ int break_stack_height_; // Jump targets - JumpTarget function_return_; + BreakTarget function_return_; // True if the function return is shadowed (ie, jumping to the target // function_return_ does not jump to the true function return, but rather Modified: branches/bleeding_edge/src/codegen-ia32.cc ============================================================================== --- branches/bleeding_edge/src/codegen-ia32.cc (original) +++ branches/bleeding_edge/src/codegen-ia32.cc Tue Mar 10 05:11:56 2009 @@ -2235,7 +2235,7 @@ // indication of when it is safe to do so. static const bool test_at_bottom = false; - JumpTarget body; // Uninitialized. + JumpTarget body(this); // Initialized as forward-only. IncrementLoopNesting(); // If the condition is always false and has no side effects, we @@ -2254,13 +2254,12 @@ // Continue is the test at the bottom, no need to label the // test at the top. The body is a backward target. node->continue_target()->Initialize(this); - body.Initialize(this, JumpTarget::BIDIRECTIONAL); + body.make_bidirectional(); } else { // Label the test at the top as the continue target. The // body is a forward-only target. node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL); node->continue_target()->Bind(); - body.Initialize(this); } // Compile the test with the body as the true target and // preferred fall-through and with the break target as the Modified: branches/bleeding_edge/src/codegen-ia32.h ============================================================================== --- branches/bleeding_edge/src/codegen-ia32.h (original) +++ branches/bleeding_edge/src/codegen-ia32.h Tue Mar 10 05:11:56 2009 @@ -622,7 +622,7 @@ // Jump targets. // The target of the return from the function. - JumpTarget function_return_; + BreakTarget function_return_; // True if the function return is shadowed (ie, jumping to the target // function_return_ does not jump to the true function return, but rather Modified: branches/bleeding_edge/src/jump-target.cc ============================================================================== --- branches/bleeding_edge/src/jump-target.cc (original) +++ branches/bleeding_edge/src/jump-target.cc Tue Mar 10 05:11:56 2009 @@ -37,35 +37,13 @@ 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); - masm_ = cgen_->masm(); -} - - -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; } @@ -512,7 +490,31 @@ } -void JumpTarget::CopyTo(JumpTarget* destination) { +void JumpTarget::AddReachingFrame(VirtualFrame* frame) { + ASSERT(reaching_frames_.length() == merge_labels_.length()); + Label fresh; + merge_labels_.Add(fresh); + reaching_frames_.Add(frame); +} + + +// ------------------------------------------------------------------------- +// 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; +} + + +void BreakTarget::CopyTo(BreakTarget* destination) { ASSERT(destination != NULL); destination->cgen_ = cgen_; destination->masm_ = masm_; @@ -531,18 +533,10 @@ } -void JumpTarget::AddReachingFrame(VirtualFrame* frame) { - ASSERT(reaching_frames_.length() == merge_labels_.length()); - Label fresh; - merge_labels_.Add(fresh); - reaching_frames_.Add(frame); -} - - // ------------------------------------------------------------------------- // ShadowTarget implementation. -ShadowTarget::ShadowTarget(JumpTarget* shadowed) { +ShadowTarget::ShadowTarget(BreakTarget* shadowed) { ASSERT(shadowed != NULL); other_target_ = shadowed; @@ -574,7 +568,7 @@ // The states of this target, which was shadowed, and the original // target, which was shadowing, are swapped. - JumpTarget temp; + BreakTarget temp; other_target_->CopyTo(&temp); CopyTo(other_target_); temp.CopyTo(this); Modified: branches/bleeding_edge/src/jump-target.h ============================================================================== --- branches/bleeding_edge/src/jump-target.h (original) +++ branches/bleeding_edge/src/jump-target.h Tue Mar 10 05:11:56 2009 @@ -58,20 +58,8 @@ explicit JumpTarget(CodeGenerator* cgen, Directionality direction = FORWARD_ONLY); - // Construct a jump target without a code generator. A code generator - // must be supplied before using the jump target as a label. This is - // useful, eg, when jump targets are embedded in AST nodes. - JumpTarget(); - virtual ~JumpTarget() { Unuse(); } - // Supply a code generator and directionality to an already - // constructed jump target. This function expects to be given a - // non-null code generator, and to be called only when the code - // generator is not yet set. - void Initialize(CodeGenerator* cgen, - Directionality direction = FORWARD_ONLY); - // Accessors. CodeGenerator* code_generator() const { return cgen_; } @@ -82,6 +70,8 @@ entry_frame_ = frame; } + void make_bidirectional() { direction_ = BIDIRECTIONAL; } + // Predicates testing the state of the encapsulated label. bool is_bound() const { return is_bound_; } bool is_linked() const { return is_linked_; } @@ -97,13 +87,6 @@ // left dangling. void Reset(); - // Copy the state of this jump target to the destination. The lists - // of forward-reaching frames and merge-point labels are copied. - // All virtual frame pointers are copied, not the pointed-to frames. - // The previous state of the destination is overwritten, without - // deallocating pointed-to virtual frames. - void CopyTo(JumpTarget* destination); - // Emit a jump to the target. There must be a current frame at the // jump and there will be no current frame after the jump. void Jump(); @@ -170,7 +153,6 @@ // Used to emit code. MacroAssembler* masm_; - private: // Directionality flag set at initialization time. Directionality direction_; @@ -194,6 +176,7 @@ bool is_bound_; bool is_linked_; + private: // Add a virtual frame reaching this labeled block via a forward // jump, and a fresh label for its merge code. void AddReachingFrame(VirtualFrame* frame); @@ -211,22 +194,60 @@ // ------------------------------------------------------------------------- -// Shadow jump targets +// Break targets +// +// A break target is a jump target that can be used to break out of a +// statement that keeps extra state on the stack (eg, for/in or +// try/finally). They know the expected stack height at the target +// and will drop state from nested statements as part of merging. +// +// Break targets are used for return, break, and continue targets. + +class BreakTarget : public JumpTarget { + public: + // Construct a break target without a code generator. A code + // generator must be supplied before using the break target as a + // label. This is useful, eg, when break targets are embedded in AST + // nodes. + BreakTarget(); + + // Supply a code generator and directionality to an already + // constructed jump target. This function expects to be given a + // non-null code generator, and to be called only when the code + // generator is not yet set. + void Initialize(CodeGenerator* cgen, + Directionality direction = FORWARD_ONLY); + + // Copy the state of this break target to the destination. The + // lists of forward-reaching frames and merge-point labels are + // copied. All virtual frame pointers are copied, not the + // pointed-to frames. The previous state of the destination is + // overwritten, without deallocating pointed-to virtual frames. + void CopyTo(BreakTarget* destination); + + private: + DISALLOW_COPY_AND_ASSIGN(BreakTarget); +}; + + +// ------------------------------------------------------------------------- +// Shadow break targets // -// Shadow jump targets represent a jump target that is temporarily shadowed -// by another one (represented by the original during shadowing). They are -// used to catch jumps to labels in certain contexts, e.g. try blocks. -// After shadowing ends, the formerly shadowed target is again represented -// by the original and the ShadowTarget can be used as a jump target in its -// own right, representing the formerly shadowing target. +// A shadow break target represents a break target that is temporarily +// shadowed by another one (represented by the original during +// shadowing). They are used to catch jumps to labels in certain +// contexts, e.g. try blocks. After shadowing ends, the formerly +// shadowed target is again represented by the original and the +// ShadowTarget can be used as a jump target in its own right, +// representing the formerly shadowing target. -class ShadowTarget : public JumpTarget { +class ShadowTarget : public BreakTarget { public: // Construct a shadow jump target. After construction the shadow - // target object holds the state of the original jump target, and - // the original target is actually a fresh one that intercepts jumps - // intended for the shadowed one. - explicit ShadowTarget(JumpTarget* shadowed); + // target object holds the state of the original target, and the + // original target is actually a fresh one that intercepts control + // flow intended for the shadowed one. + explicit ShadowTarget(BreakTarget* shadowed); virtual ~ShadowTarget() { ASSERT(!is_shadowing_); @@ -239,12 +260,12 @@ // During shadowing, the currently shadowing target. After // shadowing, the target that was shadowed. - JumpTarget* other_target() const { return other_target_; } + BreakTarget* other_target() const { return other_target_; } private: // During shadowing, the currently shadowing target. After // shadowing, the target that was shadowed. - JumpTarget* other_target_; + BreakTarget* other_target_; #ifdef DEBUG bool is_shadowing_; Modified: branches/bleeding_edge/src/parser.cc ============================================================================== --- branches/bleeding_edge/src/parser.cc (original) +++ branches/bleeding_edge/src/parser.cc Tue Mar 10 05:11:56 2009 @@ -207,7 +207,7 @@ BreakableStatement* LookupBreakTarget(Handle<String> label, bool* ok); IterationStatement* LookupContinueTarget(Handle<String> label, bool* ok); - void RegisterTargetUse(JumpTarget* target, int index); + void RegisterTargetUse(BreakTarget* target, int index); // Create a number literal. Literal* NewNumberLiteral(double value); @@ -2052,7 +2052,7 @@ bool is_catch_block, bool* ok) { // Parse the statement and collect escaping labels. - ZoneList<JumpTarget*>* target_list = NEW(ZoneList<JumpTarget*>(0)); + ZoneList<BreakTarget*>* target_list = NEW(ZoneList<BreakTarget*>(0)); TargetCollector collector(target_list); Statement* stat; { Target target(this, &collector); @@ -2197,7 +2197,7 @@ Expect(Token::TRY, CHECK_OK); - ZoneList<JumpTarget*>* target_list = NEW(ZoneList<JumpTarget*>(0)); + ZoneList<BreakTarget*>* target_list = NEW(ZoneList<BreakTarget*>(0)); TargetCollector collector(target_list); Block* try_block; @@ -2220,7 +2220,7 @@ // then we will need to collect jump targets from the catch block. Since // we don't know yet if there will be a finally block, we always collect // the jump targets. - ZoneList<JumpTarget*>* catch_target_list = NEW(ZoneList<JumpTarget*>(0)); + ZoneList<BreakTarget*>* catch_target_list = NEW(ZoneList<BreakTarget*>(0)); TargetCollector catch_collector(catch_target_list); bool has_catch = false; if (tok == Token::CATCH) { @@ -3580,10 +3580,10 @@ } -void Parser::RegisterTargetUse(JumpTarget* target, int index) { - // Register that a jump target found at the given index in the target - // stack has been used from the top of the target stack. Add the jump - // target to any TargetCollectors passed on the stack. +void Parser::RegisterTargetUse(BreakTarget* target, int index) { + // Register that a break target found at the given index in the + // target stack has been used from the top of the target stack. Add + // the break target to any TargetCollectors passed on the stack. for (int i = target_stack_->length(); i-- > index;) { TargetCollector* collector = target_stack_->at(i)->AsTargetCollector(); if (collector != NULL) collector->AddTarget(target); --~--~---------~--~----~------------~-------~--~----~ v8-dev mailing list v8-dev@googlegroups.com http://groups.google.com/group/v8-dev -~----------~----~----~----~------~----~------~--~---