Revision: 2634
Author: [email protected]
Date: Thu Aug  6 04:51:23 2009
Log: X64: Optimize MOD operator by a constant power of 2.
Review URL: http://codereview.chromium.org/164054
http://code.google.com/p/v8/source/detail?r=2634

Modified:
  /branches/bleeding_edge/src/x64/codegen-x64.cc
  /branches/bleeding_edge/src/x64/codegen-x64.h

=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc      Thu Aug  6 03:22:38 2009
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc      Thu Aug  6 04:51:23 2009
@@ -95,6 +95,78 @@
    ASSERT(owner_->state() == this);
    owner_->set_state(previous_);
  }
+
+
+//  
-------------------------------------------------------------------------
+// Deferred code objects
+//
+// These subclasses of DeferredCode add pieces of code to the end of  
generated
+// code.  They are branched to from the generated code, and
+// keep some slower code out of the main body of the generated code.
+// Many of them call a code stub or a runtime function.
+
+class DeferredInlineSmiAdd: public DeferredCode {
+ public:
+  DeferredInlineSmiAdd(Register dst,
+                       Smi* value,
+                       OverwriteMode overwrite_mode)
+      : dst_(dst), value_(value), overwrite_mode_(overwrite_mode) {
+    set_comment("[ DeferredInlineSmiAdd");
+  }
+
+  virtual void Generate();
+
+ private:
+  Register dst_;
+  Smi* value_;
+  OverwriteMode overwrite_mode_;
+};
+
+
+class DeferredInlineSmiSub: public DeferredCode {
+ public:
+  DeferredInlineSmiSub(Register dst,
+                       Smi* value,
+                       OverwriteMode overwrite_mode)
+      : dst_(dst), value_(value), overwrite_mode_(overwrite_mode) {
+    set_comment("[ DeferredInlineSmiSub");
+  }
+
+  virtual void Generate();
+
+ private:
+  Register dst_;
+  Smi* value_;
+  OverwriteMode overwrite_mode_;
+};
+
+
+// Call the appropriate binary operation stub to compute src op value
+// and leave the result in dst.
+class DeferredInlineSmiOperation: public DeferredCode {
+ public:
+  DeferredInlineSmiOperation(Token::Value op,
+                             Register dst,
+                             Register src,
+                             Smi* value,
+                             OverwriteMode overwrite_mode)
+      : op_(op),
+        dst_(dst),
+        src_(src),
+        value_(value),
+        overwrite_mode_(overwrite_mode) {
+    set_comment("[ DeferredInlineSmiOperation");
+  }
+
+  virtual void Generate();
+
+ private:
+  Token::Value op_;
+  Register dst_;
+  Register src_;
+  Smi* value_;
+  OverwriteMode overwrite_mode_;
+};


  //  
-----------------------------------------------------------------------------
@@ -4769,29 +4841,6 @@
    if (!dst_.is(rax)) __ movq(dst_, rax);
    __ pop(receiver_);
  }
-
-
-
-
-// The result of src + value is in dst.  It either overflowed or was not
-// smi tagged.  Undo the speculative addition and call the appropriate
-// specialized stub for add.  The result is left in dst.
-class DeferredInlineSmiAdd: public DeferredCode {
- public:
-  DeferredInlineSmiAdd(Register dst,
-                       Smi* value,
-                       OverwriteMode overwrite_mode)
-      : dst_(dst), value_(value), overwrite_mode_(overwrite_mode) {
-    set_comment("[ DeferredInlineSmiAdd");
-  }
-
-  virtual void Generate();
-
- private:
-  Register dst_;
-  Smi* value_;
-  OverwriteMode overwrite_mode_;
-};


  void DeferredInlineSmiAdd::Generate() {
@@ -4825,43 +4874,34 @@


  void DeferredInlineSmiAddReversed::Generate() {
-  __ push(Immediate(value_));
+  __ push(Immediate(value_));  // Note: sign extended.
    __ push(dst_);
    GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_,  
SMI_CODE_INLINED);
    __ CallStub(&igostub);
    if (!dst_.is(rax)) __ movq(dst_, rax);
  }
