Author: [email protected]
Date: Mon Dec 29 05:58:09 2008
New Revision: 1021

Modified:
    branches/experimental/toiger/src/assembler-ia32.cc
    branches/experimental/toiger/src/assembler-ia32.h
    branches/experimental/toiger/src/codegen-ia32.cc
    branches/experimental/toiger/src/disasm-ia32.cc
    branches/experimental/toiger/src/jump-target-ia32.cc
    branches/experimental/toiger/src/jump-target.h
    branches/experimental/toiger/src/virtual-frame-ia32.cc

Log:
Copy of changelist from issue 16450.  Converts compare operation
to use virtual frames, adds xchg instruction to assembler.
Review URL: http://codereview.chromium.org/16481

Modified: branches/experimental/toiger/src/assembler-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/assembler-ia32.cc  (original)
+++ branches/experimental/toiger/src/assembler-ia32.cc  Mon Dec 29 05:58:09  
2008
@@ -743,6 +743,18 @@
  }


+void Assembler::xchg(Register dst, Register src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  if (src.is(eax) || dst.is(eax)) {  // Single-byte encoding
+    EMIT(0x90 | (src.is(eax) ? dst.code() : src.code()));
+  } else {
+    EMIT(0x87);
+    EMIT(0xC0 | src.code() << 3 | dst.code());
+  }
+}
+
+
  void Assembler::adc(Register dst, int32_t imm32) {
    EnsureSpace ensure_space(this);
    last_pc_ = pc_;

Modified: branches/experimental/toiger/src/assembler-ia32.h
==============================================================================
--- branches/experimental/toiger/src/assembler-ia32.h   (original)
+++ branches/experimental/toiger/src/assembler-ia32.h   Mon Dec 29 05:58:09  
2008
@@ -499,6 +499,9 @@
    void cmov(Condition cc, Register dst, Handle<Object> handle);
    void cmov(Condition cc, Register dst, const Operand& src);

+  // Exchange two registers
+  void xchg(Register dst, Register src);
+
    // Arithmetics
    void adc(Register dst, int32_t imm32);
    void adc(Register dst, const Operand& src);

Modified: branches/experimental/toiger/src/codegen-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/codegen-ia32.cc    (original)
+++ branches/experimental/toiger/src/codegen-ia32.cc    Mon Dec 29 05:58:09  
2008
@@ -1185,38 +1185,64 @@
    // Strict only makes sense for equality comparisons.
    ASSERT(!strict || cc == equal);

+  Result left_side(this);
+  Result right_side(this);
    // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion  
order.
    if (cc == greater || cc == less_equal) {
      cc = ReverseCondition(cc);
-    frame_->EmitPop(edx);
-    frame_->EmitPop(eax);
+    left_side = frame_->Pop();
+    right_side = frame_->Pop();
    } else {
-    frame_->EmitPop(eax);
-    frame_->EmitPop(edx);
+    right_side = frame_->Pop();
+    left_side = frame_->Pop();
    }
-
+  left_side.ToRegister();
+  right_side.ToRegister();
+  ASSERT(left_side.is_valid());
+  ASSERT(right_side.is_valid());
    // Check for the smi case.
    JumpTarget is_smi(this);
    JumpTarget done(this);
-  __ mov(ecx, Operand(eax));
-  __ or_(ecx, Operand(edx));
-  __ test(ecx, Immediate(kSmiTagMask));
-  is_smi.Branch(zero, taken);
+  Result temp = allocator_->Allocate();
+  ASSERT(temp.is_valid());
+  __ mov(temp.reg(), left_side.reg());
+  __ or_(temp.reg(), Operand(right_side.reg()));
+  __ test(temp.reg(), Immediate(kSmiTagMask));
+  temp.Unuse();
+  is_smi.Branch(zero, &left_side, &right_side, taken);

    // When non-smi, call out to the compare stub.  "parameters" setup by
    // calling code in edx and eax and "result" is returned in the flags.
+  if (!left_side.reg().is(eax)) {
+    right_side.ToRegister(eax);
+    left_side.ToRegister(edx);
+  } else if (!right_side.reg().is(edx)) {
+    left_side.ToRegister(edx);
+    right_side.ToRegister(eax);
+  } else {
+    frame_->Spill(eax);  // Can be multiply referenced, even now.
+    frame_->Spill(edx);
+    __ xchg(eax, edx);
+    // If left_side and right_side become real (non-dummy) arguments
+    // to CallStub, they need to be swapped in this case.
+  }
    CompareStub stub(cc, strict);
-  frame_->CallStub(&stub, 0);
+  Result answer = frame_->CallStub(&stub, &right_side, &left_side, 0);
    if (cc == equal) {
-    __ test(eax, Operand(eax));
+    __ test(answer.reg(), Operand(answer.reg()));
    } else {
-    __ cmp(eax, 0);
+    __ cmp(answer.reg(), 0);
    }
+  answer.Unuse();
+  // 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();

-  // Test smi equality by pointer comparison.
-  is_smi.Bind();
-  __ cmp(edx, Operand(eax));
+  is_smi.Bind(&left_side, &right_side);
+  __ cmp(left_side.reg(), Operand(right_side.reg()));
+  right_side.Unuse();
+  left_side.Unuse();
    // Fall through to |done|.

    done.Bind();
@@ -4172,17 +4198,15 @@
        cc = greater_equal;
        break;
      case Token::IN: {
-      VirtualFrame::SpilledScope spilled_scope(this);
-      LoadAndSpill(left);
-      LoadAndSpill(right);
+      Load(left);
+      Load(right);
        frame_->InvokeBuiltin(Builtins::IN, CALL_FUNCTION, 2);
-      frame_->EmitPush(eax);  // push the result
+      frame_->Push(eax);  // push the result
        return;
      }
      case Token::INSTANCEOF: {
-      VirtualFrame::SpilledScope spilled_scope(this);
-      LoadAndSpill(left);
-      LoadAndSpill(right);
+      Load(left);
+      Load(right);
        InstanceofStub stub;
        frame_->CallStub(&stub, 2);
        __ test(eax, Operand(eax));
@@ -4206,9 +4230,8 @@
      return;
    }

-  VirtualFrame::SpilledScope spilled_scope(this);
-  LoadAndSpill(left);
-  LoadAndSpill(right);
+  Load(left);
+  Load(right);
    Comparison(cc, strict);
  }


