Commit e1e4d985 authored by whesse@chromium.org's avatar whesse@chromium.org

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
parent 7f0645a2
...@@ -1446,10 +1446,40 @@ bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) { ...@@ -1446,10 +1446,40 @@ bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) {
} }
static void CheckTwoForSminess(MacroAssembler* masm, void CodeGenerator::JumpIfNotBothSmiUsingTypeInfo(Register left,
Register left, Register right, Register scratch, Register right,
TypeInfo left_info, TypeInfo right_info, Register scratch,
DeferredInlineBinaryOperation* deferred); 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 // Implements a binary operation using a deferred code object and some
...@@ -1539,19 +1569,11 @@ Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr, ...@@ -1539,19 +1569,11 @@ Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr,
left_type_info, left_type_info,
right_type_info, right_type_info,
overwrite_mode); overwrite_mode);
if (left->reg().is(right->reg())) { JumpIfNotBothSmiUsingTypeInfo(left->reg(), right->reg(), edx,
__ test(left->reg(), Immediate(kSmiTagMask)); left_type_info, right_type_info, deferred);
} else { if (!left_is_in_eax) {
// Use the quotient register as a scratch for the tag check. __ mov(eax, left->reg());
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));
} }
deferred->Branch(not_zero);
if (!left_is_in_eax) __ mov(eax, left->reg());
// Sign extend eax into edx:eax. // Sign extend eax into edx:eax.
__ cdq(); __ cdq();
// Check for 0 divisor. // Check for 0 divisor.
...@@ -1674,8 +1696,8 @@ Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr, ...@@ -1674,8 +1696,8 @@ Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr,
__ cmp(answer.reg(), 0xc0000000); __ cmp(answer.reg(), 0xc0000000);
deferred->Branch(negative); deferred->Branch(negative);
} else { } else {
CheckTwoForSminess(masm_, left->reg(), right->reg(), answer.reg(), JumpIfNotBothSmiUsingTypeInfo(left->reg(), right->reg(), answer.reg(),
left_type_info, right_type_info, deferred); left_type_info, right_type_info, deferred);
// Untag both operands. // Untag both operands.
__ mov(answer.reg(), left->reg()); __ mov(answer.reg(), left->reg());
...@@ -1751,8 +1773,8 @@ Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr, ...@@ -1751,8 +1773,8 @@ Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr,
left_type_info, left_type_info,
right_type_info, right_type_info,
overwrite_mode); overwrite_mode);
CheckTwoForSminess(masm_, left->reg(), right->reg(), answer.reg(), JumpIfNotBothSmiUsingTypeInfo(left->reg(), right->reg(), answer.reg(),
left_type_info, right_type_info, deferred); left_type_info, right_type_info, deferred);
__ mov(answer.reg(), left->reg()); __ mov(answer.reg(), left->reg());
switch (op) { switch (op) {
...@@ -8976,40 +8998,6 @@ Result CodeGenerator::EmitKeyedStore(StaticType* key_type) { ...@@ -8976,40 +8998,6 @@ Result CodeGenerator::EmitKeyedStore(StaticType* key_type) {
#define __ ACCESS_MASM(masm) #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() { Handle<String> Reference::GetName() {
ASSERT(type_ == NAMED); ASSERT(type_ == NAMED);
Property* property = expression_->AsProperty(); Property* property = expression_->AsProperty();
......
...@@ -519,6 +519,16 @@ class CodeGenerator: public AstVisitor { ...@@ -519,6 +519,16 @@ class CodeGenerator: public AstVisitor {
void GenericBinaryOperation(BinaryOperation* expr, void GenericBinaryOperation(BinaryOperation* expr,
OverwriteMode overwrite_mode); 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 // 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. // a smi result, and push it on the virtual frame, all at compile time.
// Returns true if it succeeds. Otherwise it has no effect. // Returns true if it succeeds. Otherwise it has no effect.
......
...@@ -7133,6 +7133,25 @@ Result CodeGenerator::ConstantSmiBinaryOperation(BinaryOperation* expr, ...@@ -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 // Implements a binary operation using a deferred code object and some
// inline code to operate on smis quickly. // inline code to operate on smis quickly.
Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr, Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr,
...@@ -7142,9 +7161,6 @@ 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. // Copy the type info because left and right may be overwritten.
TypeInfo left_type_info = left->type_info(); TypeInfo left_type_info = left->type_info();
TypeInfo right_type_info = right->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(); Token::Value op = expr->op();
Result answer; Result answer;
// Special handling of div and mod because they use fixed registers. // Special handling of div and mod because they use fixed registers.
...@@ -7221,7 +7237,8 @@ Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr, ...@@ -7221,7 +7237,8 @@ Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr,
left->reg(), left->reg(),
right->reg(), right->reg(),
overwrite_mode); 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) { if (op == Token::DIV) {
__ SmiDiv(rax, left->reg(), right->reg(), deferred->entry_label()); __ SmiDiv(rax, left->reg(), right->reg(), deferred->entry_label());
...@@ -7303,7 +7320,8 @@ Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr, ...@@ -7303,7 +7320,8 @@ Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr,
} }
} }
} else { } else {
__ JumpIfNotBothSmi(left->reg(), rcx, deferred->entry_label()); JumpIfNotBothSmiUsingTypeInfo(left->reg(), rcx,
left_type_info, right_type_info, deferred);
} }
__ bind(&do_op); __ bind(&do_op);
...@@ -7351,7 +7369,8 @@ Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr, ...@@ -7351,7 +7369,8 @@ Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr,
left->reg(), left->reg(),
right->reg(), right->reg(),
overwrite_mode); overwrite_mode);
__ JumpIfNotBothSmi(left->reg(), right->reg(), deferred->entry_label()); JumpIfNotBothSmiUsingTypeInfo(left->reg(), right->reg(),
left_type_info, right_type_info, deferred);
switch (op) { switch (op) {
case Token::ADD: case Token::ADD:
......
...@@ -477,6 +477,15 @@ class CodeGenerator: public AstVisitor { ...@@ -477,6 +477,15 @@ class CodeGenerator: public AstVisitor {
void GenericBinaryOperation(BinaryOperation* expr, void GenericBinaryOperation(BinaryOperation* expr,
OverwriteMode overwrite_mode); 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 // 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. // a smi result, and push it on the virtual frame, all at compile time.
// Returns true if it succeeds. Otherwise it has no effect. // Returns true if it succeeds. Otherwise it has no effect.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment