Author: [email protected]
Date: Thu Apr 2 01:58:18 2009
New Revision: 1669
Modified:
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/codegen.cc
branches/bleeding_edge/src/codegen.h
branches/bleeding_edge/src/jump-target-arm.cc
branches/bleeding_edge/src/jump-target-ia32.cc
branches/bleeding_edge/src/jump-target.cc
branches/bleeding_edge/src/jump-target.h
Log:
Clean up return statements in the code generator by explicitly
counting the reference to the return value and passing it to the
return label. This requires threading it through try/catch and
try/finally. The return value is loaded into eax more lazily than
before.
Also, perform some related refactoring of jump targets.
Review URL: http://codereview.chromium.org/56172
Modified: branches/bleeding_edge/src/codegen-arm.h
==============================================================================
--- branches/bleeding_edge/src/codegen-arm.h (original)
+++ branches/bleeding_edge/src/codegen-arm.h Thu Apr 2 01:58:18 2009
@@ -394,6 +394,7 @@
// positions are collected by the assembler and emitted with the
relocation
// information.
void CodeForFunctionPosition(FunctionLiteral* fun);
+ void CodeForReturnPosition(FunctionLiteral* fun);
void CodeForStatementPosition(Node* node);
void CodeForSourcePosition(int pos);
Modified: branches/bleeding_edge/src/codegen-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/codegen-ia32.cc (original)
+++ branches/bleeding_edge/src/codegen-ia32.cc Thu Apr 2 01:58:18 2009
@@ -274,25 +274,29 @@
if (has_valid_frame()) {
// If there is a valid frame, control flow can fall off the end of
// the body. In that case there is an implicit return statement.
- // Compiling a return statement will jump to the return sequence if
- // it is already generated or generate it if not.
ASSERT(!function_return_is_shadowed_);
- Literal undefined(Factory::undefined_value());
- ReturnStatement statement(&undefined);
- statement.set_statement_pos(fun->end_position());
- VisitReturnStatement(&statement);
+ CodeForReturnPosition(fun);
+ frame_->PrepareForReturn();
+ Result undefined(Factory::undefined_value(), this);
+ if (function_return_.is_bound()) {
+ function_return_.Jump(&undefined);
+ } else {
+ // Though this is a (possibly) backward block, the frames
+ // can only differ on their top element.
+ function_return_.Bind(&undefined, 1);
+ GenerateReturnSequence(&undefined);
+ }
} else if (function_return_.is_linked()) {
// If the return target has dangling jumps to it, then we have not
// yet generated the return sequence. This can happen when (a)
// control does not flow off the end of the body so we did not
// compile an artificial return statement just above, and (b) there
// are return statements in the body but (c) they are all shadowed.
- //
- // There is no valid frame here but it is safe (also necessary) to
- // load the return value into eax.
- __ mov(eax, Immediate(Factory::undefined_value()));
- function_return_.Bind();
- GenerateReturnSequence();
+ Result return_value(this);
+ // Though this is a (possibly) backward block, the frames can
+ // only differ on their top element.
+ function_return_.Bind(&return_value, 1);
+ GenerateReturnSequence(&return_value);
}
}
}
@@ -1943,52 +1947,37 @@
ASSERT(!in_spilled_code());
Comment cmnt(masm_, "[ ReturnStatement");
+ CodeForStatementPosition(node);
+ Load(node->expression());
+ Result return_value = frame_->Pop();
if (function_return_is_shadowed_) {
- // If the function return is shadowed, we spill all information
- // and just jump to the label.
- VirtualFrame::SpilledScope spilled_scope(this);
- CodeForStatementPosition(node);
- LoadAndSpill(node->expression());
- frame_->EmitPop(eax);
- function_return_.Jump();
+ function_return_.Jump(&return_value);
} else {
- // Load the returned value.
- CodeForStatementPosition(node);
- Load(node->expression());
-
- // Pop the result from the frame and prepare the frame for
- // returning thus making it easier to merge.
- Result result = frame_->Pop();
frame_->PrepareForReturn();
-
- // Move the result into register eax where it belongs.
- result.ToRegister(eax);
- // TODO(203): Instead of explictly calling Unuse on the result, it
- // might be better to pass the result to Jump and Bind below.
- result.Unuse();
-
- // If the function return label is already bound, we reuse the
- // code by jumping to the return site.
if (function_return_.is_bound()) {
- function_return_.Jump();
+ // If the function return label is already bound we reuse the
+ // code by jumping to the return site.
+ function_return_.Jump(&return_value);
} else {
- function_return_.Bind();
- GenerateReturnSequence();
+ // Though this is a (possibly) backward block, the frames can
+ // only differ on their top element.
+ function_return_.Bind(&return_value, 1);
+ GenerateReturnSequence(&return_value);
}
}
}
-void CodeGenerator::GenerateReturnSequence() {
+void CodeGenerator::GenerateReturnSequence(Result* return_value) {
// The return value is a live (but not currently reference counted)
// reference to eax. This is safe because the current frame does not
// contain a reference to eax (it is prepared for the return by spilling
// all registers).
- ASSERT(has_valid_frame());
if (FLAG_trace) {
- frame_->Push(eax); // Materialize result on the stack.
- frame_->CallRuntime(Runtime::kTraceExit, 1);
+ frame_->Push(return_value);
+ *return_value = frame_->CallRuntime(Runtime::kTraceExit, 1);
}
+ return_value->ToRegister(eax);
// Add a label for checking the size of the code used for returning.
Label check_exit_codesize;
@@ -2921,14 +2910,22 @@
}
}
- // Generate unlink code for the (formerly) shadowing targets that have
been
- // jumped to. Deallocate each shadow target.
+ // Generate unlink code for the (formerly) shadowing targets that
+ // have been jumped to. Deallocate each shadow target.
+ Result return_value(this);
for (int i = 0; i < shadows.length(); i++) {
if (shadows[i]->is_linked()) {
- // Unlink from try chain; be careful not to destroy the TOS.
- shadows[i]->Bind();
- // Because we can be jumping here (to spilled code) from unspilled
- // code, we need to reestablish a spilled frame at this block.
+ // Unlink from try chain; be careful not to destroy the TOS if
+ // there is one.
+ if (i == kReturnShadowIndex) {
+ shadows[i]->Bind(&return_value);
+ return_value.ToRegister(eax);
+ } else {
+ shadows[i]->Bind();
+ }
+ // Because we can be jumping here (to spilled code) from
+ // unspilled code, we need to reestablish a spilled frame at
+ // this block.
frame_->SpillAll();
// Reload sp from the top handler, because some statements that we
@@ -2943,10 +2940,12 @@
frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
// next_sp popped.
- if (!function_return_is_shadowed_ && i == kReturnShadowIndex) {
- frame_->PrepareForReturn();
+ if (i == kReturnShadowIndex) {
+ if (!function_return_is_shadowed_) frame_->PrepareForReturn();
+ shadows[i]->other_target()->Jump(&return_value);
+ } else {
+ shadows[i]->other_target()->Jump();
}
- shadows[i]->other_target()->Jump();
}
delete shadows[i];
}
@@ -3043,13 +3042,18 @@
for (int i = 0; i < shadows.length(); i++) {
if (shadows[i]->is_linked()) {
// If we have come from the shadowed return, the return value is
- // in (a non-refcounted reference to) eax. We must preserve it
- // until it is pushed.
- //
+ // on the virtual frame. We must preserve it until it is
+ // pushed.
+ if (i == kReturnShadowIndex) {
+ Result return_value(this);
+ shadows[i]->Bind(&return_value);
+ return_value.ToRegister(eax);
+ } else {
+ shadows[i]->Bind();
+ }
// Because we can be jumping here (to spilled code) from
// unspilled code, we need to reestablish a spilled frame at
// this block.
- shadows[i]->Bind();
frame_->SpillAll();
// Reload sp from the top handler, because some statements that
@@ -3103,14 +3107,23 @@
// formerly shadowing targets. Deallocate each shadow target.
for (int i = 0; i < shadows.length(); i++) {
if (has_valid_frame() && shadows[i]->is_bound()) {
- JumpTarget* original = shadows[i]->other_target();
+ BreakTarget* original = shadows[i]->other_target();
__ cmp(Operand(ecx), Immediate(Smi::FromInt(JUMPING + i)));
- if (!function_return_is_shadowed_ && i == kReturnShadowIndex) {
- JumpTarget skip(this);
- skip.Branch(not_equal);
- frame_->PrepareForReturn();
- original->Jump();
- skip.Bind();
+ if (i == kReturnShadowIndex) {
+ // The return value is (already) in eax.
+ Result return_value = allocator_->Allocate(eax);
+ ASSERT(return_value.is_valid());
+ if (function_return_is_shadowed_) {
+ original->Branch(equal, &return_value);
+ } else {
+ // Branch around the preparation for return which may emit
+ // code.
+ JumpTarget skip(this);
+ skip.Branch(not_equal);
+ frame_->PrepareForReturn();
+ original->Jump(&return_value);
+ skip.Bind();
+ }
} else {
original->Branch(equal);
}
Modified: branches/bleeding_edge/src/codegen-ia32.h
==============================================================================
--- branches/bleeding_edge/src/codegen-ia32.h (original)
+++ branches/bleeding_edge/src/codegen-ia32.h Thu Apr 2 01:58:18 2009
@@ -371,11 +371,10 @@
// Main code generation function
void GenCode(FunctionLiteral* fun);
- // Generate the return sequence code. Should be called no more than once
- // per compiled function (it binds the return target, which can not be
- // done more than once). The return value is assumed to be in eax by the
- // code generated.
- void GenerateReturnSequence();
+ // Generate the return sequence code. Should be called no more than
+ // once per compiled function, immediately after binding the return
+ // target (which can not be done more than once).
+ void GenerateReturnSequence(Result* return_value);
// The following are used by class Reference.
void LoadReference(Reference* ref);
@@ -567,6 +566,7 @@
// positions are collected by the assembler and emitted with the
relocation
// information.
void CodeForFunctionPosition(FunctionLiteral* fun);
+ void CodeForReturnPosition(FunctionLiteral* fun);
void CodeForStatementPosition(Node* node);
void CodeForSourcePosition(int pos);
Modified: branches/bleeding_edge/src/codegen.cc
==============================================================================
--- branches/bleeding_edge/src/codegen.cc (original)
+++ branches/bleeding_edge/src/codegen.cc Thu Apr 2 01:58:18 2009
@@ -566,12 +566,23 @@
}
+void CodeGenerator::CodeForReturnPosition(FunctionLiteral* fun) {
+ if (FLAG_debug_info) {
+ int pos = fun->start_position();
+ if (pos != RelocInfo::kNoPosition) {
+ masm()->RecordStatementPosition(pos);
+ masm()->RecordPosition(pos);
+ }
+ }
+}
+
+
void CodeGenerator::CodeForStatementPosition(Node* node) {
if (FLAG_debug_info) {
int pos = node->statement_pos();
if (pos != RelocInfo::kNoPosition) {
masm()->RecordStatementPosition(pos);
- CodeForSourcePosition(pos);
+ masm()->RecordPosition(pos);
}
}
}
Modified: branches/bleeding_edge/src/codegen.h
==============================================================================
--- branches/bleeding_edge/src/codegen.h (original)
+++ branches/bleeding_edge/src/codegen.h Thu Apr 2 01:58:18 2009
@@ -35,37 +35,41 @@
// Include the declaration of the architecture defined class CodeGenerator.
// The contract to the shared code is that the the CodeGenerator is a
subclass
// of Visitor and that the following methods are available publicly:
-// CodeGenerator::MakeCode
-// CodeGenerator::SetFunctionInfo
-// CodeGenerator::masm
-// CodeGenerator::frame
-// CodeGenerator::has_valid_frame
-// CodeGenerator::SetFrame
-// CodeGenerator::DeleteFrame
-// CodeGenerator::allocator
-// CodeGenerator::AddDeferred
-// CodeGenerator::in_spilled_code
-// CodeGenerator::set_in_spilled_code
+// MakeCode
+// SetFunctionInfo
+// masm
+// frame
+// has_valid_frame
+// SetFrame
+// DeleteFrame
+// allocator
+// AddDeferred
+// in_spilled_code
+// set_in_spilled_code
//
// These methods are either used privately by the shared code or
implemented as
// shared code:
-// CodeGenerator::CodeGenerator
-// CodeGenerator::~CodeGenerator
-// CodeGenerator::ProcessDeferred
-// CodeGenerator::ClearDeferred
-// CodeGenerator::GenCode
-// CodeGenerator::BuildBoilerplate
-// CodeGenerator::ComputeCallInitialize
-// CodeGenerator::ComputeCallInitializeInLoop
-// CodeGenerator::ProcessDeclarations
-// CodeGenerator::DeclareGlobals
-// CodeGenerator::CheckForInlineRuntimeCall
-// CodeGenerator::GenerateFastCaseSwitchStatement
-// CodeGenerator::GenerateFastCaseSwitchCases
-// CodeGenerator::TryGenerateFastCaseSwitchStatement
-// CodeGenerator::GenerateFastCaseSwitchJumpTable
-// CodeGenerator::FastCaseSwitchMinCaseCount
-// CodeGenerator::FastCaseSwitchMaxOverheadFactor
+// CodeGenerator
+// ~CodeGenerator
+// ProcessDeferred
+// ClearDeferred
+// GenCode
+// BuildBoilerplate
+// ComputeCallInitialize
+// ComputeCallInitializeInLoop
+// ProcessDeclarations
+// DeclareGlobals
+// CheckForInlineRuntimeCall
+// GenerateFastCaseSwitchStatement
+// GenerateFastCaseSwitchCases
+// TryGenerateFastCaseSwitchStatement
+// GenerateFastCaseSwitchJumpTable
+// FastCaseSwitchMinCaseCount
+// FastCaseSwitchMaxOverheadFactor
+// CodeForFunctionPosition
+// CodeForReturnPosition
+// CodeForStatementPosition
+// CodeForSourcePosition
#ifdef ARM
#include "codegen-arm.h"
Modified: branches/bleeding_edge/src/jump-target-arm.cc
==============================================================================
--- branches/bleeding_edge/src/jump-target-arm.cc (original)
+++ branches/bleeding_edge/src/jump-target-arm.cc Thu Apr 2 01:58:18 2009
@@ -37,7 +37,7 @@
#define __ masm_->
-void JumpTarget::Jump() {
+void JumpTarget::DoJump() {
ASSERT(cgen_ != NULL);
ASSERT(cgen_->has_valid_frame());
// Live non-frame registers are not allowed at unconditional jumps
@@ -65,7 +65,7 @@
}
-void JumpTarget::Branch(Condition cc, Hint ignored) {
+void JumpTarget::DoBranch(Condition cc, Hint ignored) {
ASSERT(cgen_ != NULL);
ASSERT(cgen_->has_valid_frame());
@@ -148,7 +148,7 @@
}
-void JumpTarget::Bind(int mergable_elements) {
+void JumpTarget::DoBind(int mergable_elements) {
ASSERT(cgen_ != NULL);
ASSERT(!is_bound());
Modified: branches/bleeding_edge/src/jump-target-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/jump-target-ia32.cc (original)
+++ branches/bleeding_edge/src/jump-target-ia32.cc Thu Apr 2 01:58:18 2009
@@ -37,7 +37,7 @@
#define __ masm_->
-void JumpTarget::Jump() {
+void JumpTarget::DoJump() {
ASSERT(cgen_ != NULL);
ASSERT(cgen_->has_valid_frame());
// Live non-frame registers are not allowed at unconditional jumps
@@ -65,7 +65,7 @@
}
-void JumpTarget::Branch(Condition cc, Hint hint) {
+void JumpTarget::DoBranch(Condition cc, Hint hint) {
ASSERT(cgen_ != NULL);
ASSERT(cgen_->has_valid_frame());
@@ -148,7 +148,7 @@
}
-void JumpTarget::Bind(int mergable_elements) {
+void JumpTarget::DoBind(int mergable_elements) {
ASSERT(cgen_ != NULL);
ASSERT(!is_bound());
Modified: branches/bleeding_edge/src/jump-target.cc
==============================================================================
--- branches/bleeding_edge/src/jump-target.cc (original)
+++ branches/bleeding_edge/src/jump-target.cc Thu Apr 2 01:58:18 2009
@@ -298,12 +298,17 @@
}
+void JumpTarget::Jump() {
+ DoJump();
+}
+
+
void JumpTarget::Jump(Result* arg) {
ASSERT(cgen_ != NULL);
ASSERT(cgen_->has_valid_frame());
cgen_->frame()->Push(arg);
- Jump();
+ DoJump();
}
@@ -313,7 +318,7 @@
cgen_->frame()->Push(arg0);
cgen_->frame()->Push(arg1);
- Jump();
+ DoJump();
}
@@ -324,7 +329,12 @@
cgen_->frame()->Push(arg0);
cgen_->frame()->Push(arg1);
cgen_->frame()->Push(arg2);
- Jump();
+ DoJump();
+}
+
+
+void JumpTarget::Branch(Condition cc, Hint hint) {
+ DoBranch(cc, hint);
}
@@ -352,7 +362,7 @@
DECLARE_ARGCHECK_VARS(arg);
cgen_->frame()->Push(arg);
- Branch(cc, hint);
+ DoBranch(cc, hint);
*arg = cgen_->frame()->Pop();
ASSERT_ARGCHECK(arg);
@@ -370,7 +380,7 @@
cgen_->frame()->Push(arg0);
cgen_->frame()->Push(arg1);
- Branch(cc, hint);
+ DoBranch(cc, hint);
*arg1 = cgen_->frame()->Pop();
*arg0 = cgen_->frame()->Pop();
@@ -396,7 +406,7 @@
cgen_->frame()->Push(arg0);
cgen_->frame()->Push(arg1);
cgen_->frame()->Push(arg2);
- Branch(cc, hint);
+ DoBranch(cc, hint);
*arg2 = cgen_->frame()->Pop();
*arg1 = cgen_->frame()->Pop();
*arg0 = cgen_->frame()->Pop();
@@ -427,7 +437,7 @@
cgen_->frame()->Push(arg1);
cgen_->frame()->Push(arg2);
cgen_->frame()->Push(arg3);
- Branch(cc, hint);
+ DoBranch(cc, hint);
*arg3 = cgen_->frame()->Pop();
*arg2 = cgen_->frame()->Pop();
*arg1 = cgen_->frame()->Pop();
@@ -439,17 +449,47 @@
ASSERT_ARGCHECK(arg3);
}
+
+void BreakTarget::Branch(Condition cc, Result* arg, 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 DoBranch'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(arg); // May emit merge code here.
+ fall_through.Bind();
+ } else {
+ DECLARE_ARGCHECK_VARS(arg);
+ cgen_->frame()->Push(arg);
+ DoBranch(cc, hint);
+ *arg = cgen_->frame()->Pop();
+ ASSERT_ARGCHECK(arg);
+ }
+}
+
#undef DECLARE_ARGCHECK_VARS
#undef ASSERT_ARGCHECK
+void JumpTarget::Bind(int mergable_elements) {
+ DoBind(mergable_elements);
+}
+
+
void JumpTarget::Bind(Result* arg, int mergable_elements) {
ASSERT(cgen_ != NULL);
if (cgen_->has_valid_frame()) {
cgen_->frame()->Push(arg);
}
- Bind(mergable_elements);
+ DoBind(mergable_elements);
*arg = cgen_->frame()->Pop();
}
@@ -461,7 +501,7 @@
cgen_->frame()->Push(arg0);
cgen_->frame()->Push(arg1);
}
- Bind(mergable_elements);
+ DoBind(mergable_elements);
*arg1 = cgen_->frame()->Pop();
*arg0 = cgen_->frame()->Pop();
}
@@ -478,7 +518,7 @@
cgen_->frame()->Push(arg1);
cgen_->frame()->Push(arg2);
}
- Bind(mergable_elements);
+ DoBind(mergable_elements);
*arg2 = cgen_->frame()->Pop();
*arg1 = cgen_->frame()->Pop();
*arg0 = cgen_->frame()->Pop();
@@ -498,7 +538,7 @@
cgen_->frame()->Push(arg2);
cgen_->frame()->Push(arg3);
}
- Bind(mergable_elements);
+ DoBind(mergable_elements);
*arg3 = cgen_->frame()->Pop();
*arg2 = cgen_->frame()->Pop();
*arg1 = cgen_->frame()->Pop();
@@ -548,10 +588,20 @@
ASSERT(cgen_ != NULL);
ASSERT(cgen_->has_valid_frame());
- // This is a break target so drop leftover statement state from the
- // frame before merging.
+ // Drop leftover statement state from the frame before merging.
cgen_->frame()->ForgetElements(cgen_->frame()->height() -
expected_height_);
- JumpTarget::Jump();
+ DoJump();
+}
+
+
+void BreakTarget::Jump(Result* arg) {
+ ASSERT(cgen_ != NULL);
+ ASSERT(cgen_->has_valid_frame());
+
+ // Drop leftover statement state from the frame before merging.
+ cgen_->frame()->ForgetElements(cgen_->frame()->height() -
expected_height_);
+ cgen_->frame()->Push(arg);
+ DoJump();
}
@@ -561,9 +611,9 @@
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.
+ // We negate and branch here rather than using DoBranch'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.
@@ -571,14 +621,13 @@
Jump(); // May emit merge code here.
fall_through.Bind();
} else {
- JumpTarget::Branch(cc, hint);
+ DoBranch(cc, hint);
}
}
void BreakTarget::Bind(int mergable_elements) {
#ifdef DEBUG
- ASSERT(mergable_elements == kAllElements);
ASSERT(cgen_ != NULL);
// All the forward-reaching frames should have been adjusted at the
// jumps to this target.
@@ -587,13 +636,35 @@
reaching_frames_[i]->height() == expected_height_);
}
#endif
- // This is a break target so we drop leftover statement state from
- // the frame before merging, even on the fall through. This is
- // because we can bind the return target with state on the frame.
+ // Drop leftover statement state from the frame before merging, even
+ // on the fall through. This is so we can bind the return target
+ // with state on the frame.
+ if (cgen_->has_valid_frame()) {
+ cgen_->frame()->ForgetElements(cgen_->frame()->height() -
expected_height_);
+ }
+ DoBind(mergable_elements);
+}
+
+
+void BreakTarget::Bind(Result* arg, int mergable_elements) {
+#ifdef DEBUG
+ ASSERT(cgen_ != NULL);
+ // All the forward-reaching frames should have been adjusted at the
+ // jumps to this target.
+ for (int i = 0; i < reaching_frames_.length(); i++) {
+ ASSERT(reaching_frames_[i] == NULL ||
+ reaching_frames_[i]->height() == expected_height_ + 1);
+ }
+#endif
+ // Drop leftover statement state from the frame before merging, even
+ // on the fall through. This is so we can bind the return target
+ // with state on the frame.
if (cgen_->has_valid_frame()) {
cgen_->frame()->ForgetElements(cgen_->frame()->height() -
expected_height_);
+ cgen_->frame()->Push(arg);
}
- JumpTarget::Bind(mergable_elements);
+ DoBind(mergable_elements);
+ *arg = cgen_->frame()->Pop();
}
Modified: branches/bleeding_edge/src/jump-target.h
==============================================================================
--- branches/bleeding_edge/src/jump-target.h (original)
+++ branches/bleeding_edge/src/jump-target.h Thu Apr 2 01:58:18 2009
@@ -105,7 +105,7 @@
// 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.
virtual void Jump();
- void Jump(Result* arg);
+ virtual void Jump(Result* arg);
void Jump(Result* arg0, Result* arg1);
void Jump(Result* arg0, Result* arg1, Result* arg2);
@@ -113,7 +113,7 @@
// frame at the branch. The current frame will fall through to the
// code after the branch.
virtual void Branch(Condition cc, Hint hint = no_hint);
- void Branch(Condition cc, Result* arg, Hint hint = no_hint);
+ virtual void Branch(Condition cc, Result* arg, Hint hint = no_hint);
void Branch(Condition cc, Result* arg0, Result* arg1, Hint hint =
no_hint);
void Branch(Condition cc,
Result* arg0,
@@ -141,7 +141,7 @@
// frame elements must be mergable. Mergable elements are ignored
// completely for forward-only jump targets.
virtual void Bind(int mergable_elements = kAllElements);
- void Bind(Result* arg, int mergable_elements = kAllElements);
+ virtual void Bind(Result* arg, int mergable_elements = kAllElements);
void Bind(Result* arg0, Result* arg1, int mergable_elements =
kAllElements);
void Bind(Result* arg0,
Result* arg1,
@@ -191,6 +191,12 @@
bool is_bound_;
bool is_linked_;
+ // Implementations of Jump, Branch, and Bind with all arguments and
+ // return values using the virtual frame.
+ void DoJump();
+ void DoBranch(Condition cc, Hint hint);
+ void DoBind(int mergable_elements);
+
private:
// Add a virtual frame reaching this labeled block via a forward
// jump, and a fresh label for its merge code.
@@ -243,16 +249,19 @@
// 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.
virtual void Jump();
+ virtual void Jump(Result* arg);
// Emit a conditional branch to the target. There must be a current
// frame at the branch. The current frame will fall through to the
// code after the branch.
virtual void Branch(Condition cc, Hint hint = no_hint);
+ virtual void Branch(Condition cc, Result* arg, Hint hint = no_hint);
// Bind a break target. If there is no current frame at the binding
// site, there must be at least one frame reaching via a forward
// jump.
virtual void Bind(int mergable_elements = kAllElements);
+ virtual void Bind(Result* arg, int mergable_elements = kAllElements);
// Setter for expected height.
void set_expected_height(int expected) { expected_height_ = expected; }
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---