Index: src/arm/codegen-arm.h |
=================================================================== |
--- src/arm/codegen-arm.h (revision 2620) |
+++ src/arm/codegen-arm.h (working copy) |
@@ -421,6 +421,96 @@ |
}; |
+class GenericBinaryOpStub : public CodeStub { |
+ public: |
+ GenericBinaryOpStub(Token::Value op, |
+ OverwriteMode mode, |
+ int constant_rhs = CodeGenerator::kUnknownIntValue) |
+ : op_(op), |
+ mode_(mode), |
+ constant_rhs_(constant_rhs), |
+ specialized_on_rhs_(RhsIsOneWeWantToOptimizeFor(op, constant_rhs)) { } |
+ |
+ private: |
+ Token::Value op_; |
+ OverwriteMode mode_; |
+ int constant_rhs_; |
+ bool specialized_on_rhs_; |
+ |
+ static const int kMaxKnownRhs = 0x40000000; |
+ |
+ // Minor key encoding in 16 bits. |
+ class ModeBits: public BitField<OverwriteMode, 0, 2> {}; |
+ class OpBits: public BitField<Token::Value, 2, 6> {}; |
+ class KnownIntBits: public BitField<int, 8, 8> {}; |
+ |
+ Major MajorKey() { return GenericBinaryOp; } |
+ int MinorKey() { |
+ // Encode the parameters in a unique 16 bit value. |
+ return OpBits::encode(op_) |
+ | ModeBits::encode(mode_) |
+ | KnownIntBits::encode(MinorKeyForKnownInt()); |
+ } |
+ |
+ void Generate(MacroAssembler* masm); |
+ void HandleNonSmiBitwiseOp(MacroAssembler* masm); |
+ |
+ static bool RhsIsOneWeWantToOptimizeFor(Token::Value op, int constant_rhs) { |
+ if (constant_rhs == CodeGenerator::kUnknownIntValue) return false; |
+ if (op == Token::DIV) return constant_rhs >= 2 && constant_rhs <= 3; |
+ if (op == Token::MOD) { |
+ if (constant_rhs <= 1) return false; |
+ if (constant_rhs <= 10) return true; |
+ if (constant_rhs <= kMaxKnownRhs && IsPowerOf2(constant_rhs)) return true; |
+ return false; |
+ } |
+ return false; |
+ } |
+ |
+ int MinorKeyForKnownInt() { |
+ if (!specialized_on_rhs_) return 0; |
+ if (constant_rhs_ <= 10) return constant_rhs_ + 1; |
+ ASSERT(IsPowerOf2(constant_rhs_)); |
+ int key = 12; |
+ int d = constant_rhs_; |
+ while ((d & 1) == 0) { |
+ key++; |
+ d >>= 1; |
+ } |
+ return key; |
+ } |
+ |
+ const char* GetName() { |
+ switch (op_) { |
+ case Token::ADD: return "GenericBinaryOpStub_ADD"; |
+ case Token::SUB: return "GenericBinaryOpStub_SUB"; |
+ case Token::MUL: return "GenericBinaryOpStub_MUL"; |
+ case Token::DIV: return "GenericBinaryOpStub_DIV"; |
+ case Token::MOD: return "GenericBinaryOpStub_MOD"; |
+ case Token::BIT_OR: return "GenericBinaryOpStub_BIT_OR"; |
+ case Token::BIT_AND: return "GenericBinaryOpStub_BIT_AND"; |
+ case Token::BIT_XOR: return "GenericBinaryOpStub_BIT_XOR"; |
+ case Token::SAR: return "GenericBinaryOpStub_SAR"; |
+ case Token::SHL: return "GenericBinaryOpStub_SHL"; |
+ case Token::SHR: return "GenericBinaryOpStub_SHR"; |
+ default: return "GenericBinaryOpStub"; |
+ } |
+ } |
+ |
+#ifdef DEBUG |
+ void Print() { |
+ if (!specialized_on_rhs_) { |
+ PrintF("GenericBinaryOpStub (%s)\n", Token::String(op_)); |
+ } else { |
+ PrintF("GenericBinaryOpStub (%s by %d)\n", |
+ Token::String(op_), |
+ constant_rhs_); |
+ } |
+ } |
+#endif |
+}; |
+ |
+ |
} } // namespace v8::internal |
#endif // V8_ARM_CODEGEN_ARM_H_ |