Commit ef85ba46 authored by ager@chromium.org's avatar ager@chromium.org

First round of size reduction for JumpTargets. Reduce their size by

two words: there is no reason to keep a pointer to the current code
generator and macro assembler in the JumpTarget.
Review URL: http://codereview.chromium.org/113458

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1987 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 13a96b3a
......@@ -136,7 +136,7 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
frame_->AllocateStackSlots(scope_->num_stack_slots());
// Initialize the function return target after the locals are set
// up, because it needs the expected frame height from the frame.
function_return_.Initialize(this, JumpTarget::BIDIRECTIONAL);
function_return_.set_direction(JumpTarget::BIDIRECTIONAL);
function_return_is_shadowed_ = false;
VirtualFrame::SpilledScope spilled_scope(this);
......@@ -456,14 +456,14 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
int original_height = frame_->height();
#endif
ASSERT(!in_spilled_code());
JumpTarget true_target(this);
JumpTarget false_target(this);
JumpTarget true_target;
JumpTarget false_target;
LoadCondition(x, typeof_state, &true_target, &false_target, false);
if (has_cc()) {
// Convert cc_reg_ into a boolean value.
JumpTarget loaded(this);
JumpTarget materialize_true(this);
JumpTarget loaded;
JumpTarget materialize_true;
materialize_true.Branch(cc_reg_);
__ mov(r0, Operand(Factory::false_value()));
frame_->EmitPush(r0);
......@@ -478,7 +478,7 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
if (true_target.is_linked() || false_target.is_linked()) {
// We have at least one condition value that has been "translated"
// into a branch, thus it needs to be loaded explicitly.
JumpTarget loaded(this);
JumpTarget loaded;
if (frame_ != NULL) {
loaded.Jump(); // Don't lose the current TOS.
}
......@@ -865,7 +865,7 @@ void CodeGenerator::SmiOperation(Token::Value op,
int int_value = Smi::cast(*value)->value();
JumpTarget exit(this);
JumpTarget exit;
frame_->EmitPop(r0);
switch (op) {
......@@ -995,8 +995,8 @@ void CodeGenerator::Comparison(Condition cc, bool strict) {
// Strict only makes sense for equality comparisons.
ASSERT(!strict || cc == eq);
JumpTarget exit(this);
JumpTarget smi(this);
JumpTarget exit;
JumpTarget smi;
// Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order.
if (cc == gt || cc == le) {
cc = ReverseCondition(cc);
......@@ -1156,7 +1156,7 @@ void CodeGenerator::VisitBlock(Block* node) {
VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ Block");
CodeForStatementPosition(node);
node->break_target()->Initialize(this);
node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
VisitStatementsAndSpill(node->statements());
if (node->break_target()->is_linked()) {
node->break_target()->Bind();
......@@ -1290,11 +1290,11 @@ void CodeGenerator::VisitIfStatement(IfStatement* node) {
CodeForStatementPosition(node);
JumpTarget exit(this);
JumpTarget exit;
if (has_then_stm && has_else_stm) {
Comment cmnt(masm_, "[ IfThenElse");
JumpTarget then(this);
JumpTarget else_(this);
JumpTarget then;
JumpTarget else_;
// if (cond)
LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
&then, &else_, true);
......@@ -1318,7 +1318,7 @@ void CodeGenerator::VisitIfStatement(IfStatement* node) {
} else if (has_then_stm) {
Comment cmnt(masm_, "[ IfThen");
ASSERT(!has_else_stm);
JumpTarget then(this);
JumpTarget then;
// if (cond)
LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
&then, &exit, true);
......@@ -1334,7 +1334,7 @@ void CodeGenerator::VisitIfStatement(IfStatement* node) {
} else if (has_else_stm) {
Comment cmnt(masm_, "[ IfElse");
ASSERT(!has_then_stm);
JumpTarget else_(this);
JumpTarget else_;
// if (!cond)
LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
&exit, &else_, true);
......@@ -1424,7 +1424,7 @@ void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) {
frame_->CallRuntime(Runtime::kPushContext, 1);
}
#ifdef DEBUG
JumpTarget verified_true(this);
JumpTarget verified_true;
__ cmp(r0, Operand(cp));
verified_true.Branch(eq);
__ stop("PushContext: r0 is expected to be the same as cp");
......@@ -1468,8 +1468,8 @@ void CodeGenerator::GenerateFastCaseSwitchJumpTable(
Vector<Label*> case_targets,
Vector<Label> case_labels) {
VirtualFrame::SpilledScope spilled_scope(this);
JumpTarget setup_default(this);
JumpTarget is_smi(this);
JumpTarget setup_default;
JumpTarget is_smi;
// A non-null default label pointer indicates a default case among
// the case labels. Otherwise we use the break target as a
......@@ -1539,7 +1539,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ SwitchStatement");
CodeForStatementPosition(node);
node->break_target()->Initialize(this);
node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
LoadAndSpill(node->tag());
if (TryGenerateFastCaseSwitchStatement(node)) {
......@@ -1547,10 +1547,10 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
return;
}
JumpTarget next_test(this);
JumpTarget fall_through(this);
JumpTarget default_entry(this);
JumpTarget default_exit(this, JumpTarget::BIDIRECTIONAL);
JumpTarget next_test;
JumpTarget fall_through;
JumpTarget default_entry;
JumpTarget default_exit(JumpTarget::BIDIRECTIONAL);
ZoneList<CaseClause*>* cases = node->cases();
int length = cases->length();
CaseClause* default_clause = NULL;
......@@ -1633,7 +1633,7 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ LoopStatement");
CodeForStatementPosition(node);
node->break_target()->Initialize(this);
node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
// Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a
// known result for the test expression, with no side effects.
......@@ -1654,19 +1654,19 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
switch (node->type()) {
case LoopStatement::DO_LOOP: {
JumpTarget body(this, JumpTarget::BIDIRECTIONAL);
JumpTarget body(JumpTarget::BIDIRECTIONAL);
// Label the top of the loop for the backward CFG edge. If the test
// is always true we can use the continue target, and if the test is
// always false there is no need.
if (info == ALWAYS_TRUE) {
node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
node->continue_target()->Bind();
} else if (info == ALWAYS_FALSE) {
node->continue_target()->Initialize(this);
node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
} else {
ASSERT(info == DONT_KNOW);
node->continue_target()->Initialize(this);
node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
body.Bind();
}
......@@ -1713,11 +1713,11 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
// Label the top of the loop with the continue target for the backward
// CFG edge.
node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
node->continue_target()->Bind();
if (info == DONT_KNOW) {
JumpTarget body(this);
JumpTarget body;
LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF,
&body, node->break_target(), true);
if (has_valid_frame()) {
......@@ -1743,7 +1743,7 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
}
case LoopStatement::FOR_LOOP: {
JumpTarget loop(this, JumpTarget::BIDIRECTIONAL);
JumpTarget loop(JumpTarget::BIDIRECTIONAL);
if (node->init() != NULL) {
VisitAndSpill(node->init());
......@@ -1755,16 +1755,16 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
// If there is no update statement, label the top of the loop with the
// continue target, otherwise with the loop target.
if (node->next() == NULL) {
node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
node->continue_target()->Bind();
} else {
node->continue_target()->Initialize(this);
node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
loop.Bind();
}
// If the test is always true, there is no need to compile it.
if (info == DONT_KNOW) {
JumpTarget body(this);
JumpTarget body;
LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF,
&body, node->break_target(), true);
if (has_valid_frame()) {
......@@ -1824,12 +1824,12 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) {
Comment cmnt(masm_, "[ ForInStatement");
CodeForStatementPosition(node);
JumpTarget primitive(this);
JumpTarget jsobject(this);
JumpTarget fixed_array(this);
JumpTarget entry(this, JumpTarget::BIDIRECTIONAL);
JumpTarget end_del_check(this);
JumpTarget exit(this);
JumpTarget primitive;
JumpTarget jsobject;
JumpTarget fixed_array;
JumpTarget entry(JumpTarget::BIDIRECTIONAL);
JumpTarget end_del_check;
JumpTarget exit;
// Get the object to enumerate over (converted to JSObject).
LoadAndSpill(node->enumerable());
......@@ -1914,8 +1914,8 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) {
// sp[4] : enumerable
// Grab the current frame's height for the break and continue
// targets only after all the state is pushed on the frame.
node->break_target()->Initialize(this);
node->continue_target()->Initialize(this);
node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
__ ldr(r0, frame_->ElementAt(0)); // load the current count
__ ldr(r1, frame_->ElementAt(1)); // load the length
......@@ -2018,8 +2018,8 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) {
Comment cmnt(masm_, "[ TryCatch");
CodeForStatementPosition(node);
JumpTarget try_block(this);
JumpTarget exit(this);
JumpTarget try_block;
JumpTarget exit;
try_block.Call();
// --- Catch block ---
......@@ -2150,8 +2150,8 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
// break/continue from within the try block.
enum { FALLING, THROWING, JUMPING };
JumpTarget try_block(this);
JumpTarget finally_block(this);
JumpTarget try_block;
JumpTarget finally_block;
try_block.Call();
......@@ -2296,7 +2296,7 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
JumpTarget* original = shadows[i]->other_target();
__ cmp(r2, Operand(Smi::FromInt(JUMPING + i)));
if (!function_return_is_shadowed_ && i == kReturnShadowIndex) {
JumpTarget skip(this);
JumpTarget skip;
skip.Branch(ne);
frame_->PrepareForReturn();
original->Jump();
......@@ -2309,7 +2309,7 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
if (has_valid_frame()) {
// Check if we need to rethrow the exception.
JumpTarget exit(this);
JumpTarget exit;
__ cmp(r2, Operand(Smi::FromInt(THROWING)));
exit.Branch(ne);
......@@ -2391,9 +2391,9 @@ void CodeGenerator::VisitConditional(Conditional* node) {
#endif
VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ Conditional");
JumpTarget then(this);
JumpTarget else_(this);
JumpTarget exit(this);
JumpTarget then;
JumpTarget else_;
JumpTarget exit;
LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
&then, &else_, true);
Branch(false, &else_);
......@@ -2412,8 +2412,8 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
if (slot->type() == Slot::LOOKUP) {
ASSERT(slot->var()->is_dynamic());
JumpTarget slow(this);
JumpTarget done(this);
JumpTarget slow;
JumpTarget done;
// Generate fast-case code for variables that might be shadowed by
// eval-introduced variables. Eval is used a lot without
......@@ -2620,7 +2620,7 @@ void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
__ ldr(r2, FieldMemOperand(r1, literal_offset));
JumpTarget done(this);
JumpTarget done;
__ cmp(r2, Operand(Factory::undefined_value()));
done.Branch(ne);
......@@ -3266,7 +3266,7 @@ void CodeGenerator::VisitCallNew(CallNew* node) {
void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
VirtualFrame::SpilledScope spilled_scope(this);
ASSERT(args->length() == 1);
JumpTarget leave(this);
JumpTarget leave;
LoadAndSpill(args->at(0));
frame_->EmitPop(r0); // r0 contains object.
// if (object->IsSmi()) return the object.
......@@ -3288,7 +3288,7 @@ void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) {
VirtualFrame::SpilledScope spilled_scope(this);
ASSERT(args->length() == 2);
JumpTarget leave(this);
JumpTarget leave;
LoadAndSpill(args->at(0)); // Load the object.
LoadAndSpill(args->at(1)); // Load the value.
frame_->EmitPop(r0); // r0 contains value
......@@ -3364,7 +3364,7 @@ void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
VirtualFrame::SpilledScope spilled_scope(this);
ASSERT(args->length() == 1);
LoadAndSpill(args->at(0));
JumpTarget answer(this);
JumpTarget answer;
// We need the CC bits to come out as not_equal in the case where the
// object is a smi. This can't be done with the usual test opcode so
// we use XOR to get the right CC bits.
......@@ -3568,8 +3568,8 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
case Token::BIT_NOT: {
// smi check
JumpTarget smi_label(this);
JumpTarget continue_label(this);
JumpTarget smi_label;
JumpTarget continue_label;
__ tst(r0, Operand(kSmiTagMask));
smi_label.Branch(eq);
......@@ -3595,7 +3595,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
case Token::ADD: {
// Smi check.
JumpTarget continue_label(this);
JumpTarget continue_label;
__ tst(r0, Operand(kSmiTagMask));
continue_label.Branch(eq);
frame_->EmitPush(r0);
......@@ -3649,8 +3649,8 @@ void CodeGenerator::VisitCountOperation(CountOperation* node) {
target.GetValueAndSpill(NOT_INSIDE_TYPEOF);
frame_->EmitPop(r0);
JumpTarget slow(this);
JumpTarget exit(this);
JumpTarget slow;
JumpTarget exit;
// Load the value (1) into register r1.
__ mov(r1, Operand(Smi::FromInt(1)));
......@@ -3739,7 +3739,7 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
// of compiling the binary operation is materialized or not.
if (op == Token::AND) {
JumpTarget is_true(this);
JumpTarget is_true;
LoadConditionAndSpill(node->left(),
NOT_INSIDE_TYPEOF,
&is_true,
......@@ -3757,8 +3757,8 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
false);
} else {
JumpTarget pop_and_continue(this);
JumpTarget exit(this);
JumpTarget pop_and_continue;
JumpTarget exit;
__ ldr(r0, frame_->Top()); // dup the stack top
frame_->EmitPush(r0);
......@@ -3781,7 +3781,7 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
}
} else if (op == Token::OR) {
JumpTarget is_false(this);
JumpTarget is_false;
LoadConditionAndSpill(node->left(),
NOT_INSIDE_TYPEOF,
true_target(),
......@@ -3799,8 +3799,8 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
false);
} else {
JumpTarget pop_and_continue(this);
JumpTarget exit(this);
JumpTarget pop_and_continue;
JumpTarget exit;
__ ldr(r0, frame_->Top());
frame_->EmitPush(r0);
......@@ -4241,7 +4241,7 @@ void Reference::SetValue(InitState init_state) {
} else {
ASSERT(!slot->var()->is_dynamic());
JumpTarget exit(cgen_);
JumpTarget exit;
if (init_state == CONST_INIT) {
ASSERT(slot->var()->mode() == Variable::CONST);
// Only the first const initialization must be executed (the slot
......
......@@ -28,6 +28,7 @@
#include "v8.h"
#include "codegen-inl.h"
#include "jump-target-inl.h"
#include "register-allocator-inl.h"
namespace v8 { namespace internal {
......@@ -35,21 +36,20 @@ namespace v8 { namespace internal {
// -------------------------------------------------------------------------
// JumpTarget implementation.
#define __ ACCESS_MASM(masm_)
#define __ ACCESS_MASM(cgen()->masm())
void JumpTarget::DoJump() {
ASSERT(cgen_ != NULL);
ASSERT(cgen_->has_valid_frame());
ASSERT(cgen()->has_valid_frame());
// Live non-frame registers are not allowed at unconditional jumps
// because we have no way of invalidating the corresponding results
// which are still live in the C++ code.
ASSERT(cgen_->HasValidEntryRegisters());
ASSERT(cgen()->HasValidEntryRegisters());
if (is_bound()) {
// Backward jump. There is an expected frame to merge to.
ASSERT(direction_ == BIDIRECTIONAL);
cgen_->frame()->MergeTo(entry_frame_);
cgen_->DeleteFrame();
cgen()->frame()->MergeTo(entry_frame_);
cgen()->DeleteFrame();
__ jmp(&entry_label_);
} else {
// Preconfigured entry frame is not used on ARM.
......@@ -57,17 +57,16 @@ void JumpTarget::DoJump() {
// Forward jump. The current frame is added to the end of the list
// of frames reaching the target block and a jump to the merge code
// is emitted.
AddReachingFrame(cgen_->frame());
AddReachingFrame(cgen()->frame());
RegisterFile empty;
cgen_->SetFrame(NULL, &empty);
cgen()->SetFrame(NULL, &empty);
__ jmp(&merge_labels_.last());
}
}
void JumpTarget::DoBranch(Condition cc, Hint ignored) {
ASSERT(cgen_ != NULL);
ASSERT(cgen_->has_valid_frame());
ASSERT(cgen()->has_valid_frame());
if (is_bound()) {
ASSERT(direction_ == BIDIRECTIONAL);
......@@ -77,29 +76,29 @@ void JumpTarget::DoBranch(Condition cc, Hint ignored) {
// Swap the current frame for a copy (we do the swapping to get
// the off-frame registers off the fall through) to use for the
// branch.
VirtualFrame* fall_through_frame = cgen_->frame();
VirtualFrame* fall_through_frame = cgen()->frame();
VirtualFrame* branch_frame = new VirtualFrame(fall_through_frame);
RegisterFile non_frame_registers = RegisterAllocator::Reserved();
cgen_->SetFrame(branch_frame, &non_frame_registers);
cgen()->SetFrame(branch_frame, &non_frame_registers);
// Check if we can avoid merge code.
cgen_->frame()->PrepareMergeTo(entry_frame_);
if (cgen_->frame()->Equals(entry_frame_)) {
cgen()->frame()->PrepareMergeTo(entry_frame_);
if (cgen()->frame()->Equals(entry_frame_)) {
// Branch right in to the block.
cgen_->DeleteFrame();
cgen()->DeleteFrame();
__ b(cc, &entry_label_);
cgen_->SetFrame(fall_through_frame, &non_frame_registers);
cgen()->SetFrame(fall_through_frame, &non_frame_registers);
return;
}
// Check if we can reuse existing merge code.
for (int i = 0; i < reaching_frames_.length(); i++) {
if (reaching_frames_[i] != NULL &&
cgen_->frame()->Equals(reaching_frames_[i])) {
cgen()->frame()->Equals(reaching_frames_[i])) {
// Branch to the merge code.
cgen_->DeleteFrame();
cgen()->DeleteFrame();
__ b(cc, &merge_labels_[i]);
cgen_->SetFrame(fall_through_frame, &non_frame_registers);
cgen()->SetFrame(fall_through_frame, &non_frame_registers);
return;
}
}
......@@ -108,10 +107,10 @@ void JumpTarget::DoBranch(Condition cc, Hint ignored) {
// around the merge code on the fall through path.
Label original_fall_through;
__ b(NegateCondition(cc), &original_fall_through);
cgen_->frame()->MergeTo(entry_frame_);
cgen_->DeleteFrame();
cgen()->frame()->MergeTo(entry_frame_);
cgen()->DeleteFrame();
__ b(&entry_label_);
cgen_->SetFrame(fall_through_frame, &non_frame_registers);
cgen()->SetFrame(fall_through_frame, &non_frame_registers);
__ bind(&original_fall_through);
} else {
......@@ -120,7 +119,7 @@ void JumpTarget::DoBranch(Condition cc, Hint ignored) {
// Forward branch. A copy of the current frame is added to the end
// of the list of frames reaching the target block and a branch to
// the merge code is emitted.
AddReachingFrame(new VirtualFrame(cgen_->frame()));
AddReachingFrame(new VirtualFrame(cgen()->frame()));
__ b(cc, &merge_labels_.last());
}
}
......@@ -133,14 +132,13 @@ void JumpTarget::Call() {
// at the label (which should be the only one) is the spilled current
// frame plus an in-memory return address. The "fall-through" frame
// at the return site is the spilled current frame.
ASSERT(cgen_ != NULL);
ASSERT(cgen_->has_valid_frame());
ASSERT(cgen()->has_valid_frame());
// There are no non-frame references across the call.
ASSERT(cgen_->HasValidEntryRegisters());
ASSERT(cgen()->HasValidEntryRegisters());
ASSERT(!is_linked());
cgen_->frame()->SpillAll();
VirtualFrame* target_frame = new VirtualFrame(cgen_->frame());
cgen()->frame()->SpillAll();
VirtualFrame* target_frame = new VirtualFrame(cgen()->frame());
target_frame->Adjust(1);
// We do not expect a call with a preconfigured entry frame.
ASSERT(entry_frame_ == NULL);
......@@ -150,20 +148,19 @@ void JumpTarget::Call() {
void JumpTarget::DoBind(int mergable_elements) {
ASSERT(cgen_ != NULL);
ASSERT(!is_bound());
// Live non-frame registers are not allowed at the start of a basic
// block.
ASSERT(!cgen_->has_valid_frame() || cgen_->HasValidEntryRegisters());
ASSERT(!cgen()->has_valid_frame() || cgen()->HasValidEntryRegisters());
if (direction_ == FORWARD_ONLY) {
// A simple case: no forward jumps and no possible backward jumps.
if (!is_linked()) {
// The stack pointer can be floating above the top of the
// virtual frame before the bind. Afterward, it should not.
ASSERT(cgen_->has_valid_frame());
VirtualFrame* frame = cgen_->frame();
ASSERT(cgen()->has_valid_frame());
VirtualFrame* frame = cgen()->frame();
int difference =
frame->stack_pointer_ - (frame->elements_.length() - 1);
if (difference > 0) {
......@@ -176,12 +173,12 @@ void JumpTarget::DoBind(int mergable_elements) {
// Another simple case: no fall through, a single forward jump,
// and no possible backward jumps.
if (!cgen_->has_valid_frame() && reaching_frames_.length() == 1) {
if (!cgen()->has_valid_frame() && reaching_frames_.length() == 1) {
// Pick up the only reaching frame, take ownership of it, and
// use it for the block about to be emitted.
VirtualFrame* frame = reaching_frames_[0];
RegisterFile reserved = RegisterAllocator::Reserved();
cgen_->SetFrame(frame, &reserved);
cgen()->SetFrame(frame, &reserved);
reaching_frames_[0] = NULL;
__ bind(&merge_labels_[0]);
......@@ -201,11 +198,11 @@ void JumpTarget::DoBind(int mergable_elements) {
// If there is a current frame, record it as the fall-through. It
// is owned by the reaching frames for now.
bool had_fall_through = false;
if (cgen_->has_valid_frame()) {
if (cgen()->has_valid_frame()) {
had_fall_through = true;
AddReachingFrame(cgen_->frame()); // Return value ignored.
AddReachingFrame(cgen()->frame()); // Return value ignored.
RegisterFile empty;
cgen_->SetFrame(NULL, &empty);
cgen()->SetFrame(NULL, &empty);
}
// Compute the frame to use for entry to the block.
......@@ -242,17 +239,17 @@ void JumpTarget::DoBind(int mergable_elements) {
// binding site or as the fall through from a previous merge
// code block. Jump around the code we are about to
// generate.
if (cgen_->has_valid_frame()) {
cgen_->DeleteFrame();
if (cgen()->has_valid_frame()) {
cgen()->DeleteFrame();
__ b(&entry_label_);
}
// Pick up the frame for this block. Assume ownership if
// there cannot be backward jumps.
RegisterFile reserved = RegisterAllocator::Reserved();
if (direction_ == BIDIRECTIONAL) {
cgen_->SetFrame(new VirtualFrame(frame), &reserved);
cgen()->SetFrame(new VirtualFrame(frame), &reserved);
} else {
cgen_->SetFrame(frame, &reserved);
cgen()->SetFrame(frame, &reserved);
reaching_frames_[i] = NULL;
}
__ bind(&merge_labels_[i]);
......@@ -261,7 +258,7 @@ void JumpTarget::DoBind(int mergable_elements) {
// looking for any that can share merge code with this one.
for (int j = 0; j < i; j++) {
VirtualFrame* other = reaching_frames_[j];
if (other != NULL && other->Equals(cgen_->frame())) {
if (other != NULL && other->Equals(cgen()->frame())) {
// Set the reaching frame element to null to avoid
// processing it later, and then bind its entry label.
reaching_frames_[j] = NULL;
......@@ -270,13 +267,13 @@ void JumpTarget::DoBind(int mergable_elements) {
}
// Emit the merge code.
cgen_->frame()->MergeTo(entry_frame_);
cgen()->frame()->MergeTo(entry_frame_);
} else if (i == reaching_frames_.length() - 1 && had_fall_through) {
// If this is the fall through, and it didn't need merge
// code, we need to pick up the frame so we can jump around
// subsequent merge blocks if necessary.
RegisterFile reserved = RegisterAllocator::Reserved();
cgen_->SetFrame(frame, &reserved);
cgen()->SetFrame(frame, &reserved);
reaching_frames_[i] = NULL;
}
}
......@@ -285,9 +282,9 @@ void JumpTarget::DoBind(int mergable_elements) {
// The code generator may not have a current frame if there was no
// fall through and none of the reaching frames needed merging.
// In that case, clone the entry frame as the current frame.
if (!cgen_->has_valid_frame()) {
if (!cgen()->has_valid_frame()) {
RegisterFile reserved_registers = RegisterAllocator::Reserved();
cgen_->SetFrame(new VirtualFrame(entry_frame_), &reserved_registers);
cgen()->SetFrame(new VirtualFrame(entry_frame_), &reserved_registers);
}
// There may be unprocessed reaching frames that did not need
......@@ -313,9 +310,9 @@ void JumpTarget::DoBind(int mergable_elements) {
// Use a copy of the reaching frame so the original can be saved
// for possible reuse as a backward merge block.
RegisterFile reserved = RegisterAllocator::Reserved();
cgen_->SetFrame(new VirtualFrame(reaching_frames_[0]), &reserved);
cgen()->SetFrame(new VirtualFrame(reaching_frames_[0]), &reserved);
__ bind(&merge_labels_[0]);
cgen_->frame()->MergeTo(entry_frame_);
cgen()->frame()->MergeTo(entry_frame_);
}
__ bind(&entry_label_);
......
......@@ -47,8 +47,7 @@ CodeGenerator* CodeGeneratorScope::top_ = NULL;
DeferredCode::DeferredCode(CodeGenerator* generator)
: generator_(generator),
masm_(generator->masm()),
enter_(generator),
exit_(generator, JumpTarget::BIDIRECTIONAL),
exit_(JumpTarget::BIDIRECTIONAL),
statement_position_(masm_->current_statement_position()),
position_(masm_->current_position()) {
generator->AddDeferred(this);
......
......@@ -141,7 +141,7 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
frame_->AllocateStackSlots(scope_->num_stack_slots());
// Initialize the function return target after the locals are set
// up, because it needs the expected frame height from the frame.
function_return_.Initialize(this, JumpTarget::BIDIRECTIONAL);
function_return_.set_direction(JumpTarget::BIDIRECTIONAL);
function_return_is_shadowed_ = false;
// Allocate the arguments object and copy the parameters into it.
......@@ -468,14 +468,14 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
int original_height = frame_->height();
#endif
ASSERT(!in_spilled_code());
JumpTarget true_target(this);
JumpTarget false_target(this);
JumpTarget true_target;
JumpTarget false_target;
ControlDestination dest(&true_target, &false_target, true);
LoadCondition(x, typeof_state, &dest, false);
if (dest.false_was_fall_through()) {
// The false target was just bound.
JumpTarget loaded(this);
JumpTarget loaded;
frame_->Push(Factory::false_value());
// There may be dangling jumps to the true target.
if (true_target.is_linked()) {
......@@ -488,7 +488,7 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
} else if (dest.is_used()) {
// There is true, and possibly false, control flow (with true as
// the fall through).
JumpTarget loaded(this);
JumpTarget loaded;
frame_->Push(Factory::true_value());
if (false_target.is_linked()) {
loaded.Jump();
......@@ -504,7 +504,7 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
// short-circuited boolean operators).
ASSERT(has_valid_frame());
if (true_target.is_linked() || false_target.is_linked()) {
JumpTarget loaded(this);
JumpTarget loaded;
loaded.Jump(); // Don't lose the current TOS.
if (true_target.is_linked()) {
true_target.Bind();
......@@ -1541,7 +1541,7 @@ void CodeGenerator::Comparison(Condition cc,
// where both sides are Smis.
left_side.ToRegister();
ASSERT(left_side.is_valid());
JumpTarget is_smi(this);
JumpTarget is_smi;
__ test(left_side.reg(), Immediate(kSmiTagMask));
is_smi.Branch(zero, &left_side, &right_side, taken);
......@@ -1612,7 +1612,7 @@ void CodeGenerator::Comparison(Condition cc,
(right_side.is_constant() && !right_side.handle()->IsSmi());
left_side.ToRegister();
right_side.ToRegister();
JumpTarget is_smi(this);
JumpTarget is_smi;
if (!known_non_smi) {
// Check for the smi case.
Result temp = allocator_->Allocate();
......@@ -1757,7 +1757,7 @@ void CodeGenerator::VisitBlock(Block* node) {
ASSERT(!in_spilled_code());
Comment cmnt(masm_, "[ Block");
CodeForStatementPosition(node);
node->break_target()->Initialize(this);
node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
VisitStatements(node->statements());
if (node->break_target()->is_linked()) {
node->break_target()->Bind();
......@@ -1871,10 +1871,10 @@ void CodeGenerator::VisitIfStatement(IfStatement* node) {
bool has_else_stm = node->HasElseStatement();
CodeForStatementPosition(node);
JumpTarget exit(this);
JumpTarget exit;
if (has_then_stm && has_else_stm) {
JumpTarget then(this);
JumpTarget else_(this);
JumpTarget then;
JumpTarget else_;
ControlDestination dest(&then, &else_, true);
LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true);
......@@ -1901,7 +1901,7 @@ void CodeGenerator::VisitIfStatement(IfStatement* node) {
} else if (has_then_stm) {
ASSERT(!has_else_stm);
JumpTarget then(this);
JumpTarget then;
ControlDestination dest(&then, &exit, true);
LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true);
......@@ -1921,7 +1921,7 @@ void CodeGenerator::VisitIfStatement(IfStatement* node) {
} else if (has_else_stm) {
ASSERT(!has_then_stm);
JumpTarget else_(this);
JumpTarget else_;
ControlDestination dest(&exit, &else_, false);
LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true);
......@@ -2088,8 +2088,8 @@ void CodeGenerator::GenerateFastCaseSwitchJumpTable(
// placeholders, and fill in the addresses after the labels have been
// bound.
JumpTarget setup_default(this);
JumpTarget is_smi(this);
JumpTarget setup_default;
JumpTarget is_smi;
// A non-null default label pointer indicates a default case among
// the case labels. Otherwise we use the break target as a
......@@ -2134,7 +2134,7 @@ void CodeGenerator::GenerateFastCaseSwitchJumpTable(
// frame of the correct height can be merged to). Keep a copy to
// restore at the start of every label. Create a jump target and
// bind it to set its entry frame properly.
JumpTarget entry_target(this, JumpTarget::BIDIRECTIONAL);
JumpTarget entry_target(JumpTarget::BIDIRECTIONAL);
entry_target.Bind(&smi_value);
VirtualFrame* start_frame = new VirtualFrame(frame_);
......@@ -2191,7 +2191,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
ASSERT(!in_spilled_code());
Comment cmnt(masm_, "[ SwitchStatement");
CodeForStatementPosition(node);
node->break_target()->Initialize(this);
node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
// Compile the switch value.
Load(node->tag());
......@@ -2204,7 +2204,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
int length = cases->length();
CaseClause* default_clause = NULL;
JumpTarget next_test(this);
JumpTarget next_test;
// Compile the case label expressions and comparisons. Exit early
// if a comparison is unconditionally true. The target next_test is
// bound before the loop in order to indicate control flow to the
......@@ -2212,7 +2212,6 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
next_test.Bind();
for (int i = 0; i < length && !next_test.is_unused(); i++) {
CaseClause* clause = cases->at(i);
clause->body_target()->Initialize(this);
// The default is not a test, but remember it for later.
if (clause->is_default()) {
default_clause = clause;
......@@ -2283,7 +2282,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
if (clause->is_default()) {
clause->body_target()->Bind();
} else {
JumpTarget body(this);
JumpTarget body;
body.Jump();
clause->body_target()->Bind();
frame_->Drop();
......@@ -2321,7 +2320,7 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
ASSERT(!in_spilled_code());
Comment cmnt(masm_, "[ LoopStatement");
CodeForStatementPosition(node);
node->break_target()->Initialize(this);
node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
// Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a
// known result for the test expression, with no side effects.
......@@ -2342,21 +2341,21 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
switch (node->type()) {
case LoopStatement::DO_LOOP: {
JumpTarget body(this, JumpTarget::BIDIRECTIONAL);
JumpTarget body(JumpTarget::BIDIRECTIONAL);
IncrementLoopNesting();
// Label the top of the loop for the backward jump if necessary.
if (info == ALWAYS_TRUE) {
// Use the continue target.
node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
node->continue_target()->Bind();
} else if (info == ALWAYS_FALSE) {
// No need to label it.
node->continue_target()->Initialize(this);
node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
} else {
// Continue is the test, so use the backward body target.
ASSERT(info == DONT_KNOW);
node->continue_target()->Initialize(this);
node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
body.Bind();
}
......@@ -2415,27 +2414,25 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
JumpTarget body;
if (test_at_bottom) {
body.Initialize(this, JumpTarget::BIDIRECTIONAL);
} else {
body.Initialize(this);
body.set_direction(JumpTarget::BIDIRECTIONAL);
}
// Based on the condition analysis, compile the test as necessary.
if (info == ALWAYS_TRUE) {
// We will not compile the test expression. Label the top of
// the loop with the continue target.
node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
node->continue_target()->Bind();
} else {
ASSERT(info == DONT_KNOW); // ALWAYS_FALSE cannot reach here.
if (test_at_bottom) {
// 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);
node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
} 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()->set_direction(JumpTarget::BIDIRECTIONAL);
node->continue_target()->Bind();
}
// Compile the test with the body as the true target and
......@@ -2518,15 +2515,13 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
// Target for backward edge if no test at the bottom, otherwise
// unused.
JumpTarget loop(this, JumpTarget::BIDIRECTIONAL);
JumpTarget loop(JumpTarget::BIDIRECTIONAL);
// Target for backward edge if there is a test at the bottom,
// otherwise used as target for test at the top.
JumpTarget body;
if (test_at_bottom) {
body.Initialize(this, JumpTarget::BIDIRECTIONAL);
} else {
body.Initialize(this);
body.set_direction(JumpTarget::BIDIRECTIONAL);
}
// Based on the condition analysis, compile the test as necessary.
......@@ -2535,11 +2530,11 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
// the loop.
if (node->next() == NULL) {
// Use the continue target if there is no update expression.
node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
node->continue_target()->Bind();
} else {
// Otherwise use the backward loop target.
node->continue_target()->Initialize(this);
node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
loop.Bind();
}
} else {
......@@ -2547,16 +2542,16 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
if (test_at_bottom) {
// Continue is either the update expression or the test at
// the bottom, no need to label the test at the top.
node->continue_target()->Initialize(this);
node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
} else if (node->next() == NULL) {
// We are not recompiling the test at the bottom and there
// is no update expression.
node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
node->continue_target()->Bind();
} else {
// We are not recompiling the test at the bottom and there
// is an update expression.
node->continue_target()->Initialize(this);
node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
loop.Bind();
}
......@@ -2660,12 +2655,12 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) {
Comment cmnt(masm_, "[ ForInStatement");
CodeForStatementPosition(node);
JumpTarget primitive(this);
JumpTarget jsobject(this);
JumpTarget fixed_array(this);
JumpTarget entry(this, JumpTarget::BIDIRECTIONAL);
JumpTarget end_del_check(this);
JumpTarget exit(this);
JumpTarget primitive;
JumpTarget jsobject;
JumpTarget fixed_array;
JumpTarget entry(JumpTarget::BIDIRECTIONAL);
JumpTarget end_del_check;
JumpTarget exit;
// Get the object to enumerate over (converted to JSObject).
LoadAndSpill(node->enumerable());
......@@ -2750,8 +2745,8 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) {
entry.Bind();
// Grab the current frame's height for the break and continue
// targets only after all the state is pushed on the frame.
node->break_target()->Initialize(this);
node->continue_target()->Initialize(this);
node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
__ mov(eax, frame_->ElementAt(0)); // load the current count
__ cmp(eax, frame_->ElementAt(1)); // compare to the array length
......@@ -2850,8 +2845,8 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) {
Comment cmnt(masm_, "[ TryCatch");
CodeForStatementPosition(node);
JumpTarget try_block(this);
JumpTarget exit(this);
JumpTarget try_block;
JumpTarget exit;
try_block.Call();
// --- Catch block ---
......@@ -2994,8 +2989,8 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
// break/continue from within the try block.
enum { FALLING, THROWING, JUMPING };
JumpTarget try_block(this);
JumpTarget finally_block(this);
JumpTarget try_block;
JumpTarget finally_block;
try_block.Call();
......@@ -3147,7 +3142,7 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
} else {
// Branch around the preparation for return which may emit
// code.
JumpTarget skip(this);
JumpTarget skip;
skip.Branch(not_equal);
frame_->PrepareForReturn();
original->Jump(&return_value);
......@@ -3161,7 +3156,7 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
if (has_valid_frame()) {
// Check if we need to rethrow the exception.
JumpTarget exit(this);
JumpTarget exit;
__ cmp(Operand(ecx), Immediate(Smi::FromInt(THROWING)));
exit.Branch(not_equal);
......@@ -3221,9 +3216,9 @@ void CodeGenerator::VisitFunctionBoilerplateLiteral(
void CodeGenerator::VisitConditional(Conditional* node) {
Comment cmnt(masm_, "[ Conditional");
JumpTarget then(this);
JumpTarget else_(this);
JumpTarget exit(this);
JumpTarget then;
JumpTarget else_;
JumpTarget exit;
ControlDestination dest(&then, &else_, true);
LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true);
......@@ -3255,8 +3250,8 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
if (slot->type() == Slot::LOOKUP) {
ASSERT(slot->var()->is_dynamic());
JumpTarget slow(this);
JumpTarget done(this);
JumpTarget slow;
JumpTarget done;
Result value;
// Generate fast-case code for variables that might be shadowed by
......@@ -3322,7 +3317,7 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
// potentially unsafe direct-frame access of SlotOperand.
VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ Load const");
JumpTarget exit(this);
JumpTarget exit;
__ mov(ecx, SlotOperand(slot, ecx));
__ cmp(ecx, Factory::the_hole_value());
exit.Branch(not_equal);
......@@ -3460,7 +3455,7 @@ void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) {
} else {
ASSERT(!slot->var()->is_dynamic());
JumpTarget exit(this);
JumpTarget exit;
if (init_state == CONST_INIT) {
ASSERT(slot->var()->mode() == Variable::CONST);
// Only the first const initialization must be executed (the slot
......@@ -4285,13 +4280,13 @@ void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
ASSERT(args->length() == 2);
JumpTarget slow_case(this);
JumpTarget end(this);
JumpTarget not_a_flat_string(this);
JumpTarget a_cons_string(this);
JumpTarget try_again_with_new_string(this, JumpTarget::BIDIRECTIONAL);
JumpTarget ascii_string(this);
JumpTarget got_char_code(this);
JumpTarget slow_case;
JumpTarget end;
JumpTarget not_a_flat_string;
JumpTarget a_cons_string;
JumpTarget try_again_with_new_string(JumpTarget::BIDIRECTIONAL);
JumpTarget ascii_string;
JumpTarget got_char_code;
Load(args->at(0));
Load(args->at(1));
......@@ -4449,7 +4444,7 @@ void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) {
void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
JumpTarget leave(this);
JumpTarget leave;
Load(args->at(0)); // Load the object.
frame_->Dup();
Result object = frame_->Pop();
......@@ -4473,7 +4468,7 @@ void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) {
ASSERT(args->length() == 2);
JumpTarget leave(this);
JumpTarget leave;
Load(args->at(0)); // Load the object.
Load(args->at(1)); // Load the value.
Result value = frame_->Pop();
......@@ -4702,8 +4697,8 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
case Token::BIT_NOT: {
// Smi check.
JumpTarget smi_label(this);
JumpTarget continue_label(this);
JumpTarget smi_label;
JumpTarget continue_label;
Result operand = frame_->Pop();
operand.ToRegister();
__ test(operand.reg(), Immediate(kSmiTagMask));
......@@ -4726,7 +4721,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
case Token::ADD: {
// Smi check.
JumpTarget continue_label(this);
JumpTarget continue_label;
Result operand = frame_->Pop();
operand.ToRegister();
__ test(operand.reg(), Immediate(kSmiTagMask));
......@@ -4922,7 +4917,7 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
// is necessary because we assume that if we get control flow on the
// last path out of an expression we got it on all paths.
if (op == Token::AND) {
JumpTarget is_true(this);
JumpTarget is_true;
ControlDestination dest(&is_true, destination()->false_target(), true);
LoadCondition(node->left(), NOT_INSIDE_TYPEOF, &dest, false);
......@@ -4960,8 +4955,8 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
// We have a materialized value on the frame, so we exit with
// one on all paths. There are possibly also jumps to is_true
// from nested subexpressions.
JumpTarget pop_and_continue(this);
JumpTarget exit(this);
JumpTarget pop_and_continue;
JumpTarget exit;
// Avoid popping the result if it converts to 'false' using the
// standard ToBoolean() conversion as described in ECMA-262,
......@@ -4985,7 +4980,7 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
}
} else if (op == Token::OR) {
JumpTarget is_false(this);
JumpTarget is_false;
ControlDestination dest(destination()->true_target(), &is_false, false);
LoadCondition(node->left(), NOT_INSIDE_TYPEOF, &dest, false);
......@@ -5022,8 +5017,8 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
// We have a materialized value on the frame, so we exit with
// one on all paths. There are possibly also jumps to is_false
// from nested subexpressions.
JumpTarget pop_and_continue(this);
JumpTarget exit(this);
JumpTarget pop_and_continue;
JumpTarget exit;
// Avoid popping the result if it converts to 'true' using the
// standard ToBoolean() conversion as described in ECMA-262,
......@@ -6010,7 +6005,7 @@ Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left,
// the left and right arguments, and jump to slow case.
// The low bit of the left argument may be lost, but only
// in a case where it is dropped anyway.
JumpTarget result_ok(generator());
JumpTarget result_ok;
__ test(left->reg(), Immediate(0xc0000000));
result_ok.Branch(zero, left, taken);
__ shl(left->reg());
......@@ -6024,7 +6019,7 @@ Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left,
case Token::SHL: {
__ shl(left->reg());
// Check that the *signed* result fits in a smi.
JumpTarget result_ok(generator());
JumpTarget result_ok;
__ cmp(left->reg(), 0xc0000000);
result_ok.Branch(positive, left, taken);
......
......@@ -28,6 +28,7 @@
#include "v8.h"
#include "codegen-inl.h"
#include "jump-target-inl.h"
#include "register-allocator-inl.h"
namespace v8 { namespace internal {
......@@ -35,42 +36,41 @@ namespace v8 { namespace internal {
// -------------------------------------------------------------------------
// JumpTarget implementation.
#define __ ACCESS_MASM(masm_)
#define __ ACCESS_MASM(cgen()->masm())
void JumpTarget::DoJump() {
ASSERT(cgen_ != NULL);
ASSERT(cgen_->has_valid_frame());
ASSERT(cgen()->has_valid_frame());
// Live non-frame registers are not allowed at unconditional jumps
// because we have no way of invalidating the corresponding results
// which are still live in the C++ code.
ASSERT(cgen_->HasValidEntryRegisters());
ASSERT(cgen()->HasValidEntryRegisters());
if (is_bound()) {
// Backward jump. There is an expected frame to merge to.
ASSERT(direction_ == BIDIRECTIONAL);
cgen_->frame()->MergeTo(entry_frame_);
cgen_->DeleteFrame();
cgen()->frame()->MergeTo(entry_frame_);
cgen()->DeleteFrame();
__ jmp(&entry_label_);
} else if (entry_frame_ != NULL) {
// Forward jump with a preconfigured entry frame. Assert the
// current frame matches the expected one and jump to the block.
ASSERT(cgen_->frame()->Equals(entry_frame_));
cgen_->DeleteFrame();
ASSERT(cgen()->frame()->Equals(entry_frame_));
cgen()->DeleteFrame();
__ jmp(&entry_label_);
} else {
// Forward jump. Remember the current frame and emit a jump to
// its merge code.
AddReachingFrame(cgen_->frame());
AddReachingFrame(cgen()->frame());
RegisterFile empty;
cgen_->SetFrame(NULL, &empty);
cgen()->SetFrame(NULL, &empty);
__ jmp(&merge_labels_.last());
}
}
void JumpTarget::DoBranch(Condition cc, Hint hint) {
ASSERT(cgen_ != NULL);
ASSERT(cgen_->has_valid_frame());
ASSERT(cgen() != NULL);
ASSERT(cgen()->has_valid_frame());
if (is_bound()) {
ASSERT(direction_ == BIDIRECTIONAL);
......@@ -80,29 +80,29 @@ void JumpTarget::DoBranch(Condition cc, Hint hint) {
// Swap the current frame for a copy (we do the swapping to get
// the off-frame registers off the fall through) to use for the
// branch.
VirtualFrame* fall_through_frame = cgen_->frame();
VirtualFrame* fall_through_frame = cgen()->frame();
VirtualFrame* branch_frame = new VirtualFrame(fall_through_frame);
RegisterFile non_frame_registers = RegisterAllocator::Reserved();
cgen_->SetFrame(branch_frame, &non_frame_registers);
cgen()->SetFrame(branch_frame, &non_frame_registers);
// Check if we can avoid merge code.
cgen_->frame()->PrepareMergeTo(entry_frame_);
if (cgen_->frame()->Equals(entry_frame_)) {
cgen()->frame()->PrepareMergeTo(entry_frame_);
if (cgen()->frame()->Equals(entry_frame_)) {
// Branch right in to the block.
cgen_->DeleteFrame();
cgen()->DeleteFrame();
__ j(cc, &entry_label_, hint);
cgen_->SetFrame(fall_through_frame, &non_frame_registers);
cgen()->SetFrame(fall_through_frame, &non_frame_registers);
return;
}
// Check if we can reuse existing merge code.
for (int i = 0; i < reaching_frames_.length(); i++) {
if (reaching_frames_[i] != NULL &&
cgen_->frame()->Equals(reaching_frames_[i])) {
cgen()->frame()->Equals(reaching_frames_[i])) {
// Branch to the merge code.
cgen_->DeleteFrame();
cgen()->DeleteFrame();
__ j(cc, &merge_labels_[i], hint);
cgen_->SetFrame(fall_through_frame, &non_frame_registers);
cgen()->SetFrame(fall_through_frame, &non_frame_registers);
return;
}
}
......@@ -111,21 +111,21 @@ void JumpTarget::DoBranch(Condition cc, Hint hint) {
// around the merge code on the fall through path.
Label original_fall_through;
__ j(NegateCondition(cc), &original_fall_through, NegateHint(hint));
cgen_->frame()->MergeTo(entry_frame_);
cgen_->DeleteFrame();
cgen()->frame()->MergeTo(entry_frame_);
cgen()->DeleteFrame();
__ jmp(&entry_label_);
cgen_->SetFrame(fall_through_frame, &non_frame_registers);
cgen()->SetFrame(fall_through_frame, &non_frame_registers);
__ bind(&original_fall_through);
} else if (entry_frame_ != NULL) {
// Forward branch with a preconfigured entry frame. Assert the
// current frame matches the expected one and branch to the block.
ASSERT(cgen_->frame()->Equals(entry_frame_));
ASSERT(cgen()->frame()->Equals(entry_frame_));
// Explicitly use the macro assembler instead of __ as forward
// branches are expected to be a fixed size (no inserted
// coverage-checking instructions please). This is used in
// Reference::GetValue.
masm_->j(cc, &entry_label_, hint);
cgen()->masm()->j(cc, &entry_label_, hint);
} else {
// Forward branch. A copy of the current frame is remembered and
......@@ -133,8 +133,8 @@ void JumpTarget::DoBranch(Condition cc, Hint hint) {
// macro assembler instead of __ as forward branches are expected
// to be a fixed size (no inserted coverage-checking instructions
// please). This is used in Reference::GetValue.
AddReachingFrame(new VirtualFrame(cgen_->frame()));
masm_->j(cc, &merge_labels_.last(), hint);
AddReachingFrame(new VirtualFrame(cgen()->frame()));
cgen()->masm()->j(cc, &merge_labels_.last(), hint);
}
}
......@@ -146,14 +146,14 @@ void JumpTarget::Call() {
// at the label (which should be the only one) is the spilled current
// frame plus an in-memory return address. The "fall-through" frame
// at the return site is the spilled current frame.
ASSERT(cgen_ != NULL);
ASSERT(cgen_->has_valid_frame());
ASSERT(cgen() != NULL);
ASSERT(cgen()->has_valid_frame());
// There are no non-frame references across the call.
ASSERT(cgen_->HasValidEntryRegisters());
ASSERT(cgen()->HasValidEntryRegisters());
ASSERT(!is_linked());
cgen_->frame()->SpillAll();
VirtualFrame* target_frame = new VirtualFrame(cgen_->frame());
cgen()->frame()->SpillAll();
VirtualFrame* target_frame = new VirtualFrame(cgen()->frame());
target_frame->Adjust(1);
// We do not expect a call with a preconfigured entry frame.
ASSERT(entry_frame_ == NULL);
......@@ -163,28 +163,28 @@ void JumpTarget::Call() {
void JumpTarget::DoBind(int mergable_elements) {
ASSERT(cgen_ != NULL);
ASSERT(cgen() != NULL);
ASSERT(!is_bound());
// Live non-frame registers are not allowed at the start of a basic
// block.
ASSERT(!cgen_->has_valid_frame() || cgen_->HasValidEntryRegisters());
ASSERT(!cgen()->has_valid_frame() || cgen()->HasValidEntryRegisters());
// Fast case: the jump target was manually configured with an entry
// frame to use.
if (entry_frame_ != NULL) {
// Assert no reaching frames to deal with.
ASSERT(reaching_frames_.is_empty());
ASSERT(!cgen_->has_valid_frame());
ASSERT(!cgen()->has_valid_frame());
RegisterFile reserved = RegisterAllocator::Reserved();
if (direction_ == BIDIRECTIONAL) {
// Copy the entry frame so the original can be used for a
// possible backward jump.
cgen_->SetFrame(new VirtualFrame(entry_frame_), &reserved);
cgen()->SetFrame(new VirtualFrame(entry_frame_), &reserved);
} else {
// Take ownership of the entry frame.
cgen_->SetFrame(entry_frame_, &reserved);
cgen()->SetFrame(entry_frame_, &reserved);
entry_frame_ = NULL;
}
__ bind(&entry_label_);
......@@ -192,12 +192,12 @@ void JumpTarget::DoBind(int mergable_elements) {
}
if (!is_linked()) {
ASSERT(cgen_->has_valid_frame());
ASSERT(cgen()->has_valid_frame());
if (direction_ == FORWARD_ONLY) {
// Fast case: no forward jumps and no possible backward jumps.
// The stack pointer can be floating above the top of the
// virtual frame before the bind. Afterward, it should not.
VirtualFrame* frame = cgen_->frame();
VirtualFrame* frame = cgen()->frame();
int difference =
frame->stack_pointer_ - (frame->elements_.length() - 1);
if (difference > 0) {
......@@ -209,22 +209,22 @@ void JumpTarget::DoBind(int mergable_elements) {
// Fast case: no forward jumps, possible backward ones. Remove
// constants and copies above the watermark on the fall-through
// frame and use it as the entry frame.
cgen_->frame()->MakeMergable(mergable_elements);
entry_frame_ = new VirtualFrame(cgen_->frame());
cgen()->frame()->MakeMergable(mergable_elements);
entry_frame_ = new VirtualFrame(cgen()->frame());
}
__ bind(&entry_label_);
return;
}
if (direction_ == FORWARD_ONLY &&
!cgen_->has_valid_frame() &&
!cgen()->has_valid_frame() &&
reaching_frames_.length() == 1) {
// Fast case: no fall-through, a single forward jump, and no
// possible backward jumps. Pick up the only reaching frame, take
// ownership of it, and use it for the block about to be emitted.
VirtualFrame* frame = reaching_frames_[0];
RegisterFile reserved = RegisterAllocator::Reserved();
cgen_->SetFrame(frame, &reserved);
cgen()->SetFrame(frame, &reserved);
reaching_frames_[0] = NULL;
__ bind(&merge_labels_[0]);
......@@ -244,11 +244,11 @@ void JumpTarget::DoBind(int mergable_elements) {
// If there is a current frame, record it as the fall-through. It
// is owned by the reaching frames for now.
bool had_fall_through = false;
if (cgen_->has_valid_frame()) {
if (cgen()->has_valid_frame()) {
had_fall_through = true;
AddReachingFrame(cgen_->frame()); // Return value ignored.
AddReachingFrame(cgen()->frame()); // Return value ignored.
RegisterFile empty;
cgen_->SetFrame(NULL, &empty);
cgen()->SetFrame(NULL, &empty);
}
// Compute the frame to use for entry to the block.
......@@ -283,17 +283,17 @@ void JumpTarget::DoBind(int mergable_elements) {
// binding site or as the fall through from a previous merge
// code block. Jump around the code we are about to
// generate.
if (cgen_->has_valid_frame()) {
cgen_->DeleteFrame();
if (cgen()->has_valid_frame()) {
cgen()->DeleteFrame();
__ jmp(&entry_label_);
}
// Pick up the frame for this block. Assume ownership if
// there cannot be backward jumps.
RegisterFile reserved = RegisterAllocator::Reserved();
if (direction_ == BIDIRECTIONAL) {
cgen_->SetFrame(new VirtualFrame(frame), &reserved);
cgen()->SetFrame(new VirtualFrame(frame), &reserved);
} else {
cgen_->SetFrame(frame, &reserved);
cgen()->SetFrame(frame, &reserved);
reaching_frames_[i] = NULL;
}
__ bind(&merge_labels_[i]);
......@@ -302,7 +302,7 @@ void JumpTarget::DoBind(int mergable_elements) {
// looking for any that can share merge code with this one.
for (int j = 0; j < i; j++) {
VirtualFrame* other = reaching_frames_[j];
if (other != NULL && other->Equals(cgen_->frame())) {
if (other != NULL && other->Equals(cgen()->frame())) {
// Set the reaching frame element to null to avoid
// processing it later, and then bind its entry label.
reaching_frames_[j] = NULL;
......@@ -311,13 +311,13 @@ void JumpTarget::DoBind(int mergable_elements) {
}
// Emit the merge code.
cgen_->frame()->MergeTo(entry_frame_);
cgen()->frame()->MergeTo(entry_frame_);
} else if (i == reaching_frames_.length() - 1 && had_fall_through) {
// If this is the fall through frame, and it didn't need
// merge code, we need to pick up the frame so we can jump
// around subsequent merge blocks if necessary.
RegisterFile reserved = RegisterAllocator::Reserved();
cgen_->SetFrame(frame, &reserved);
cgen()->SetFrame(frame, &reserved);
reaching_frames_[i] = NULL;
}
}
......@@ -326,9 +326,9 @@ void JumpTarget::DoBind(int mergable_elements) {
// The code generator may not have a current frame if there was no
// fall through and none of the reaching frames needed merging.
// In that case, clone the entry frame as the current frame.
if (!cgen_->has_valid_frame()) {
if (!cgen()->has_valid_frame()) {
RegisterFile reserved_registers = RegisterAllocator::Reserved();
cgen_->SetFrame(new VirtualFrame(entry_frame_), &reserved_registers);
cgen()->SetFrame(new VirtualFrame(entry_frame_), &reserved_registers);
}
// There may be unprocessed reaching frames that did not need
......@@ -354,9 +354,9 @@ void JumpTarget::DoBind(int mergable_elements) {
// Use a copy of the reaching frame so the original can be saved
// for possible reuse as a backward merge block.
RegisterFile reserved = RegisterAllocator::Reserved();
cgen_->SetFrame(new VirtualFrame(reaching_frames_[0]), &reserved);
cgen()->SetFrame(new VirtualFrame(reaching_frames_[0]), &reserved);
__ bind(&merge_labels_[0]);
cgen_->frame()->MergeTo(entry_frame_);
cgen()->frame()->MergeTo(entry_frame_);
}
__ bind(&entry_label_);
......
......@@ -631,7 +631,7 @@ void MacroAssembler::NegativeZeroTest(CodeGenerator* cgen,
Register result,
Register op,
JumpTarget* then_target) {
JumpTarget ok(cgen);
JumpTarget ok;
test(result, Operand(result));
ok.Branch(not_zero, taken);
test(op, Operand(op));
......
......@@ -30,6 +30,10 @@
namespace v8 { namespace internal {
CodeGenerator* JumpTarget::cgen() {
return CodeGeneratorScope::Current();
}
void JumpTarget::InitializeEntryElement(int index, FrameElement* target) {
entry_frame_->elements_[index].clear_copied();
if (target->is_register()) {
......
......@@ -39,36 +39,6 @@ namespace v8 { namespace internal {
bool JumpTarget::compiling_deferred_code_ = false;
JumpTarget::JumpTarget(CodeGenerator* cgen, Directionality direction)
: cgen_(cgen),
direction_(direction),
reaching_frames_(0),
merge_labels_(0),
entry_frame_(NULL) {
ASSERT(cgen != NULL);
masm_ = cgen->masm();
}
JumpTarget::JumpTarget()
: cgen_(NULL),
masm_(NULL),
direction_(FORWARD_ONLY),
reaching_frames_(0),
merge_labels_(0),
entry_frame_(NULL) {
}
void JumpTarget::Initialize(CodeGenerator* cgen, Directionality direction) {
ASSERT(cgen != NULL);
ASSERT(cgen_ == NULL);
cgen_ = cgen;
masm_ = cgen->masm();
direction_ = direction;
}
void JumpTarget::Unuse() {
reaching_frames_.Clear();
merge_labels_.Clear();
......@@ -151,7 +121,7 @@ void JumpTarget::ComputeEntryFrame(int mergable_elements) {
// Build the new frame. A freshly allocated frame has memory elements
// for the parameters and some platform-dependent elements (e.g.,
// return address). Replace those first.
entry_frame_ = new VirtualFrame(cgen_);
entry_frame_ = new VirtualFrame(cgen());
int index = 0;
for (; index < entry_frame_->elements_.length(); index++) {
FrameElement* target = elements[index];
......@@ -266,31 +236,28 @@ void JumpTarget::Jump() {
void JumpTarget::Jump(Result* arg) {
ASSERT(cgen_ != NULL);
ASSERT(cgen_->has_valid_frame());
ASSERT(cgen()->has_valid_frame());
cgen_->frame()->Push(arg);
cgen()->frame()->Push(arg);
DoJump();
}
void JumpTarget::Jump(Result* arg0, Result* arg1) {
ASSERT(cgen_ != NULL);
ASSERT(cgen_->has_valid_frame());
ASSERT(cgen()->has_valid_frame());
cgen_->frame()->Push(arg0);
cgen_->frame()->Push(arg1);
cgen()->frame()->Push(arg0);
cgen()->frame()->Push(arg1);
DoJump();
}
void JumpTarget::Jump(Result* arg0, Result* arg1, Result* arg2) {
ASSERT(cgen_ != NULL);
ASSERT(cgen_->has_valid_frame());
ASSERT(cgen()->has_valid_frame());
cgen_->frame()->Push(arg0);
cgen_->frame()->Push(arg1);
cgen_->frame()->Push(arg2);
cgen()->frame()->Push(arg0);
cgen()->frame()->Push(arg1);
cgen()->frame()->Push(arg2);
DoJump();
}
......@@ -316,35 +283,33 @@ void JumpTarget::Branch(Condition cc, Hint hint) {
#endif
void JumpTarget::Branch(Condition cc, Result* arg, Hint hint) {
ASSERT(cgen_ != NULL);
ASSERT(cgen_->has_valid_frame());
ASSERT(cgen()->has_valid_frame());
// We want to check that non-frame registers at the call site stay in
// the same registers on the fall-through branch.
DECLARE_ARGCHECK_VARS(arg);
cgen_->frame()->Push(arg);
cgen()->frame()->Push(arg);
DoBranch(cc, hint);
*arg = cgen_->frame()->Pop();
*arg = cgen()->frame()->Pop();
ASSERT_ARGCHECK(arg);
}
void JumpTarget::Branch(Condition cc, Result* arg0, Result* arg1, Hint hint) {
ASSERT(cgen_ != NULL);
ASSERT(cgen_->frame() != NULL);
ASSERT(cgen()->frame() != NULL);
// We want to check that non-frame registers at the call site stay in
// the same registers on the fall-through branch.
DECLARE_ARGCHECK_VARS(arg0);
DECLARE_ARGCHECK_VARS(arg1);
cgen_->frame()->Push(arg0);
cgen_->frame()->Push(arg1);
cgen()->frame()->Push(arg0);
cgen()->frame()->Push(arg1);
DoBranch(cc, hint);
*arg1 = cgen_->frame()->Pop();
*arg0 = cgen_->frame()->Pop();
*arg1 = cgen()->frame()->Pop();
*arg0 = cgen()->frame()->Pop();
ASSERT_ARGCHECK(arg0);
ASSERT_ARGCHECK(arg1);
......@@ -356,8 +321,7 @@ void JumpTarget::Branch(Condition cc,
Result* arg1,
Result* arg2,
Hint hint) {
ASSERT(cgen_ != NULL);
ASSERT(cgen_->frame() != NULL);
ASSERT(cgen()->frame() != NULL);
// We want to check that non-frame registers at the call site stay in
// the same registers on the fall-through branch.
......@@ -365,13 +329,13 @@ void JumpTarget::Branch(Condition cc,
DECLARE_ARGCHECK_VARS(arg1);
DECLARE_ARGCHECK_VARS(arg2);
cgen_->frame()->Push(arg0);
cgen_->frame()->Push(arg1);
cgen_->frame()->Push(arg2);
cgen()->frame()->Push(arg0);
cgen()->frame()->Push(arg1);
cgen()->frame()->Push(arg2);
DoBranch(cc, hint);
*arg2 = cgen_->frame()->Pop();
*arg1 = cgen_->frame()->Pop();
*arg0 = cgen_->frame()->Pop();
*arg2 = cgen()->frame()->Pop();
*arg1 = cgen()->frame()->Pop();
*arg0 = cgen()->frame()->Pop();
ASSERT_ARGCHECK(arg0);
ASSERT_ARGCHECK(arg1);
......@@ -385,8 +349,7 @@ void JumpTarget::Branch(Condition cc,
Result* arg2,
Result* arg3,
Hint hint) {
ASSERT(cgen_ != NULL);
ASSERT(cgen_->frame() != NULL);
ASSERT(cgen()->frame() != NULL);
// We want to check that non-frame registers at the call site stay in
// the same registers on the fall-through branch.
......@@ -395,15 +358,15 @@ void JumpTarget::Branch(Condition cc,
DECLARE_ARGCHECK_VARS(arg2);
DECLARE_ARGCHECK_VARS(arg3);
cgen_->frame()->Push(arg0);
cgen_->frame()->Push(arg1);
cgen_->frame()->Push(arg2);
cgen_->frame()->Push(arg3);
cgen()->frame()->Push(arg0);
cgen()->frame()->Push(arg1);
cgen()->frame()->Push(arg2);
cgen()->frame()->Push(arg3);
DoBranch(cc, hint);
*arg3 = cgen_->frame()->Pop();
*arg2 = cgen_->frame()->Pop();
*arg1 = cgen_->frame()->Pop();
*arg0 = cgen_->frame()->Pop();
*arg3 = cgen()->frame()->Pop();
*arg2 = cgen()->frame()->Pop();
*arg1 = cgen()->frame()->Pop();
*arg0 = cgen()->frame()->Pop();
ASSERT_ARGCHECK(arg0);
ASSERT_ARGCHECK(arg1);
......@@ -413,15 +376,14 @@ void JumpTarget::Branch(Condition cc,
void BreakTarget::Branch(Condition cc, Result* arg, Hint hint) {
ASSERT(cgen_ != NULL);
ASSERT(cgen_->has_valid_frame());
ASSERT(cgen()->has_valid_frame());
int count = cgen_->frame()->height() - expected_height_;
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_);
JumpTarget fall_through;
// Branch to fall through will not negate, because it is a
// forward-only target.
fall_through.Branch(NegateCondition(cc), NegateHint(hint));
......@@ -429,9 +391,9 @@ void BreakTarget::Branch(Condition cc, Result* arg, Hint hint) {
fall_through.Bind();
} else {
DECLARE_ARGCHECK_VARS(arg);
cgen_->frame()->Push(arg);
cgen()->frame()->Push(arg);
DoBranch(cc, hint);
*arg = cgen_->frame()->Pop();
*arg = cgen()->frame()->Pop();
ASSERT_ARGCHECK(arg);
}
}
......@@ -446,26 +408,22 @@ void JumpTarget::Bind(int mergable_elements) {
void JumpTarget::Bind(Result* arg, int mergable_elements) {
ASSERT(cgen_ != NULL);
if (cgen_->has_valid_frame()) {
cgen_->frame()->Push(arg);
if (cgen()->has_valid_frame()) {
cgen()->frame()->Push(arg);
}
DoBind(mergable_elements);
*arg = cgen_->frame()->Pop();
*arg = cgen()->frame()->Pop();
}
void JumpTarget::Bind(Result* arg0, Result* arg1, int mergable_elements) {
ASSERT(cgen_ != NULL);
if (cgen_->has_valid_frame()) {
cgen_->frame()->Push(arg0);
cgen_->frame()->Push(arg1);
if (cgen()->has_valid_frame()) {
cgen()->frame()->Push(arg0);
cgen()->frame()->Push(arg1);
}
DoBind(mergable_elements);
*arg1 = cgen_->frame()->Pop();
*arg0 = cgen_->frame()->Pop();
*arg1 = cgen()->frame()->Pop();
*arg0 = cgen()->frame()->Pop();
}
......@@ -473,17 +431,15 @@ void JumpTarget::Bind(Result* arg0,
Result* arg1,
Result* arg2,
int mergable_elements) {
ASSERT(cgen_ != NULL);
if (cgen_->has_valid_frame()) {
cgen_->frame()->Push(arg0);
cgen_->frame()->Push(arg1);
cgen_->frame()->Push(arg2);
if (cgen()->has_valid_frame()) {
cgen()->frame()->Push(arg0);
cgen()->frame()->Push(arg1);
cgen()->frame()->Push(arg2);
}
DoBind(mergable_elements);
*arg2 = cgen_->frame()->Pop();
*arg1 = cgen_->frame()->Pop();
*arg0 = cgen_->frame()->Pop();
*arg2 = cgen()->frame()->Pop();
*arg1 = cgen()->frame()->Pop();
*arg0 = cgen()->frame()->Pop();
}
......@@ -492,19 +448,17 @@ void JumpTarget::Bind(Result* arg0,
Result* arg2,
Result* arg3,
int mergable_elements) {
ASSERT(cgen_ != NULL);
if (cgen_->has_valid_frame()) {
cgen_->frame()->Push(arg0);
cgen_->frame()->Push(arg1);
cgen_->frame()->Push(arg2);
cgen_->frame()->Push(arg3);
if (cgen()->has_valid_frame()) {
cgen()->frame()->Push(arg0);
cgen()->frame()->Push(arg1);
cgen()->frame()->Push(arg2);
cgen()->frame()->Push(arg3);
}
DoBind(mergable_elements);
*arg3 = cgen_->frame()->Pop();
*arg2 = cgen_->frame()->Pop();
*arg1 = cgen_->frame()->Pop();
*arg0 = cgen_->frame()->Pop();
*arg3 = cgen()->frame()->Pop();
*arg2 = cgen()->frame()->Pop();
*arg1 = cgen()->frame()->Pop();
*arg0 = cgen()->frame()->Pop();
}
......@@ -520,17 +474,15 @@ void JumpTarget::AddReachingFrame(VirtualFrame* frame) {
// -------------------------------------------------------------------------
// BreakTarget implementation.
void BreakTarget::Initialize(CodeGenerator* cgen, Directionality direction) {
JumpTarget::Initialize(cgen, direction);
ASSERT(cgen_->has_valid_frame());
expected_height_ = cgen_->frame()->height();
void BreakTarget::set_direction(Directionality direction) {
JumpTarget::set_direction(direction);
ASSERT(cgen()->has_valid_frame());
expected_height_ = cgen()->frame()->height();
}
void BreakTarget::CopyTo(BreakTarget* destination) {
ASSERT(destination != NULL);
destination->cgen_ = cgen_;
destination->masm_ = masm_;
destination->direction_ = direction_;
destination->reaching_frames_.Clear();
destination->merge_labels_.Clear();
......@@ -546,36 +498,33 @@ void BreakTarget::CopyTo(BreakTarget* destination) {
void BreakTarget::Jump() {
ASSERT(cgen_ != NULL);
ASSERT(cgen_->has_valid_frame());
ASSERT(cgen()->has_valid_frame());
// Drop leftover statement state from the frame before merging.
cgen_->frame()->ForgetElements(cgen_->frame()->height() - expected_height_);
cgen()->frame()->ForgetElements(cgen()->frame()->height() - expected_height_);
DoJump();
}
void BreakTarget::Jump(Result* arg) {
ASSERT(cgen_ != NULL);
ASSERT(cgen_->has_valid_frame());
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);
cgen()->frame()->ForgetElements(cgen()->frame()->height() - expected_height_);
cgen()->frame()->Push(arg);
DoJump();
}
void BreakTarget::Branch(Condition cc, Hint hint) {
ASSERT(cgen_ != NULL);
ASSERT(cgen_->has_valid_frame());
ASSERT(cgen()->has_valid_frame());
int count = cgen_->frame()->height() - expected_height_;
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_);
JumpTarget fall_through;
// Branch to fall through will not negate, because it is a
// forward-only target.
fall_through.Branch(NegateCondition(cc), NegateHint(hint));
......@@ -589,7 +538,6 @@ void BreakTarget::Branch(Condition cc, Hint hint) {
void BreakTarget::Bind(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++) {
......@@ -600,8 +548,9 @@ void BreakTarget::Bind(int mergable_elements) {
// 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_);
if (cgen()->has_valid_frame()) {
int count = cgen()->frame()->height() - expected_height_;
cgen()->frame()->ForgetElements(count);
}
DoBind(mergable_elements);
}
......@@ -609,7 +558,6 @@ void BreakTarget::Bind(int 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++) {
......@@ -620,12 +568,13 @@ void BreakTarget::Bind(Result* arg, int mergable_elements) {
// 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);
if (cgen()->has_valid_frame()) {
int count = cgen()->frame()->height() - expected_height_;
cgen()->frame()->ForgetElements(count);
cgen()->frame()->Push(arg);
}
DoBind(mergable_elements);
*arg = cgen_->frame()->Pop();
*arg = cgen()->frame()->Pop();
}
......@@ -644,25 +593,14 @@ ShadowTarget::ShadowTarget(BreakTarget* shadowed) {
// The original's state is reset.
shadowed->Unuse();
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;
ASSERT(cgen()->has_valid_frame());
shadowed->set_expected_height(cgen()->frame()->height());
}
void ShadowTarget::StopShadowing() {
ASSERT(is_shadowing_);
// This target does not have a valid code generator yet.
cgen_ = other_target_->code_generator();
ASSERT(cgen_ != NULL);
masm_ = cgen_->masm();
// The states of this target, which was shadowed, and the original
// target, which was shadowing, are swapped.
BreakTarget temp;
......
......@@ -56,31 +56,34 @@ class JumpTarget : public ZoneObject { // Shadows are dynamically allocated.
// Forward-only jump targets can only be reached by forward CFG edges.
enum Directionality { FORWARD_ONLY, BIDIRECTIONAL };
// Construct a jump target with a given code generator used to generate
// code and to provide access to a current frame.
explicit JumpTarget(CodeGenerator* cgen,
Directionality direction = FORWARD_ONLY);
// Construct a jump target used to generate code and to provide
// access to a current frame.
explicit JumpTarget(Directionality direction)
: direction_(direction),
reaching_frames_(0),
merge_labels_(0),
entry_frame_(NULL) {
}
// 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 break targets are embedded in
// AST nodes.
JumpTarget();
// Construct a jump target.
JumpTarget()
: direction_(FORWARD_ONLY),
reaching_frames_(0),
merge_labels_(0),
entry_frame_(NULL) {
}
virtual ~JumpTarget() {}
// 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.
virtual void Initialize(CodeGenerator* cgen,
Directionality direction = FORWARD_ONLY);
// Set the direction of the jump target.
virtual void set_direction(Directionality direction) {
direction_ = direction;
}
// Treat the jump target as a fresh one. The state is reset.
void Unuse();
// Accessors.
CodeGenerator* code_generator() const { return cgen_; }
inline CodeGenerator* cgen();
Label* entry_label() { return &entry_label_; }
......@@ -163,12 +166,6 @@ class JumpTarget : public ZoneObject { // Shadows are dynamically allocated.
}
protected:
// The code generator gives access to its current frame.
CodeGenerator* cgen_;
// Used to emit code.
MacroAssembler* masm_;
// Directionality flag set at initialization time.
Directionality direction_;
......@@ -224,20 +221,13 @@ class JumpTarget : public ZoneObject { // Shadows are dynamically allocated.
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.
// Construct a break target.
BreakTarget() {}
virtual ~BreakTarget() {}
// Supply a code generator, expected expression stack height, and
// directionality to an already constructed break 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.
virtual void Initialize(CodeGenerator* cgen,
Directionality direction = FORWARD_ONLY);
// Set the direction of the break target.
virtual void set_direction(Directionality direction);
// Copy the state of this break target to the destination. The
// lists of forward-reaching frames and merge-point labels are
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment