Add inlined code for (constant SHL smi), ported from ia32 to x64. Improve type information on ia32 version of code.

Review URL: http://codereview.chromium.org/1869001

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4571 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
whesse@chromium.org 2010-05-04 08:10:05 +00:00
parent b685df1caa
commit 1f9fef3d51
2 changed files with 103 additions and 31 deletions

View File

@ -2041,8 +2041,8 @@ Result CodeGenerator::ConstantSmiBinaryOperation(
if (!operand->type_info().IsSmi()) { if (!operand->type_info().IsSmi()) {
__ test(operand->reg(), Immediate(kSmiTagMask)); __ test(operand->reg(), Immediate(kSmiTagMask));
deferred->Branch(not_zero); deferred->Branch(not_zero);
} else { } else if (FLAG_debug_code) {
if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg()); __ AbortIfNotSmi(operand->reg());
} }
deferred->BindExit(); deferred->BindExit();
answer = *operand; answer = *operand;
@ -2080,8 +2080,8 @@ Result CodeGenerator::ConstantSmiBinaryOperation(
if (!operand->type_info().IsSmi()) { if (!operand->type_info().IsSmi()) {
__ test(answer.reg(), Immediate(kSmiTagMask)); __ test(answer.reg(), Immediate(kSmiTagMask));
deferred->Branch(not_zero); deferred->Branch(not_zero);
} else { } else if (FLAG_debug_code) {
if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg()); __ AbortIfNotSmi(operand->reg());
} }
deferred->BindExit(); deferred->BindExit();
operand->Unuse(); operand->Unuse();
@ -2115,7 +2115,9 @@ Result CodeGenerator::ConstantSmiBinaryOperation(
} }
deferred->BindExit(); deferred->BindExit();
} else { } else {
if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg()); if (FLAG_debug_code) {
__ AbortIfNotSmi(operand->reg());
}
if (shift_value > 0) { if (shift_value > 0) {
__ sar(operand->reg(), shift_value); __ sar(operand->reg(), shift_value);
__ and_(operand->reg(), ~kSmiTagMask); __ and_(operand->reg(), ~kSmiTagMask);
@ -2147,8 +2149,8 @@ Result CodeGenerator::ConstantSmiBinaryOperation(
if (!operand->type_info().IsSmi()) { if (!operand->type_info().IsSmi()) {
__ test(operand->reg(), Immediate(kSmiTagMask)); __ test(operand->reg(), Immediate(kSmiTagMask));
deferred->Branch(not_zero); deferred->Branch(not_zero);
} else { } else if (FLAG_debug_code) {
if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg()); __ AbortIfNotSmi(operand->reg());
} }
__ mov(answer.reg(), operand->reg()); __ mov(answer.reg(), operand->reg());
__ SmiUntag(answer.reg()); __ SmiUntag(answer.reg());
@ -2166,12 +2168,12 @@ Result CodeGenerator::ConstantSmiBinaryOperation(
case Token::SHL: case Token::SHL:
if (reversed) { if (reversed) {
// Move operand into ecx and also into a second register.
// If operand is already in a register, take advantage of that.
// This lets us modify ecx, but still bail out to deferred code.
Result right; Result right;
Result right_copy_in_ecx; Result right_copy_in_ecx;
TypeInfo right_type_info = operand->type_info();
// Make sure to get a copy of the right operand into ecx. This
// allows us to modify it without having to restore it in the
// deferred code.
operand->ToRegister(); operand->ToRegister();
if (operand->reg().is(ecx)) { if (operand->reg().is(ecx)) {
right = allocator()->Allocate(); right = allocator()->Allocate();
@ -2191,14 +2193,14 @@ Result CodeGenerator::ConstantSmiBinaryOperation(
answer.reg(), answer.reg(),
smi_value, smi_value,
right.reg(), right.reg(),
right.type_info(), right_type_info,
overwrite_mode); overwrite_mode);
__ mov(answer.reg(), Immediate(int_value)); __ mov(answer.reg(), Immediate(int_value));
__ sar(ecx, kSmiTagSize); __ sar(ecx, kSmiTagSize);
if (!right.type_info().IsSmi()) { if (!right.type_info().IsSmi()) {
deferred->Branch(carry); deferred->Branch(carry);
} else { } else if (FLAG_debug_code) {
if (FLAG_debug_code) __ AbortIfNotSmi(right.reg()); __ AbortIfNotSmi(right.reg());
} }
__ shl_cl(answer.reg()); __ shl_cl(answer.reg());
__ cmp(answer.reg(), 0xc0000000); __ cmp(answer.reg(), 0xc0000000);
@ -2239,8 +2241,8 @@ Result CodeGenerator::ConstantSmiBinaryOperation(
if (!operand->type_info().IsSmi()) { if (!operand->type_info().IsSmi()) {
__ test(operand->reg(), Immediate(kSmiTagMask)); __ test(operand->reg(), Immediate(kSmiTagMask));
deferred->Branch(not_zero); deferred->Branch(not_zero);
} else { } else if (FLAG_debug_code) {
if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg()); __ AbortIfNotSmi(operand->reg());
} }
__ mov(answer.reg(), operand->reg()); __ mov(answer.reg(), operand->reg());
ASSERT(kSmiTag == 0); // adjust code if not the case ASSERT(kSmiTag == 0); // adjust code if not the case
@ -2283,8 +2285,8 @@ Result CodeGenerator::ConstantSmiBinaryOperation(
if (!operand->type_info().IsSmi()) { if (!operand->type_info().IsSmi()) {
__ test(operand->reg(), Immediate(kSmiTagMask)); __ test(operand->reg(), Immediate(kSmiTagMask));
deferred->Branch(not_zero); deferred->Branch(not_zero);
} else { } else if (FLAG_debug_code) {
if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg()); __ AbortIfNotSmi(operand->reg());
} }
if (op == Token::BIT_AND) { if (op == Token::BIT_AND) {
__ and_(Operand(operand->reg()), Immediate(value)); __ and_(Operand(operand->reg()), Immediate(value));

View File

@ -193,6 +193,34 @@ class DeferredInlineSmiOperation: public DeferredCode {
}; };
// Call the appropriate binary operation stub to compute value op src
// and leave the result in dst.
class DeferredInlineSmiOperationReversed: public DeferredCode {
public:
DeferredInlineSmiOperationReversed(Token::Value op,
Register dst,
Smi* value,
Register src,
OverwriteMode overwrite_mode)
: op_(op),
dst_(dst),
value_(value),
src_(src),
overwrite_mode_(overwrite_mode) {
set_comment("[ DeferredInlineSmiOperationReversed");
}
virtual void Generate();
private:
Token::Value op_;
Register dst_;
Smi* value_;
Register src_;
OverwriteMode overwrite_mode_;
};
class FloatingPointHelper : public AllStatic { class FloatingPointHelper : public AllStatic {
public: public:
// Code pattern for loading a floating point value. Input value must // Code pattern for loading a floating point value. Input value must
@ -6363,6 +6391,16 @@ void DeferredInlineSmiOperation::Generate() {
} }
void DeferredInlineSmiOperationReversed::Generate() {
GenericBinaryOpStub stub(
op_,
overwrite_mode_,
NO_SMI_CODE_IN_STUB);
stub.GenerateCall(masm_, value_, src_);
if (!dst_.is(rax)) __ movq(dst_, rax);
}
Result CodeGenerator::ConstantSmiBinaryOperation(BinaryOperation* expr, Result CodeGenerator::ConstantSmiBinaryOperation(BinaryOperation* expr,
Result* operand, Result* operand,
Handle<Object> value, Handle<Object> value,
@ -6492,9 +6530,45 @@ Result CodeGenerator::ConstantSmiBinaryOperation(BinaryOperation* expr,
case Token::SHL: case Token::SHL:
if (reversed) { if (reversed) {
Result constant_operand(value); // Move operand into rcx and also into a second register.
answer = LikelySmiBinaryOperation(expr, &constant_operand, operand, // If operand is already in a register, take advantage of that.
overwrite_mode); // This lets us modify rcx, but still bail out to deferred code.
Result right;
Result right_copy_in_rcx;
TypeInfo right_type_info = operand->type_info();
operand->ToRegister();
if (operand->reg().is(rcx)) {
right = allocator()->Allocate();
__ movq(right.reg(), rcx);
frame_->Spill(rcx);
right_copy_in_rcx = *operand;
} else {
right_copy_in_rcx = allocator()->Allocate(rcx);
__ movq(rcx, operand->reg());
right = *operand;
}
operand->Unuse();
answer = allocator()->Allocate();
DeferredInlineSmiOperationReversed* deferred =
new DeferredInlineSmiOperationReversed(op,
answer.reg(),
smi_value,
right.reg(),
overwrite_mode);
__ movq(answer.reg(), Immediate(int_value));
__ SmiToInteger32(rcx, rcx);
if (!right.type_info().IsSmi()) {
Condition is_smi = masm_->CheckSmi(right.reg());
deferred->Branch(NegateCondition(is_smi));
} else if (FLAG_debug_code) {
__ AbortIfNotSmi(right.reg(),
"Static type info claims non-smi is smi in (const SHL smi).");
}
__ shl_cl(answer.reg());
__ Integer32ToSmi(answer.reg(), answer.reg());
deferred->BindExit();
} else { } else {
// Only the least significant 5 bits of the shift value are used. // Only the least significant 5 bits of the shift value are used.
// In the slow case, this masking is done inside the runtime call. // In the slow case, this masking is done inside the runtime call.
@ -7201,10 +7275,8 @@ void Reference::SetValue(InitState init_state) {
// Check that the key is a smi. // Check that the key is a smi.
if (!key.is_smi()) { if (!key.is_smi()) {
__ JumpIfNotSmi(key.reg(), deferred->entry_label()); __ JumpIfNotSmi(key.reg(), deferred->entry_label());
} else { } else if (FLAG_debug_code) {
if (FLAG_debug_code) { __ AbortIfNotSmi(key.reg(), "Non-smi value in smi-typed value.");
__ AbortIfNotSmi(key.reg(), "Non-smi value in smi-typed value.");
}
} }
// Check that the receiver is a JSArray. // Check that the receiver is a JSArray.
@ -9961,12 +10033,10 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
Label not_floats; Label not_floats;
// rax: y // rax: y
// rdx: x // rdx: x
if (static_operands_type_.IsNumber()) { if (static_operands_type_.IsNumber() && FLAG_debug_code) {
if (FLAG_debug_code) { // Assert at runtime that inputs are only numbers.
// Assert at runtime that inputs are only numbers. __ AbortIfNotNumber(rdx, "GenericBinaryOpStub operand not a number.");
__ AbortIfNotNumber(rdx, "GenericBinaryOpStub operand not a number."); __ AbortIfNotNumber(rax, "GenericBinaryOpStub operand not a number.");
__ AbortIfNotNumber(rax, "GenericBinaryOpStub operand not a number.");
}
} else { } else {
FloatingPointHelper::CheckNumberOperands(masm, &call_runtime); FloatingPointHelper::CheckNumberOperands(masm, &call_runtime);
} }