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:
parent
b685df1caa
commit
1f9fef3d51
@ -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));
|
||||||
|
@ -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.
|
||||||
|
// 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);
|
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,11 +7275,9 @@ 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.
|
||||||
__ CmpObjectType(receiver.reg(), JS_ARRAY_TYPE, kScratchRegister);
|
__ CmpObjectType(receiver.reg(), JS_ARRAY_TYPE, kScratchRegister);
|
||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user