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
This commit is contained in:
whesse@chromium.org 2010-06-09 11:15:54 +00:00
parent 7f0645a20a
commit e1e4d985f9
4 changed files with 86 additions and 60 deletions

View File

@ -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<String> Reference::GetName() {
ASSERT(type_ == NAMED);
Property* property = expression_->AsProperty();

View File

@ -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.

View File

@ -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:

View File

@ -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.