Author: [email protected]
Date: Thu Jan 15 01:29:05 2009
New Revision: 1075

Modified:
    branches/experimental/toiger/src/codegen-ia32.cc

Log:
Experimental: processor flags are not preserved across CFG edges
targeting labeled basic blocks.  Merge code may be generated at the
block exit which could potentially destroy a value in the flags
register.

This solution is to always materialize the flag result in a register.
The generated code is known to be bad but (more) correct and will have
to be fixed as a future change.
Review URL: http://codereview.chromium.org/18225

Modified: branches/experimental/toiger/src/codegen-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/codegen-ia32.cc    (original)
+++ branches/experimental/toiger/src/codegen-ia32.cc    Thu Jan 15 01:29:05  
2009
@@ -1269,25 +1269,46 @@
    }
    CompareStub stub(cc, strict);
    Result answer = frame_->CallStub(&stub, &right_side, &left_side, 0);
+  ASSERT(answer.is_register() && answer.reg().is_byte_register());
+  frame_->Spill(answer.reg());
    if (cc == equal) {
      __ test(answer.reg(), Operand(answer.reg()));
    } else {
      __ cmp(answer.reg(), 0);
    }
-  answer.Unuse();
+  __ setcc(cc, answer.reg());
+  __ and_(Operand(answer.reg()), Immediate(1));
    // The expected frame at JumpTarget "done" is bound to the current frame.
    // This current frame is spilled, due to the call to CallStub.
    // It would be better if the fast SMI case controlled the expected frame.
-  done.Jump();
+  done.Jump(&answer);

    is_smi.Bind(&left_side, &right_side);
+  left_side.ToRegister();
+  right_side.ToRegister();
+  // Find a byte register for the flag value.
+  if (!left_side.reg().is_byte_register() &&
+      !right_side.reg().is_byte_register()) {
+    // If we allocate a register here, it should be a byte register
+    // because there is only one non-reserved register on IA32 that
+    // does not have a byte part (namely edi) and it must be left_side
+    // (and right_side).
+    answer = allocator_->Allocate();
+    ASSERT(answer.is_register() && answer.reg().is_byte_register());
+  } else {
+    answer = left_side.reg().is_byte_register() ? left_side : right_side;
+    frame_->Spill(answer.reg());
+  }
    __ cmp(left_side.reg(), Operand(right_side.reg()));
    right_side.Unuse();
    left_side.Unuse();
-  // Fall through to |done|.
+  __ setcc(cc, answer.reg());
+  __ and_(Operand(answer.reg()), Immediate(1));

-  done.Bind();
-  cc_reg_ = cc;
+  done.Bind(&answer);
+  answer.ToRegister();
+  __ test(answer.reg(), Operand(answer.reg()));
+  cc_reg_ = not_zero;
  }


@@ -1324,11 +1345,12 @@
    ASSERT(value.is_valid());
    __ Set(value.reg(), Immediate(Smi::FromInt(int_value_)));
    Result result = cgen->frame()->CallStub(&stub, &argument, &value, 0);
-  ASSERT(result.is_register());
+  ASSERT(result.is_register() && result.reg().is_byte_register());
+  cgen->frame()->Spill(result.reg());
    __ cmp(result.reg(), 0);
-  result.Unuse();
-  // The actual result is returned in the flags.
-  exit()->Jump();
+  __ setcc(cc_, result.reg());
+  __ and_(Operand(result.reg()), Immediate(1));
+  exit()->Jump(&result);
  }


@@ -1348,11 +1370,28 @@
    comparee.ToRegister();
    __ test(comparee.reg(), Immediate(kSmiTagMask));
    deferred->enter()->Branch(not_zero, &comparee, not_taken);
+  // Find a byte register to hold the flag value.  If the comparee is
+  // a byte register we can use it, otherwise allocating will give us
+  // one since there is only one non-reserved IA32 register that does
+  // not have a byte part (namely edi).
+  Result flag(this);
+  if (comparee.reg().is_byte_register()) {
+    flag = comparee;
+    frame_->Spill(flag.reg());
+  } else {
+    flag = allocator_->Allocate();
+    ASSERT(flag.is_register() && flag.reg().is_byte_register());
+  }
    // Test smi equality and comparison by signed int comparison.
    __ cmp(Operand(comparee.reg()), Immediate(value));
    comparee.Unuse();
-  deferred->exit()->Bind();
-  cc_reg_ = cc;
+  __ setcc(cc, flag.reg());
+  __ and_(Operand(flag.reg()), Immediate(1));
+
+  deferred->exit()->Bind(&flag);
+  flag.ToRegister();
+  __ test(flag.reg(), Operand(flag.reg()));
+  cc_reg_ = not_zero;
  }


@@ -3590,7 +3629,7 @@
  void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
    ASSERT(args->length() == 1);
    LoadAndSpill(args->at(0));
-  JumpTarget answer(this);
+  Label 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 copy the object to ecx and do some destructive ops on it that
@@ -3599,13 +3638,13 @@
    __ mov(ecx, Operand(eax));
    __ and_(ecx, kSmiTagMask);
    __ xor_(ecx, kSmiTagMask);
-  answer.Branch(not_equal, not_taken);
+  __ j(not_equal, &answer, not_taken);
    // It is a heap object - get map.
    __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
    __ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset));
    // Check if the object is a JS array or not.
    __ cmp(eax, JS_ARRAY_TYPE);
-  answer.Bind();
+  __ bind(&answer);
    cc_reg_ = equal;
  }


--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to