Modified: branches/experimental/toiger/src/disasm-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/disasm-ia32.cc     (original)
+++ branches/experimental/toiger/src/disasm-ia32.cc     Mon Dec 29 05:58:09 2008
@@ -65,6 +65,7 @@
    {0x85, "test", REG_OPER_OP_ORDER},
    {0x31, "xor", OPER_REG_OP_ORDER},
    {0x33, "xor", REG_OPER_OP_ORDER},
+  {0x87, "xchg", REG_OPER_OP_ORDER},
    {0x8A, "mov_b", REG_OPER_OP_ORDER},
    {0x8B, "mov", REG_OPER_OP_ORDER},
    {-1, "", UNSET_OP_ORDER}
@@ -177,6 +178,7 @@
    SetTableRange(REGISTER_INSTR, 0x48, 0x4F, "dec");
    SetTableRange(REGISTER_INSTR, 0x50, 0x57, "push");
    SetTableRange(REGISTER_INSTR, 0x58, 0x5F, "pop");
+  SetTableRange(REGISTER_INSTR, 0x91, 0x97, "xchg eax,");  // 0x90 is nop.
    SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, "mov");
  }


Modified: branches/experimental/toiger/src/jump-target-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/jump-target-ia32.cc        (original)
+++ branches/experimental/toiger/src/jump-target-ia32.cc        Mon Dec 29  
05:58:09 2008
@@ -168,6 +168,32 @@
  }