-
-
-// The result of src - value is in dst.  It either overflowed or was not
-// smi tagged.  Undo the speculative subtraction and call the
-// appropriate specialized stub for subtract.  The result is left in
-// dst.
-class DeferredInlineSmiSub: public DeferredCode {
- public:
-  DeferredInlineSmiSub(Register dst,
-                       Smi* value,
-                       OverwriteMode overwrite_mode)
-      : dst_(dst), value_(value), overwrite_mode_(overwrite_mode) {
-    set_comment("[ DeferredInlineSmiSub");
-  }
-
-  virtual void Generate();
-
- private:
-  Register dst_;
-  Smi* value_;
-  OverwriteMode overwrite_mode_;
-};


  void DeferredInlineSmiSub::Generate() {
    __ push(dst_);
-  __ push(Immediate(value_));
+  __ push(Immediate(value_));  // Note: sign extended.
    GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_,  
SMI_CODE_INLINED);
    __ CallStub(&igostub);
    if (!dst_.is(rax)) __ movq(dst_, rax);
  }
+
+
+void DeferredInlineSmiOperation::Generate() {
+  __ push(src_);
+  __ push(Immediate(value_));  // Note: sign extended.
+  // For mod we don't generate all the Smi code inline.
+  GenericBinaryOpStub stub(
+      op_,
+      overwrite_mode_,
+      (op_ == Token::MOD) ? SMI_CODE_IN_STUB : SMI_CODE_INLINED);
+  __ CallStub(&stub);
+  if (!dst_.is(rax)) __ movq(dst_, rax);
+}


  void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
@@ -4892,6 +4932,7 @@

    // Get the literal value.
    Smi* smi_value = Smi::cast(*value);
+  int int_value = smi_value->value();

    switch (op) {
      case Token::ADD: {
@@ -4921,6 +4962,36 @@
        break;
      }
      // TODO(X64): Move other implementations from ia32 to here.
+
+    // Generate inline code for mod of powers of 2 and negative powers of  
2.
+    case Token::MOD:
+      if (!reversed &&
+          int_value != 0 &&
+          (IsPowerOf2(int_value) || IsPowerOf2(-int_value))) {
+        operand->ToRegister();
+        frame_->Spill(operand->reg());
+        DeferredCode* deferred = new DeferredInlineSmiOperation(op,
+                                                                 
operand->reg(),
+                                                                 
operand->reg(),
+                                                                smi_value,
+                                                                 
overwrite_mode);
+        // Check for negative or non-Smi left hand side.
+        __ testl(operand->reg(),
+                 Immediate(static_cast<int32_t>(kSmiTagMask |  
0x80000000)));
+        deferred->Branch(not_zero);
+        if (int_value < 0) int_value = -int_value;
+        if (int_value == 1) {
+          __ movl(operand->reg(), Immediate(Smi::FromInt(0)));
+        } else {
+          __ and_(operand->reg(), Immediate((int_value << kSmiTagSize) -  
1));
+        }
+        deferred->BindExit();
+        frame_->Push(operand);
+        break;  // This break only applies if we generated code for MOD.
+      }
+      // Fall through if we did not find a power of 2 on the right hand  
side!
+      // The next case must be the default.
+
      default: {
        Result constant_operand(value);
        if (reversed) {
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.h       Wed Aug  5 05:52:31 2009
+++ /branches/bleeding_edge/src/x64/codegen-x64.h       Thu Aug  6 04:51:23 2009
@@ -601,6 +601,15 @@
  };


+//  
-------------------------------------------------------------------------
+// Code stubs
+//
+// These independent code objects are created once, and used multiple
+// times by generated code to perform common tasks, often the slow
+// case of a JavaScript operation.  They are all subclasses of CodeStub,
+// which is declared in code-stubs.h.
+
+
  // Flag that indicates whether or not the code that handles smi arguments
  // should be placed in the stub, inlined, or omitted entirely.
  enum GenericBinaryFlags {

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

Reply via email to