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:
parent
7f0645a20a
commit
e1e4d985f9
@ -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();
|
||||
|
@ -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.
|
||||
|
@ -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:
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user