+void JumpTarget::Branch(Condition cc, Result* arg0, Result* arg1, Hint  
hint) {
+  ASSERT(cgen_ != NULL);
+  ASSERT(cgen_->frame() != NULL);
+
+#ifdef DEBUG
+  // We want register results at the call site to stay in the same  
registers
+  // on the fall-through branch.
+  Result::Type arg0_type = arg0->type();
+  Register arg0_reg = arg0->is_register() ? arg0->reg() : no_reg;
+  Result::Type arg1_type = arg1->type();
+  Register arg1_reg = arg1->is_register() ? arg1->reg() : no_reg;
+#endif
+
+  cgen_->frame()->Push(arg0);
+  cgen_->frame()->Push(arg1);
+  Branch(cc, hint);
+  *arg1 = cgen_->frame()->Pop();
+  *arg0 = cgen_->frame()->Pop();
+
+  ASSERT(arg0->type() == arg0_type);
+  ASSERT(!arg0->is_register() || arg0->reg().is(arg0_reg));
+  ASSERT(arg1->type() == arg1_type);
+  ASSERT(!arg1->is_register() || arg1->reg().is(arg1_reg));
+}
+
+
  void JumpTarget::Call() {
    // Precondition: there is a current frame, and there is no expected frame
    // at the label.
@@ -258,6 +284,45 @@

    ASSERT(!had_entry_frame || arg->type() == arg_type);
    ASSERT(!had_entry_frame || !arg->is_register() ||  
arg->reg().is(arg_reg));
+}
+
+
+void JumpTarget::Bind(Result* arg0, Result* arg1) {
+  ASSERT(cgen_ != NULL);
+
+#ifdef DEBUG
+  // We want register results at the call site to stay in the same
+  // registers.
+  bool had_entry_frame = false;
+  Result::Type arg0_type;
+  Register arg0_reg;
+  Result::Type arg1_type;
+  Register arg1_reg;
+#endif
+
+  if (cgen_->frame() != NULL) {
+#ifdef DEBUG
+    had_entry_frame = true;
+    arg0_type = arg0->type();
+    arg0_reg = arg0->is_register() ? arg0->reg() : no_reg;
+    arg1_type = arg1->type();
+    arg1_reg = arg1->is_register() ? arg1->reg() : no_reg;
+#endif
+    cgen_->frame()->Push(arg0);
+    cgen_->frame()->Push(arg1);
+  }
+  Bind();
+  *arg1 = cgen_->frame()->Pop();
+  *arg0 = cgen_->frame()->Pop();
+
+  ASSERT(!had_entry_frame || arg0->type() == arg0_type);
+  ASSERT(!had_entry_frame ||
+         !arg0->is_register() ||
+         arg0->reg().is(arg0_reg));
+  ASSERT(!had_entry_frame || arg1->type() == arg1_type);
+  ASSERT(!had_entry_frame ||
+         !arg1->is_register() ||
+         arg1->reg().is(arg1_reg));
  }



Modified: branches/experimental/toiger/src/jump-target.h
==============================================================================
--- branches/experimental/toiger/src/jump-target.h      (original)
+++ branches/experimental/toiger/src/jump-target.h      Mon Dec 29 05:58:09 2008
@@ -98,11 +98,13 @@
    // there must be one expected at the target.
    void Branch(Condition cc, Hint hint = no_hint);
    void Branch(Condition cc, Result* arg, Hint hint = no_hint);
+  void Branch(Condition cc, Result* arg0, Result* arg1, Hint hint =  
no_hint);

    // Bind a jump target.  There must be a current frame and no expected
    // frame at the target (targets are only bound once).
    void Bind();
    void Bind(Result* arg);
+  void Bind(Result* arg0, Result* arg1);

    // Emit a call to a jump target.  There must be a current frame.  The
    // frame at the target is the same as the current frame except for an

Modified: branches/experimental/toiger/src/virtual-frame-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/virtual-frame-ia32.cc      (original)
+++ branches/experimental/toiger/src/virtual-frame-ia32.cc      Mon Dec 29  
05:58:09 2008
@@ -132,6 +132,7 @@


  void VirtualFrame::Spill(Register target) {
+  if (!frame_registers_.is_used(target)) return;
    for (int i = 0; i < elements_.length(); i++) {
      if (elements_[i].is_register() && elements_[i].reg().is(target)) {
        SpillElementAt(i);

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

Reply via email to