Chromium Code Reviews| Index: src/ia32/codegen-ia32.cc |
| =================================================================== |
| --- src/ia32/codegen-ia32.cc (revision 4025) |
| +++ src/ia32/codegen-ia32.cc (working copy) |
| @@ -733,7 +733,27 @@ |
| Result value = frame_->Pop(); |
| value.ToRegister(); |
| - if (value.is_number()) { |
| + if (value.is_integer32()) { // Also takes Smi case. |
| + Comment cmnt(masm_, "ONLY_INTEGER_32"); |
| + if (FLAG_debug_code) { |
| + Label ok; |
| + __ AbortIfNotNumber(value.reg(), "ToBoolean operand is not a number."); |
| + __ test(value.reg(), Immediate(kSmiTagMask)); |
| + __ j(zero, &ok); |
| + __ fldz(); |
| + __ fld_d(FieldOperand(value.reg(), HeapNumber::kValueOffset)); |
| + __ FCmp(); |
| + __ j(not_zero, &ok); |
| + __ Abort("Smi was wrapped in HeapNumber in output from bitop"); |
| + __ bind(&ok); |
| + } |
| + // In the integer32 case there are no Smis hidden in heap numbers, so we |
| + // need only test for Smi zero. |
| + __ test(value.reg(), Operand(value.reg())); |
| + dest->false_target()->Branch(zero); |
| + value.Unuse(); |
| + dest->Split(not_zero); |
| + } else if (value.is_number()) { |
| Comment cmnt(masm_, "ONLY_NUMBER"); |
| // Fast case if NumberInfo indicates only numbers. |
| if (FLAG_debug_code) { |
| @@ -817,6 +837,7 @@ |
| // Takes the operands in edx and eax and loads them as integers in eax |
| // and ecx. |
| static void LoadAsIntegers(MacroAssembler* masm, |
| + NumberInfo number_info, |
| bool use_sse3, |
| Label* operand_conversion_failure); |
| // Test if operands are smis or heap numbers and load them |
| @@ -856,7 +877,7 @@ |
| (flags_ & NO_SMI_CODE_IN_STUB) ? "_NoSmiInStub" : "", |
| args_in_registers_ ? "RegArgs" : "StackArgs", |
| args_reversed_ ? "_R" : "", |
| - NumberInfo::ToString(static_operands_type_), |
| + static_operands_type_.ToString(), |
| BinaryOpIC::GetName(runtime_operands_type_)); |
| return name_; |
| } |
| @@ -869,8 +890,11 @@ |
| Register dst, |
| Register left, |
| Register right, |
| + NumberInfo left_info, |
| + NumberInfo right_info, |
| OverwriteMode mode) |
| - : op_(op), dst_(dst), left_(left), right_(right), mode_(mode) { |
| + : op_(op), dst_(dst), left_(left), right_(right), |
| + left_info_(left_info), right_info_(right_info), mode_(mode) { |
| set_comment("[ DeferredInlineBinaryOperation"); |
| } |
| @@ -881,6 +905,8 @@ |
| Register dst_; |
| Register left_; |
| Register right_; |
| + NumberInfo left_info_; |
| + NumberInfo right_info_; |
| OverwriteMode mode_; |
| }; |
| @@ -894,18 +920,22 @@ |
| CpuFeatures::Scope use_sse2(SSE2); |
| Label call_runtime, after_alloc_failure; |
| Label left_smi, right_smi, load_right, do_op; |
| - __ test(left_, Immediate(kSmiTagMask)); |
| - __ j(zero, &left_smi); |
| - __ cmp(FieldOperand(left_, HeapObject::kMapOffset), |
| - Factory::heap_number_map()); |
| - __ j(not_equal, &call_runtime); |
| - __ movdbl(xmm0, FieldOperand(left_, HeapNumber::kValueOffset)); |
| - if (mode_ == OVERWRITE_LEFT) { |
| - __ mov(dst_, left_); |
| + if (!left_info_.IsSmi()) { |
| + __ test(left_, Immediate(kSmiTagMask)); |
| + __ j(zero, &left_smi); |
| + if (!left_info_.IsNumber()) { |
| + __ cmp(FieldOperand(left_, HeapObject::kMapOffset), |
| + Factory::heap_number_map()); |
| + __ j(not_equal, &call_runtime); |
| + } |
| + __ movdbl(xmm0, FieldOperand(left_, HeapNumber::kValueOffset)); |
| + if (mode_ == OVERWRITE_LEFT) { |
| + __ mov(dst_, left_); |
| + } |
| + __ jmp(&load_right); |
| + |
| + __ bind(&left_smi); |
| } |
| - __ jmp(&load_right); |
| - |
| - __ bind(&left_smi); |
| __ SmiUntag(left_); |
| __ cvtsi2sd(xmm0, Operand(left_)); |
| __ SmiTag(left_); |
| @@ -917,23 +947,27 @@ |
| } |
| __ bind(&load_right); |
| - __ test(right_, Immediate(kSmiTagMask)); |
| - __ j(zero, &right_smi); |
| - __ cmp(FieldOperand(right_, HeapObject::kMapOffset), |
| - Factory::heap_number_map()); |
| - __ j(not_equal, &call_runtime); |
| - __ movdbl(xmm1, FieldOperand(right_, HeapNumber::kValueOffset)); |
| - if (mode_ == OVERWRITE_RIGHT) { |
| - __ mov(dst_, right_); |
| - } else if (mode_ == NO_OVERWRITE) { |
| - Label alloc_failure; |
| - __ push(left_); |
| - __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure); |
| - __ pop(left_); |
| + if (!right_info_.IsSmi()) { |
| + __ test(right_, Immediate(kSmiTagMask)); |
| + __ j(zero, &right_smi); |
| + if (!right_info_.IsNumber()) { |
| + __ cmp(FieldOperand(right_, HeapObject::kMapOffset), |
| + Factory::heap_number_map()); |
| + __ j(not_equal, &call_runtime); |
| + } |
| + __ movdbl(xmm1, FieldOperand(right_, HeapNumber::kValueOffset)); |
| + if (mode_ == OVERWRITE_RIGHT) { |
| + __ mov(dst_, right_); |
| + } else if (mode_ == NO_OVERWRITE) { |
| + Label alloc_failure; |
| + __ push(left_); |
| + __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure); |
| + __ pop(left_); |
| + } |
| + __ jmp(&do_op); |
| + |
| + __ bind(&right_smi); |
| } |
| - __ jmp(&do_op); |
| - |
| - __ bind(&right_smi); |
| __ SmiUntag(right_); |
| __ cvtsi2sd(xmm1, Operand(right_)); |
| __ SmiTag(right_); |
| @@ -959,13 +993,104 @@ |
| __ pop(left_); |
| __ bind(&call_runtime); |
| } |
| - GenericBinaryOpStub stub(op_, mode_, NO_SMI_CODE_IN_STUB); |
| + GenericBinaryOpStub stub(op_, |
| + mode_, |
| + NO_SMI_CODE_IN_STUB, |
| + NumberInfo::Combine(left_info_, right_info_)); |
| stub.GenerateCall(masm_, left_, right_); |
| if (!dst_.is(eax)) __ mov(dst_, eax); |
| __ bind(&done); |
| } |
| +static NumberInfo CalculateNumberInfo(NumberInfo operands_type, |
| + Token::Value op, |
| + const Result& right, |
| + const Result& left) { |
| + // Set NumberInfo of result according to the operation performed. |
| + // Rely on the fact that smis have a 31 bit payload on ia32. |
| + ASSERT(kSmiValueSize == 31); |
| + switch (op) { |
| + case Token::COMMA: |
| + return right.number_info(); |
| + case Token::OR: |
| + case Token::AND: |
| + // Result type can be either of the two input types. |
| + return operands_type; |
| + case Token::BIT_AND: { |
| + // Anding with positive Smis will give you a Smi. |
| + if (right.is_constant() && right.handle()->IsSmi() && |
| + Smi::cast(*right.handle())->value() >= 0) { |
| + return NumberInfo::Smi(); |
| + } else if (left.is_constant() && left.handle()->IsSmi() && |
| + Smi::cast(*left.handle())->value() >= 0) { |
| + return NumberInfo::Smi(); |
| + } |
| + return (operands_type.IsSmi()) |
| + ? NumberInfo::Smi() |
| + : NumberInfo::Integer32(); |
| + } |
| + case Token::BIT_OR: { |
| + // Oring with negative Smis will give you a Smi. |
| + if (right.is_constant() && right.handle()->IsSmi() && |
| + Smi::cast(*right.handle())->value() < 0) { |
| + return NumberInfo::Smi(); |
| + } else if (left.is_constant() && left.handle()->IsSmi() && |
| + Smi::cast(*left.handle())->value() < 0) { |
| + return NumberInfo::Smi(); |
| + } |
| + return (operands_type.IsSmi()) |
| + ? NumberInfo::Smi() |
| + : NumberInfo::Integer32(); |
| + } |
| + case Token::BIT_XOR: |
| + // Result is always a number. Smi property of inputs is preserved. |
|
fschneider
2010/03/05 15:01:07
// Result is always a integer32.
|
| + return (operands_type.IsSmi()) |
| + ? NumberInfo::Smi() |
| + : NumberInfo::Integer32(); |
| + case Token::SAR: |
| + if (left.is_smi()) return NumberInfo::Smi(); |
| + // Result is a smi if we shift by a constant >= 1, otherwise a number. |
|
fschneider
2010/03/05 15:01:07
number --> integer32
|
| + return (right.is_constant() && right.handle()->IsSmi() |
| + && Smi::cast(*right.handle())->value() >= 1) |
| + ? NumberInfo::Smi() |
| + : NumberInfo::Integer32(); |
| + case Token::SHR: |
| + // Result is a smi if we shift by a constant >= 2, otherwise a number. |
|
fschneider
2010/03/05 15:01:07
number --> integer32
|
| + return (right.is_constant() && right.handle()->IsSmi() |
| + && Smi::cast(*right.handle())->value() >= 2) |
| + ? NumberInfo::Smi() |
| + : NumberInfo::Integer32(); |
| + case Token::ADD: |
| + if (operands_type.IsSmi()) { |
| + // The Integer32 range is big enough to take the sum of any two Smis. |
| + return NumberInfo::Integer32(); |
| + } else { |
| + // Result could be a string or a number. Check types of inputs. |
| + return operands_type.IsNumber() |
| + ? NumberInfo::Number() |
| + : NumberInfo::Unknown(); |
| + } |
| + case Token::SHL: |
| + return NumberInfo::Integer32(); |
| + case Token::SUB: |
| + // The Integer32 range is big enough to take the difference of any two Smis. |
|
fschneider
2010/03/05 15:01:07
long line
|
| + return (operands_type.IsSmi()) ? |
| + NumberInfo::Integer32() : |
| + NumberInfo::Number(); |
| + case Token::MUL: |
| + case Token::DIV: |
| + case Token::MOD: |
| + // Result is always a number. |
| + return NumberInfo::Number(); |
| + default: |
| + UNREACHABLE(); |
| + } |
| + UNREACHABLE(); |
| + return NumberInfo::Unknown(); |
| +} |
| + |
| + |
| void CodeGenerator::GenericBinaryOperation(Token::Value op, |
| StaticType* type, |
| OverwriteMode overwrite_mode) { |
| @@ -1021,9 +1146,11 @@ |
| } |
| // Get number type of left and right sub-expressions. |
| - NumberInfo::Type operands_type = |
| + NumberInfo operands_type = |
| NumberInfo::Combine(left.number_info(), right.number_info()); |
| + NumberInfo result_type = CalculateNumberInfo(operands_type, op, right, left); |
| + |
| Result answer; |
| if (left_is_non_smi_constant || right_is_non_smi_constant) { |
| // Go straight to the slow case, with no smi code. |
| @@ -1044,7 +1171,10 @@ |
| // generate the inline Smi check code if this operation is part of a loop. |
| // For all other operations only inline the Smi check code for likely smis |
| // if the operation is part of a loop. |
| - if (loop_nesting() > 0 && (Token::IsBitOp(op) || type->IsLikelySmi())) { |
| + if (loop_nesting() > 0 && |
| + (Token::IsBitOp(op) || |
| + operands_type.IsInteger32() || |
| + type->IsLikelySmi())) { |
| answer = LikelySmiBinaryOperation(op, &left, &right, overwrite_mode); |
| } else { |
| GenericBinaryOpStub stub(op, |
| @@ -1055,58 +1185,6 @@ |
| } |
| } |
| - // Set NumberInfo of result according to the operation performed. |
| - // Rely on the fact that smis have a 31 bit payload on ia32. |
| - ASSERT(kSmiValueSize == 31); |
| - NumberInfo::Type result_type = NumberInfo::kUnknown; |
| - switch (op) { |
| - case Token::COMMA: |
| - result_type = right.number_info(); |
| - break; |
| - case Token::OR: |
| - case Token::AND: |
| - // Result type can be either of the two input types. |
| - result_type = operands_type; |
| - break; |
| - case Token::BIT_OR: |
| - case Token::BIT_XOR: |
| - case Token::BIT_AND: |
| - // Result is always a number. Smi property of inputs is preserved. |
| - result_type = (operands_type == NumberInfo::kSmi) |
| - ? NumberInfo::kSmi |
| - : NumberInfo::kNumber; |
| - break; |
| - case Token::SAR: |
| - // Result is a smi if we shift by a constant >= 1, otherwise a number. |
| - result_type = (right.is_constant() && right.handle()->IsSmi() |
| - && Smi::cast(*right.handle())->value() >= 1) |
| - ? NumberInfo::kSmi |
| - : NumberInfo::kNumber; |
| - break; |
| - case Token::SHR: |
| - // Result is a smi if we shift by a constant >= 2, otherwise a number. |
| - result_type = (right.is_constant() && right.handle()->IsSmi() |
| - && Smi::cast(*right.handle())->value() >= 2) |
| - ? NumberInfo::kSmi |
| - : NumberInfo::kNumber; |
| - break; |
| - case Token::ADD: |
| - // Result could be a string or a number. Check types of inputs. |
| - result_type = NumberInfo::IsNumber(operands_type) |
| - ? NumberInfo::kNumber |
| - : NumberInfo::kUnknown; |
| - break; |
| - case Token::SHL: |
| - case Token::SUB: |
| - case Token::MUL: |
| - case Token::DIV: |
| - case Token::MOD: |
| - // Result is always a number. |
| - result_type = NumberInfo::kNumber; |
| - break; |
| - default: |
| - UNREACHABLE(); |
| - } |
| answer.set_number_info(result_type); |
| frame_->Push(&answer); |
| } |
| @@ -1193,6 +1271,12 @@ |
| } |
| +static void CheckTwoForSminess(MacroAssembler* masm, |
| + Register left, Register right, Register scratch, |
| + NumberInfo left_info, NumberInfo right_info, |
| + DeferredInlineBinaryOperation* deferred); |
| + |
| + |
| // Implements a binary operation using a deferred code object and some |
| // inline code to operate on smis quickly. |
| Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op, |
| @@ -1273,6 +1357,8 @@ |
| (op == Token::DIV) ? eax : edx, |
| left->reg(), |
| right->reg(), |
| + left->number_info(), |
| + right->number_info(), |
| overwrite_mode); |
| if (left->reg().is(right->reg())) { |
| __ test(left->reg(), Immediate(kSmiTagMask)); |
| @@ -1370,11 +1456,11 @@ |
| answer.reg(), |
| left->reg(), |
| ecx, |
| + left->number_info(), |
| + right->number_info(), |
| overwrite_mode); |
| - __ mov(answer.reg(), left->reg()); |
| - __ or_(answer.reg(), Operand(ecx)); |
| - __ test(answer.reg(), Immediate(kSmiTagMask)); |
| - deferred->Branch(not_zero); |
| + CheckTwoForSminess(masm_, left->reg(), right->reg(), answer.reg(), |
| + left->number_info(), right->number_info(), deferred); |
| // Untag both operands. |
| __ mov(answer.reg(), left->reg()); |
| @@ -1444,16 +1530,12 @@ |
| answer.reg(), |
| left->reg(), |
| right->reg(), |
| + left->number_info(), |
| + right->number_info(), |
| overwrite_mode); |
| - if (left->reg().is(right->reg())) { |
| - __ test(left->reg(), Immediate(kSmiTagMask)); |
| - } else { |
| - __ mov(answer.reg(), left->reg()); |
| - __ or_(answer.reg(), Operand(right->reg())); |
| - ASSERT(kSmiTag == 0); // Adjust test if not the case. |
| - __ test(answer.reg(), Immediate(kSmiTagMask)); |
| - } |
| - deferred->Branch(not_zero); |
| + CheckTwoForSminess(masm_, left->reg(), right->reg(), answer.reg(), |
| + left->number_info(), right->number_info(), deferred); |
| + |
| __ mov(answer.reg(), left->reg()); |
| switch (op) { |
| case Token::ADD: |
| @@ -1522,13 +1604,16 @@ |
| DeferredInlineSmiOperation(Token::Value op, |
| Register dst, |
| Register src, |
| + NumberInfo number_info, |
| Smi* value, |
| OverwriteMode overwrite_mode) |
| : op_(op), |
| dst_(dst), |
| src_(src), |
| + number_info_(number_info), |
| value_(value), |
| overwrite_mode_(overwrite_mode) { |
| + if (number_info.IsSmi()) overwrite_mode_ = NO_OVERWRITE; |
| set_comment("[ DeferredInlineSmiOperation"); |
| } |
| @@ -1538,6 +1623,7 @@ |
| Token::Value op_; |
| Register dst_; |
| Register src_; |
| + NumberInfo number_info_; |
| Smi* value_; |
| OverwriteMode overwrite_mode_; |
| }; |
| @@ -1548,7 +1634,8 @@ |
| GenericBinaryOpStub stub( |
| op_, |
| overwrite_mode_, |
| - (op_ == Token::MOD) ? NO_GENERIC_BINARY_FLAGS : NO_SMI_CODE_IN_STUB); |
| + (op_ == Token::MOD) ? NO_GENERIC_BINARY_FLAGS : NO_SMI_CODE_IN_STUB, |
| + NumberInfo::Combine(NumberInfo::Smi(), number_info_)); |
| stub.GenerateCall(masm_, src_, value_); |
| if (!dst_.is(eax)) __ mov(dst_, eax); |
| } |
| @@ -1562,9 +1649,11 @@ |
| Register dst, |
| Smi* value, |
| Register src, |
| + NumberInfo number_info, |
| OverwriteMode overwrite_mode) |
| : op_(op), |
| dst_(dst), |
| + number_info_(number_info), |
| value_(value), |
| src_(src), |
| overwrite_mode_(overwrite_mode) { |
| @@ -1576,6 +1665,7 @@ |
| private: |
| Token::Value op_; |
| Register dst_; |
| + NumberInfo number_info_; |
| Smi* value_; |
| Register src_; |
| OverwriteMode overwrite_mode_; |
| @@ -1583,7 +1673,11 @@ |
| void DeferredInlineSmiOperationReversed::Generate() { |
| - GenericBinaryOpStub igostub(op_, overwrite_mode_, NO_SMI_CODE_IN_STUB); |
| + GenericBinaryOpStub igostub( |
| + op_, |
| + overwrite_mode_, |
| + NO_SMI_CODE_IN_STUB, |
| + NumberInfo::Combine(NumberInfo::Smi(), number_info_)); |
| igostub.GenerateCall(masm_, value_, src_); |
| if (!dst_.is(eax)) __ mov(dst_, eax); |
| } |
| @@ -1595,9 +1689,14 @@ |
| class DeferredInlineSmiAdd: public DeferredCode { |
| public: |
| DeferredInlineSmiAdd(Register dst, |
| + NumberInfo number_info, |
| Smi* value, |
| OverwriteMode overwrite_mode) |
| - : dst_(dst), value_(value), overwrite_mode_(overwrite_mode) { |
| + : dst_(dst), |
| + number_info_(number_info), |
| + value_(value), |
| + overwrite_mode_(overwrite_mode) { |
| + if (number_info_.IsSmi()) overwrite_mode_ = NO_OVERWRITE; |
| set_comment("[ DeferredInlineSmiAdd"); |
| } |
| @@ -1605,6 +1704,7 @@ |
| private: |
| Register dst_; |
| + NumberInfo number_info_; |
| Smi* value_; |
| OverwriteMode overwrite_mode_; |
| }; |
| @@ -1613,7 +1713,11 @@ |
| void DeferredInlineSmiAdd::Generate() { |
| // Undo the optimistic add operation and call the shared stub. |
| __ sub(Operand(dst_), Immediate(value_)); |
| - GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, NO_SMI_CODE_IN_STUB); |
| + GenericBinaryOpStub igostub( |
| + Token::ADD, |
| + overwrite_mode_, |
| + NO_SMI_CODE_IN_STUB, |
| + NumberInfo::Combine(NumberInfo::Smi(), number_info_)); |
| igostub.GenerateCall(masm_, dst_, value_); |
| if (!dst_.is(eax)) __ mov(dst_, eax); |
| } |
| @@ -1625,9 +1729,13 @@ |
| class DeferredInlineSmiAddReversed: public DeferredCode { |
| public: |
| DeferredInlineSmiAddReversed(Register dst, |
| + NumberInfo number_info, |
| Smi* value, |
| OverwriteMode overwrite_mode) |
| - : dst_(dst), value_(value), overwrite_mode_(overwrite_mode) { |
| + : dst_(dst), |
| + number_info_(number_info), |
| + value_(value), |
| + overwrite_mode_(overwrite_mode) { |
| set_comment("[ DeferredInlineSmiAddReversed"); |
| } |
| @@ -1635,6 +1743,7 @@ |
| private: |
| Register dst_; |
| + NumberInfo number_info_; |
| Smi* value_; |
| OverwriteMode overwrite_mode_; |
| }; |
| @@ -1643,7 +1752,10 @@ |
| void DeferredInlineSmiAddReversed::Generate() { |
| // Undo the optimistic add operation and call the shared stub. |
| __ sub(Operand(dst_), Immediate(value_)); |
| - GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, NO_SMI_CODE_IN_STUB); |
| + GenericBinaryOpStub igostub(Token::ADD, |
| + overwrite_mode_, |
| + NO_SMI_CODE_IN_STUB, |
| + NumberInfo::Combine(NumberInfo::Smi(), number_info_)); |
| igostub.GenerateCall(masm_, value_, dst_); |
| if (!dst_.is(eax)) __ mov(dst_, eax); |
| } |
| @@ -1656,9 +1768,14 @@ |
| class DeferredInlineSmiSub: public DeferredCode { |
| public: |
| DeferredInlineSmiSub(Register dst, |
| + NumberInfo number_info, |
| Smi* value, |
| OverwriteMode overwrite_mode) |
| - : dst_(dst), value_(value), overwrite_mode_(overwrite_mode) { |
| + : dst_(dst), |
| + number_info_(number_info), |
| + value_(value), |
| + overwrite_mode_(overwrite_mode) { |
| + if (number_info.IsSmi()) overwrite_mode_ = NO_OVERWRITE; |
| set_comment("[ DeferredInlineSmiSub"); |
| } |
| @@ -1666,6 +1783,7 @@ |
| private: |
| Register dst_; |
| + NumberInfo number_info_; |
| Smi* value_; |
| OverwriteMode overwrite_mode_; |
| }; |
| @@ -1674,7 +1792,10 @@ |
| void DeferredInlineSmiSub::Generate() { |
| // Undo the optimistic sub operation and call the shared stub. |
| __ add(Operand(dst_), Immediate(value_)); |
| - GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, NO_SMI_CODE_IN_STUB); |
| + GenericBinaryOpStub igostub(Token::SUB, |
| + overwrite_mode_, |
| + NO_SMI_CODE_IN_STUB, |
| + NumberInfo::Combine(NumberInfo::Smi(), number_info_)); |
| igostub.GenerateCall(masm_, dst_, value_); |
| if (!dst_.is(eax)) __ mov(dst_, eax); |
| } |
| @@ -1718,17 +1839,21 @@ |
| DeferredCode* deferred = NULL; |
| if (reversed) { |
| deferred = new DeferredInlineSmiAddReversed(operand->reg(), |
| + operand->number_info(), |
| smi_value, |
| overwrite_mode); |
| } else { |
| deferred = new DeferredInlineSmiAdd(operand->reg(), |
| + operand->number_info(), |
| smi_value, |
| overwrite_mode); |
| } |
| __ add(Operand(operand->reg()), Immediate(value)); |
| deferred->Branch(overflow); |
| - __ test(operand->reg(), Immediate(kSmiTagMask)); |
| - deferred->Branch(not_zero); |
| + if (!operand->number_info().IsSmi()) { |
| + __ test(operand->reg(), Immediate(kSmiTagMask)); |
| + deferred->Branch(not_zero); |
| + } |
| deferred->BindExit(); |
| answer = *operand; |
| break; |
| @@ -1747,6 +1872,7 @@ |
| answer.reg(), |
| smi_value, |
| operand->reg(), |
| + operand->number_info(), |
|
fschneider
2010/03/05 15:01:07
long line?
|
| overwrite_mode); |
| __ sub(answer.reg(), Operand(operand->reg())); |
| } else { |
| @@ -1754,13 +1880,16 @@ |
| frame_->Spill(operand->reg()); |
| answer = *operand; |
| deferred = new DeferredInlineSmiSub(operand->reg(), |
| + operand->number_info(), |
| smi_value, |
| overwrite_mode); |
| __ sub(Operand(operand->reg()), Immediate(value)); |
| } |
| deferred->Branch(overflow); |
| - __ test(answer.reg(), Immediate(kSmiTagMask)); |
| - deferred->Branch(not_zero); |
| + if (!operand->number_info().IsSmi()) { |
| + __ test(answer.reg(), Immediate(kSmiTagMask)); |
| + deferred->Branch(not_zero); |
| + } |
| deferred->BindExit(); |
| operand->Unuse(); |
| break; |
| @@ -1781,10 +1910,13 @@ |
| new DeferredInlineSmiOperation(op, |
| operand->reg(), |
| operand->reg(), |
| + operand->number_info(), |
|
fschneider
2010/03/05 15:01:07
You could avoid creating the DeferredInlineSmiOper
|
| smi_value, |
| overwrite_mode); |
| - __ test(operand->reg(), Immediate(kSmiTagMask)); |
| - deferred->Branch(not_zero); |
| + if (!operand->number_info().IsSmi()) { |
| + __ test(operand->reg(), Immediate(kSmiTagMask)); |
| + deferred->Branch(not_zero); |
| + } |
| if (shift_value > 0) { |
| __ sar(operand->reg(), shift_value); |
| __ and_(operand->reg(), ~kSmiTagMask); |
| @@ -1810,10 +1942,13 @@ |
| new DeferredInlineSmiOperation(op, |
| answer.reg(), |
| operand->reg(), |
| + operand->number_info(), |
| smi_value, |
| overwrite_mode); |
| - __ test(operand->reg(), Immediate(kSmiTagMask)); |
| - deferred->Branch(not_zero); |
| + if (!operand->number_info().IsSmi()) { |
| + __ test(operand->reg(), Immediate(kSmiTagMask)); |
| + deferred->Branch(not_zero); |
| + } |
| __ mov(answer.reg(), operand->reg()); |
| __ SmiUntag(answer.reg()); |
| __ shr(answer.reg(), shift_value); |
| @@ -1855,10 +1990,13 @@ |
| answer.reg(), |
| smi_value, |
| right.reg(), |
| + right.number_info(), |
| overwrite_mode); |
| __ mov(answer.reg(), Immediate(int_value)); |
| __ sar(ecx, kSmiTagSize); |
| - deferred->Branch(carry); |
| + if (!right.number_info().IsSmi()) { |
| + deferred->Branch(carry); |
| + } |
| __ shl_cl(answer.reg()); |
| __ cmp(answer.reg(), 0xc0000000); |
| deferred->Branch(sign); |
| @@ -1877,10 +2015,13 @@ |
| new DeferredInlineSmiOperation(op, |
| operand->reg(), |
| operand->reg(), |
| + operand->number_info(), |
| smi_value, |
| overwrite_mode); |
| - __ test(operand->reg(), Immediate(kSmiTagMask)); |
| - deferred->Branch(not_zero); |
| + if (!operand->number_info().IsSmi()) { |
|
fschneider
2010/03/05 15:01:07
Also here only instantiate DeferredInlineSmiOperat
|
| + __ test(operand->reg(), Immediate(kSmiTagMask)); |
| + deferred->Branch(not_zero); |
| + } |
| deferred->BindExit(); |
| answer = *operand; |
| } else { |
| @@ -1891,10 +2032,13 @@ |
| new DeferredInlineSmiOperation(op, |
| answer.reg(), |
| operand->reg(), |
| + operand->number_info(), |
| smi_value, |
| overwrite_mode); |
| - __ test(operand->reg(), Immediate(kSmiTagMask)); |
| - deferred->Branch(not_zero); |
| + if (!operand->number_info().IsSmi()) { |
| + __ test(operand->reg(), Immediate(kSmiTagMask)); |
| + deferred->Branch(not_zero); |
| + } |
| __ mov(answer.reg(), operand->reg()); |
| ASSERT(kSmiTag == 0); // adjust code if not the case |
| // We do no shifts, only the Smi conversion, if shift_value is 1. |
| @@ -1922,16 +2066,20 @@ |
| operand->reg(), |
| smi_value, |
| operand->reg(), |
| + operand->number_info(), |
|
fschneider
2010/03/05 15:01:07
long line.
|
| overwrite_mode); |
| } else { |
| deferred = new DeferredInlineSmiOperation(op, |
| operand->reg(), |
| operand->reg(), |
| + operand->number_info(), |
| smi_value, |
| overwrite_mode); |
| } |
| - __ test(operand->reg(), Immediate(kSmiTagMask)); |
| - deferred->Branch(not_zero); |
| + if (!operand->number_info().IsSmi()) { |
|
fschneider
2010/03/05 15:01:07
Also here only instantiate DeferredInlineSmiOperat
Erik Corry
2010/03/05 20:20:15
Actually instead I will remove the 'if' since shif
|
| + __ test(operand->reg(), Immediate(kSmiTagMask)); |
| + deferred->Branch(not_zero); |
| + } |
| if (op == Token::BIT_AND) { |
| __ and_(Operand(operand->reg()), Immediate(value)); |
| } else if (op == Token::BIT_XOR) { |
| @@ -1958,6 +2106,7 @@ |
| new DeferredInlineSmiOperation(op, |
| operand->reg(), |
| operand->reg(), |
| + operand->number_info(), |
| smi_value, |
| overwrite_mode); |
| // Check that lowest log2(value) bits of operand are zero, and test |
| @@ -1992,6 +2141,7 @@ |
| DeferredCode* deferred = new DeferredInlineSmiOperation(op, |
| operand->reg(), |
| operand->reg(), |
| + operand->number_info(), |
|
fschneider
2010/03/05 15:01:07
Long line.
|
| smi_value, |
| overwrite_mode); |
| // Check for negative or non-Smi left hand side. |
| @@ -2027,6 +2177,8 @@ |
| static bool CouldBeNaN(const Result& result) { |
| + if (result.number_info().IsSmi()) return false; |
| + if (result.number_info().IsInteger32()) return false; |
| if (!result.is_constant()) return true; |
| if (!result.handle()->IsHeapNumber()) return false; |
| return isnan(HeapNumber::cast(*result.handle())->value()); |
| @@ -7130,8 +7282,10 @@ |
| deferred->Branch(not_equal); |
| // Check that the key is a smi. |
| - __ test(key.reg(), Immediate(kSmiTagMask)); |
| - deferred->Branch(not_zero); |
| + if (!key.is_smi()) { |
| + __ test(key.reg(), Immediate(kSmiTagMask)); |
| + deferred->Branch(not_zero); |
| + } |
| // Get the elements array from the receiver and check that it |
| // is not a dictionary. |
| @@ -7276,6 +7430,34 @@ |
| #define __ ACCESS_MASM(masm) |
| +static void CheckTwoForSminess(MacroAssembler* masm, |
| + Register left, Register right, Register scratch, |
| + NumberInfo left_info, NumberInfo right_info, |
| + DeferredInlineBinaryOperation* deferred) { |
| + if (left.is(right)) { |
| + if (!left_info.IsSmi()) { |
| + __ test(left, Immediate(kSmiTagMask)); |
| + deferred->Branch(not_zero); |
| + } |
| + } 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); |
| + } |
| + } else { |
| + if (!right_info.IsSmi()) { |
| + __ test(right, Immediate(kSmiTagMask)); |
| + deferred->Branch(not_zero); |
| + } |
| + } |
| +} |
| + |
| + |
| Handle<String> Reference::GetName() { |
| ASSERT(type_ == NAMED); |
| Property* property = expression_->AsProperty(); |
| @@ -7776,6 +7958,22 @@ |
| __ mov(left, Operand(esp, 2 * kPointerSize)); |
| } |
| + if (static_operands_type_.IsSmi()) { |
| + if (op_ == Token::BIT_OR) { |
| + __ or_(right, Operand(left)); |
| + GenerateReturn(masm); |
| + return; |
| + } else if (op_ == Token::BIT_AND) { |
| + __ and_(right, Operand(left)); |
| + GenerateReturn(masm); |
| + return; |
| + } else if (op_ == Token::BIT_XOR) { |
| + __ xor_(right, Operand(left)); |
| + GenerateReturn(masm); |
| + return; |
| + } |
| + } |
| + |
| // 2. Prepare the smi check of both operands by oring them together. |
| Comment smi_check_comment(masm, "-- Smi check arguments"); |
| Label not_smis; |
| @@ -8112,7 +8310,7 @@ |
| Label not_floats; |
| if (CpuFeatures::IsSupported(SSE2)) { |
| CpuFeatures::Scope use_sse2(SSE2); |
| - if (NumberInfo::IsNumber(static_operands_type_)) { |
| + if (static_operands_type_.IsNumber()) { |
| if (FLAG_debug_code) { |
| // Assert at runtime that inputs are only numbers. |
| __ AbortIfNotNumber(edx, |
| @@ -8120,7 +8318,11 @@ |
| __ AbortIfNotNumber(eax, |
| "GenericBinaryOpStub operand not a number."); |
| } |
| - FloatingPointHelper::LoadSSE2Operands(masm); |
| + if (static_operands_type_.IsSmi()) { |
| + FloatingPointHelper::LoadSSE2Smis(masm, ecx); |
| + } else { |
| + FloatingPointHelper::LoadSSE2Operands(masm); |
| + } |
| } else { |
| FloatingPointHelper::LoadSSE2Operands(masm, &call_runtime); |
| } |
| @@ -8136,7 +8338,7 @@ |
| __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
| GenerateReturn(masm); |
| } else { // SSE2 not available, use FPU. |
| - if (NumberInfo::IsNumber(static_operands_type_)) { |
| + if (static_operands_type_.IsNumber()) { |
| if (FLAG_debug_code) { |
| // Assert at runtime that inputs are only numbers. |
| __ AbortIfNotNumber(edx, |
| @@ -8190,7 +8392,10 @@ |
| case Token::SHL: |
| case Token::SHR: { |
| Label non_smi_result; |
| - FloatingPointHelper::LoadAsIntegers(masm, use_sse3_, &call_runtime); |
| + FloatingPointHelper::LoadAsIntegers(masm, |
| + static_operands_type_, |
| + use_sse3_, |
| + &call_runtime); |
| switch (op_) { |
| case Token::BIT_OR: __ or_(eax, Operand(ecx)); break; |
| case Token::BIT_AND: __ and_(eax, Operand(ecx)); break; |
| @@ -8719,24 +8924,29 @@ |
| // trashed registers. |
| void IntegerConvert(MacroAssembler* masm, |
| Register source, |
| + NumberInfo number_info, |
| bool use_sse3, |
| Label* conversion_failure) { |
| ASSERT(!source.is(ecx) && !source.is(edi) && !source.is(ebx)); |
| Label done, right_exponent, normal_exponent; |
| Register scratch = ebx; |
| Register scratch2 = edi; |
| - // Get exponent word. |
| - __ mov(scratch, FieldOperand(source, HeapNumber::kExponentOffset)); |
| - // Get exponent alone in scratch2. |
| - __ mov(scratch2, scratch); |
| - __ and_(scratch2, HeapNumber::kExponentMask); |
| + if (!number_info.IsInteger32() || !use_sse3) { |
| + // Get exponent word. |
| + __ mov(scratch, FieldOperand(source, HeapNumber::kExponentOffset)); |
| + // Get exponent alone in scratch2. |
| + __ mov(scratch2, scratch); |
| + __ and_(scratch2, HeapNumber::kExponentMask); |
| + } |
| if (use_sse3) { |
| CpuFeatures::Scope scope(SSE3); |
| - // Check whether the exponent is too big for a 64 bit signed integer. |
| - static const uint32_t kTooBigExponent = |
| - (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; |
| - __ cmp(Operand(scratch2), Immediate(kTooBigExponent)); |
| - __ j(greater_equal, conversion_failure); |
| + if (!number_info.IsInteger32()) { |
| + // Check whether the exponent is too big for a 64 bit signed integer. |
| + static const uint32_t kTooBigExponent = |
| + (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; |
| + __ cmp(Operand(scratch2), Immediate(kTooBigExponent)); |
| + __ j(greater_equal, conversion_failure); |
| + } |
| // Load x87 register with heap number. |
| __ fld_d(FieldOperand(source, HeapNumber::kValueOffset)); |
| // Reserve space for 64 bit answer. |
| @@ -8851,6 +9061,7 @@ |
| // Input: edx, eax are the left and right objects of a bit op. |
| // Output: eax, ecx are left and right integers for a bit op. |
| void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm, |
| + NumberInfo number_info, |
| bool use_sse3, |
| Label* conversion_failure) { |
| // Check float operands. |
| @@ -8858,48 +9069,68 @@ |
| Label arg2_is_object, check_undefined_arg2; |
| Label load_arg2, done; |
| - __ test(edx, Immediate(kSmiTagMask)); |
| - __ j(not_zero, &arg1_is_object); |
| - __ SmiUntag(edx); |
| - __ jmp(&load_arg2); |
| + if (number_info.IsHeapNumber()) { |
|
fschneider
2010/03/05 15:01:07
This function is getting quite messy with all the
|
| + __ jmp (&arg1_is_object); |
|
fschneider
2010/03/05 15:01:07
Remove extra space.
|
| + } else { |
| + if (!number_info.IsSmi()) { |
| + __ test(edx, Immediate(kSmiTagMask)); |
| + __ j(not_zero, &arg1_is_object); |
| + } |
| + __ SmiUntag(edx); |
| + __ jmp(&load_arg2); |
| + } |
| // If the argument is undefined it converts to zero (ECMA-262, section 9.5). |
| - __ bind(&check_undefined_arg1); |
| - __ cmp(edx, Factory::undefined_value()); |
| - __ j(not_equal, conversion_failure); |
| - __ mov(edx, Immediate(0)); |
| - __ jmp(&load_arg2); |
| + if (!number_info.IsNumber()) { |
| + __ bind(&check_undefined_arg1); |
| + __ cmp(edx, Factory::undefined_value()); |
| + __ j(not_equal, conversion_failure); |
| + __ mov(edx, Immediate(0)); |
| + __ jmp(&load_arg2); |
| + } |
| __ bind(&arg1_is_object); |
| - __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); |
| - __ cmp(ebx, Factory::heap_number_map()); |
| - __ j(not_equal, &check_undefined_arg1); |
| + if (!number_info.IsNumber()) { |
| + __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); |
| + __ cmp(ebx, Factory::heap_number_map()); |
| + __ j(not_equal, &check_undefined_arg1); |
| + } |
| // Get the untagged integer version of the edx heap number in ecx. |
| - IntegerConvert(masm, edx, use_sse3, conversion_failure); |
| + IntegerConvert(masm, edx, number_info, use_sse3, conversion_failure); |
| __ mov(edx, ecx); |
| // Here edx has the untagged integer, eax has a Smi or a heap number. |
| __ bind(&load_arg2); |
| - // Test if arg2 is a Smi. |
| - __ test(eax, Immediate(kSmiTagMask)); |
| - __ j(not_zero, &arg2_is_object); |
| - __ SmiUntag(eax); |
| - __ mov(ecx, eax); |
| - __ jmp(&done); |
| + if (number_info.IsHeapNumber()) { |
| + __ jmp(&arg2_is_object); |
| + } else { |
| + // Test if arg2 is a Smi. |
| + if (!number_info.IsSmi()) { |
| + __ test(eax, Immediate(kSmiTagMask)); |
| + __ j(not_zero, &arg2_is_object); |
| + } |
| + __ SmiUntag(eax); |
| + __ mov(ecx, eax); |
| + __ jmp(&done); |
| + } |
| // If the argument is undefined it converts to zero (ECMA-262, section 9.5). |
| - __ bind(&check_undefined_arg2); |
| - __ cmp(eax, Factory::undefined_value()); |
| - __ j(not_equal, conversion_failure); |
| - __ mov(ecx, Immediate(0)); |
| - __ jmp(&done); |
| + if (!number_info.IsNumber()) { |
| + __ bind(&check_undefined_arg2); |
| + __ cmp(eax, Factory::undefined_value()); |
| + __ j(not_equal, conversion_failure); |
| + __ mov(ecx, Immediate(0)); |
| + __ jmp(&done); |
| + } |
| __ bind(&arg2_is_object); |
| - __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| - __ cmp(ebx, Factory::heap_number_map()); |
| - __ j(not_equal, &check_undefined_arg2); |
| + if (!number_info.IsNumber()) { |
| + __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| + __ cmp(ebx, Factory::heap_number_map()); |
| + __ j(not_equal, &check_undefined_arg2); |
| + } |
| // Get the untagged integer version of the eax heap number in ecx. |
| - IntegerConvert(masm, eax, use_sse3, conversion_failure); |
| + IntegerConvert(masm, eax, number_info, use_sse3, conversion_failure); |
| __ bind(&done); |
| __ mov(eax, edx); |
| } |
| @@ -9141,7 +9372,11 @@ |
| __ j(not_equal, &slow, not_taken); |
| // Convert the heap number in eax to an untagged integer in ecx. |
| - IntegerConvert(masm, eax, CpuFeatures::IsSupported(SSE3), &slow); |
| + IntegerConvert(masm, |
| + eax, |
| + NumberInfo::Unknown(), |
| + CpuFeatures::IsSupported(SSE3), |
| + &slow); |
| // Do the bitwise operation and check if the result fits in a smi. |
| Label try_float; |