From e1e4d985f9f4e24f4de20364ba542b513ff865b8 Mon Sep 17 00:00:00 2001 From: "whesse@chromium.org" Date: Wed, 9 Jun 2010 11:15:54 +0000 Subject: [PATCH] Use static type information on x64 in LikelySmiBinaryOperation. Refactor check for smi operands, using type information, on ia32 and x64. Review URL: http://codereview.chromium.org/2771001 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4831 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/ia32/codegen-ia32.cc | 96 ++++++++++++++++++---------------------- src/ia32/codegen-ia32.h | 10 +++++ src/x64/codegen-x64.cc | 31 ++++++++++--- src/x64/codegen-x64.h | 9 ++++ 4 files changed, 86 insertions(+), 60 deletions(-) diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc index 603f9135ff..d870828a00 100644 --- a/src/ia32/codegen-ia32.cc +++ b/src/ia32/codegen-ia32.cc @@ -1446,10 +1446,40 @@ bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) { } -static void CheckTwoForSminess(MacroAssembler* masm, - Register left, Register right, Register scratch, - TypeInfo left_info, TypeInfo right_info, - DeferredInlineBinaryOperation* deferred); +void CodeGenerator::JumpIfNotBothSmiUsingTypeInfo(Register left, + Register right, + Register scratch, + TypeInfo left_info, + TypeInfo right_info, + DeferredCode* deferred) { + if (left.is(right)) { + if (!left_info.IsSmi()) { + __ test(left, Immediate(kSmiTagMask)); + deferred->Branch(not_zero); + } else { + if (FLAG_debug_code) __ AbortIfNotSmi(left); + } + } else if (!left_info.IsSmi()) { + if (!right_info.IsSmi()) { + __ mov(scratch, left); + __ or_(scratch, Operand(right)); + __ test(scratch, Immediate(kSmiTagMask)); + deferred->Branch(not_zero); + } else { + __ test(left, Immediate(kSmiTagMask)); + deferred->Branch(not_zero); + if (FLAG_debug_code) __ AbortIfNotSmi(right); + } + } else { + if (FLAG_debug_code) __ AbortIfNotSmi(left); + if (!right_info.IsSmi()) { + __ test(right, Immediate(kSmiTagMask)); + deferred->Branch(not_zero); + } else { + if (FLAG_debug_code) __ AbortIfNotSmi(right); + } + } +} // Implements a binary operation using a deferred code object and some @@ -1539,19 +1569,11 @@ Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr, left_type_info, right_type_info, overwrite_mode); - if (left->reg().is(right->reg())) { - __ test(left->reg(), Immediate(kSmiTagMask)); - } else { - // Use the quotient register as a scratch for the tag check. - if (!left_is_in_eax) __ mov(eax, left->reg()); - left_is_in_eax = false; // About to destroy the value in eax. - __ or_(eax, Operand(right->reg())); - ASSERT(kSmiTag == 0); // Adjust test if not the case. - __ test(eax, Immediate(kSmiTagMask)); + JumpIfNotBothSmiUsingTypeInfo(left->reg(), right->reg(), edx, + left_type_info, right_type_info, deferred); + if (!left_is_in_eax) { + __ mov(eax, left->reg()); } - deferred->Branch(not_zero); - - if (!left_is_in_eax) __ mov(eax, left->reg()); // Sign extend eax into edx:eax. __ cdq(); // Check for 0 divisor. @@ -1674,8 +1696,8 @@ Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr, __ cmp(answer.reg(), 0xc0000000); deferred->Branch(negative); } else { - CheckTwoForSminess(masm_, left->reg(), right->reg(), answer.reg(), - left_type_info, right_type_info, deferred); + JumpIfNotBothSmiUsingTypeInfo(left->reg(), right->reg(), answer.reg(), + left_type_info, right_type_info, deferred); // Untag both operands. __ mov(answer.reg(), left->reg()); @@ -1751,8 +1773,8 @@ Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr, left_type_info, right_type_info, overwrite_mode); - CheckTwoForSminess(masm_, left->reg(), right->reg(), answer.reg(), - left_type_info, right_type_info, deferred); + JumpIfNotBothSmiUsingTypeInfo(left->reg(), right->reg(), answer.reg(), + left_type_info, right_type_info, deferred); __ mov(answer.reg(), left->reg()); switch (op) { @@ -8976,40 +8998,6 @@ Result CodeGenerator::EmitKeyedStore(StaticType* key_type) { #define __ ACCESS_MASM(masm) -static void CheckTwoForSminess(MacroAssembler* masm, - Register left, Register right, Register scratch, - TypeInfo left_info, TypeInfo right_info, - DeferredInlineBinaryOperation* deferred) { - if (left.is(right)) { - if (!left_info.IsSmi()) { - __ test(left, Immediate(kSmiTagMask)); - deferred->Branch(not_zero); - } else { - if (FLAG_debug_code) __ AbortIfNotSmi(left); - } - } else if (!left_info.IsSmi()) { - if (!right_info.IsSmi()) { - __ mov(scratch, left); - __ or_(scratch, Operand(right)); - __ test(scratch, Immediate(kSmiTagMask)); - deferred->Branch(not_zero); - } else { - __ test(left, Immediate(kSmiTagMask)); - deferred->Branch(not_zero); - if (FLAG_debug_code) __ AbortIfNotSmi(right); - } - } else { - if (FLAG_debug_code) __ AbortIfNotSmi(left); - if (!right_info.IsSmi()) { - __ test(right, Immediate(kSmiTagMask)); - deferred->Branch(not_zero); - } else { - if (FLAG_debug_code) __ AbortIfNotSmi(right); - } - } -} - - Handle Reference::GetName() { ASSERT(type_ == NAMED); Property* property = expression_->AsProperty(); diff --git a/src/ia32/codegen-ia32.h b/src/ia32/codegen-ia32.h index 180b9a6bdf..a432c13f15 100644 --- a/src/ia32/codegen-ia32.h +++ b/src/ia32/codegen-ia32.h @@ -519,6 +519,16 @@ class CodeGenerator: public AstVisitor { void GenericBinaryOperation(BinaryOperation* expr, OverwriteMode overwrite_mode); + // Emits code sequence that jumps to deferred code if the inputs + // are not both smis. Cannot be in MacroAssembler because it takes + // advantage of TypeInfo to skip unneeded checks. + void JumpIfNotBothSmiUsingTypeInfo(Register left, + Register right, + Register scratch, + TypeInfo left_info, + TypeInfo right_info, + DeferredCode* deferred); + // If possible, combine two constant smi values using op to produce // a smi result, and push it on the virtual frame, all at compile time. // Returns true if it succeeds. Otherwise it has no effect. diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc index 701ec6501c..a0b1b5bf78 100644 --- a/src/x64/codegen-x64.cc +++ b/src/x64/codegen-x64.cc @@ -7133,6 +7133,25 @@ Result CodeGenerator::ConstantSmiBinaryOperation(BinaryOperation* expr, } +void CodeGenerator::JumpIfNotBothSmiUsingTypeInfo(Register left, + Register right, + TypeInfo left_info, + TypeInfo right_info, + DeferredCode* deferred) { + if (!left_info.IsSmi() && !right_info.IsSmi()) { + __ JumpIfNotBothSmi(left, right, deferred->entry_label()); + } else if (!left_info.IsSmi()) { + __ JumpIfNotSmi(left, deferred->entry_label()); + } else if (!right_info.IsSmi()) { + __ JumpIfNotSmi(right, deferred->entry_label()); + } + if (FLAG_debug_code) { + __ AbortIfNotSmi(left); + __ AbortIfNotSmi(right); + } +} + + // Implements a binary operation using a deferred code object and some // inline code to operate on smis quickly. Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr, @@ -7142,9 +7161,6 @@ Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr, // Copy the type info because left and right may be overwritten. TypeInfo left_type_info = left->type_info(); TypeInfo right_type_info = right->type_info(); - USE(left_type_info); - USE(right_type_info); - // TODO(X64): Use type information in calculations. Token::Value op = expr->op(); Result answer; // Special handling of div and mod because they use fixed registers. @@ -7221,7 +7237,8 @@ Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr, left->reg(), right->reg(), overwrite_mode); - __ JumpIfNotBothSmi(left->reg(), right->reg(), deferred->entry_label()); + JumpIfNotBothSmiUsingTypeInfo(left->reg(), right->reg(), + left_type_info, right_type_info, deferred); if (op == Token::DIV) { __ SmiDiv(rax, left->reg(), right->reg(), deferred->entry_label()); @@ -7303,7 +7320,8 @@ Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr, } } } else { - __ JumpIfNotBothSmi(left->reg(), rcx, deferred->entry_label()); + JumpIfNotBothSmiUsingTypeInfo(left->reg(), rcx, + left_type_info, right_type_info, deferred); } __ bind(&do_op); @@ -7351,7 +7369,8 @@ Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr, left->reg(), right->reg(), overwrite_mode); - __ JumpIfNotBothSmi(left->reg(), right->reg(), deferred->entry_label()); + JumpIfNotBothSmiUsingTypeInfo(left->reg(), right->reg(), + left_type_info, right_type_info, deferred); switch (op) { case Token::ADD: diff --git a/src/x64/codegen-x64.h b/src/x64/codegen-x64.h index 5b1c8af86a..fcf35f02d4 100644 --- a/src/x64/codegen-x64.h +++ b/src/x64/codegen-x64.h @@ -477,6 +477,15 @@ class CodeGenerator: public AstVisitor { void GenericBinaryOperation(BinaryOperation* expr, OverwriteMode overwrite_mode); + // Emits code sequence that jumps to deferred code if the inputs + // are not both smis. Cannot be in MacroAssembler because it takes + // advantage of TypeInfo to skip unneeded checks. + void JumpIfNotBothSmiUsingTypeInfo(Register left, + Register right, + TypeInfo left_info, + TypeInfo right_info, + DeferredCode* deferred); + // If possible, combine two constant smi values using op to produce // a smi result, and push it on the virtual frame, all at compile time. // Returns true if it succeeds. Otherwise it has no effect.