From 00a44ae51ad077de82c160416ebfdb2cb76aa9c5 Mon Sep 17 00:00:00 2001 From: "erik.corry@gmail.com" Date: Fri, 5 Mar 2010 23:54:13 +0000 Subject: [PATCH] Make more use of the NumberInfo data. Makes NumberInfo into a real class. Fix bug where NumberInfo was lost in ToRegister. Allow 17 bits in safe Smis instead of 16. Review URL: http://codereview.chromium.org/668151 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4046 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/virtual-frame-arm.cc | 2 +- src/arm/virtual-frame-arm.h | 4 +- src/frame-element.h | 32 +- src/ia32/codegen-ia32.cc | 637 ++++++++++++++++++++-------- src/ia32/codegen-ia32.h | 21 +- src/ia32/full-codegen-ia32.cc | 6 +- src/ia32/register-allocator-ia32.cc | 1 + src/ia32/virtual-frame-ia32.cc | 14 +- src/ia32/virtual-frame-ia32.h | 10 +- src/jump-target-inl.h | 2 +- src/jump-target.cc | 13 +- src/number-info.h | 160 ++++++- src/register-allocator-inl.h | 39 ++ src/register-allocator.cc | 21 +- src/register-allocator.h | 21 +- src/virtual-frame-inl.h | 4 +- src/virtual-frame.cc | 18 +- src/x64/codegen-x64.cc | 24 +- src/x64/codegen-x64.h | 10 +- src/x64/virtual-frame-x64.cc | 24 +- src/x64/virtual-frame-x64.h | 12 +- 21 files changed, 764 insertions(+), 311 deletions(-) diff --git a/src/arm/virtual-frame-arm.cc b/src/arm/virtual-frame-arm.cc index bc9da8427..ab6e5f813 100644 --- a/src/arm/virtual-frame-arm.cc +++ b/src/arm/virtual-frame-arm.cc @@ -295,7 +295,7 @@ void VirtualFrame::EmitPop(Register reg) { void VirtualFrame::EmitPush(Register reg) { ASSERT(stack_pointer_ == element_count() - 1); - elements_.Add(FrameElement::MemoryElement(NumberInfo::kUnknown)); + elements_.Add(FrameElement::MemoryElement(NumberInfo::Unknown())); stack_pointer_++; __ push(reg); } diff --git a/src/arm/virtual-frame-arm.h b/src/arm/virtual-frame-arm.h index b41cd74bc..6eb08119e 100644 --- a/src/arm/virtual-frame-arm.h +++ b/src/arm/virtual-frame-arm.h @@ -69,7 +69,7 @@ class VirtualFrame : public ZoneObject { // Create a duplicate of an existing valid frame element. FrameElement CopyElementAt(int index, - NumberInfo::Type info = NumberInfo::kUnknown); + NumberInfo info = NumberInfo::Unknown()); // The number of elements on the virtual frame. int element_count() { return elements_.length(); } @@ -344,7 +344,7 @@ class VirtualFrame : public ZoneObject { void EmitPushMultiple(int count, int src_regs); // Push an element on the virtual frame. - inline void Push(Register reg, NumberInfo::Type info = NumberInfo::kUnknown); + inline void Push(Register reg, NumberInfo info = NumberInfo::Unknown()); inline void Push(Handle value); inline void Push(Smi* value); diff --git a/src/frame-element.h b/src/frame-element.h index 5762814ff..af53b17b2 100644 --- a/src/frame-element.h +++ b/src/frame-element.h @@ -53,23 +53,25 @@ class FrameElement BASE_EMBEDDED { SYNCED }; - inline NumberInfo::Type number_info() { + inline NumberInfo number_info() { // Copied elements do not have number info. Instead // we have to inspect their backing element in the frame. ASSERT(!is_copy()); - if (!is_constant()) return NumberInfoField::decode(value_); + if (!is_constant()) { + return NumberInfo::FromInt(NumberInfoField::decode(value_)); + } Handle value = handle(); - if (value->IsSmi()) return NumberInfo::kSmi; - if (value->IsHeapNumber()) return NumberInfo::kHeapNumber; - return NumberInfo::kUnknown; + if (value->IsSmi()) return NumberInfo::Smi(); + if (value->IsHeapNumber()) return NumberInfo::HeapNumber(); + return NumberInfo::Unknown(); } - inline void set_number_info(NumberInfo::Type info) { + inline void set_number_info(NumberInfo info) { // Copied elements do not have number info. Instead // we have to inspect their backing element in the frame. ASSERT(!is_copy()); value_ = value_ & ~NumberInfoField::mask(); - value_ = value_ | NumberInfoField::encode(info); + value_ = value_ | NumberInfoField::encode(info.ToInt()); } // The default constructor creates an invalid frame element. @@ -77,7 +79,7 @@ class FrameElement BASE_EMBEDDED { value_ = TypeField::encode(INVALID) | CopiedField::encode(false) | SyncedField::encode(false) - | NumberInfoField::encode(NumberInfo::kUninitialized) + | NumberInfoField::encode(NumberInfo::Uninitialized().ToInt()) | DataField::encode(0); } @@ -88,7 +90,7 @@ class FrameElement BASE_EMBEDDED { } // Factory function to construct an in-memory frame element. - static FrameElement MemoryElement(NumberInfo::Type info) { + static FrameElement MemoryElement(NumberInfo info) { FrameElement result(MEMORY, no_reg, SYNCED, info); return result; } @@ -96,7 +98,7 @@ class FrameElement BASE_EMBEDDED { // Factory function to construct an in-register frame element. static FrameElement RegisterElement(Register reg, SyncFlag is_synced, - NumberInfo::Type info) { + NumberInfo info) { return FrameElement(REGISTER, reg, is_synced, info); } @@ -210,11 +212,11 @@ class FrameElement BASE_EMBEDDED { FrameElement(Type type, Register reg, SyncFlag is_synced, - NumberInfo::Type info) { + NumberInfo info) { value_ = TypeField::encode(type) | CopiedField::encode(false) | SyncedField::encode(is_synced != NOT_SYNCED) - | NumberInfoField::encode(info) + | NumberInfoField::encode(info.ToInt()) | DataField::encode(reg.code_ > 0 ? reg.code_ : 0); } @@ -223,7 +225,7 @@ class FrameElement BASE_EMBEDDED { value_ = TypeField::encode(CONSTANT) | CopiedField::encode(false) | SyncedField::encode(is_synced != NOT_SYNCED) - | NumberInfoField::encode(NumberInfo::kUninitialized) + | NumberInfoField::encode(NumberInfo::Uninitialized().ToInt()) | DataField::encode(ConstantList()->length()); ConstantList()->Add(value); } @@ -252,8 +254,8 @@ class FrameElement BASE_EMBEDDED { class TypeField: public BitField {}; class CopiedField: public BitField {}; class SyncedField: public BitField {}; - class NumberInfoField: public BitField {}; - class DataField: public BitField {}; + class NumberInfoField: public BitField {}; + class DataField: public BitField {}; friend class VirtualFrame; }; diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc index b611cd07d..dfb5cd779 100644 --- a/src/ia32/codegen-ia32.cc +++ b/src/ia32/codegen-ia32.cc @@ -733,7 +733,27 @@ void CodeGenerator::ToBoolean(ControlDestination* dest) { 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,8 +837,17 @@ class FloatingPointHelper : public AllStatic { // 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); + static void LoadNumbersAsIntegers(MacroAssembler* masm, + NumberInfo number_info, + bool use_sse3, + Label* operand_conversion_failure); + static void LoadUnknownsAsIntegers(MacroAssembler* masm, + bool use_sse3, + Label* operand_conversion_failure); + // Test if operands are smis or heap numbers and load them // into xmm0 and xmm1 if they are. Operands are in edx and eax. // Leaves operands unchanged. @@ -856,7 +885,7 @@ const char* GenericBinaryOpStub::GetName() { (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 +898,11 @@ class DeferredInlineBinaryOperation: public DeferredCode { 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 +913,8 @@ class DeferredInlineBinaryOperation: public DeferredCode { Register dst_; Register left_; Register right_; + NumberInfo left_info_; + NumberInfo right_info_; OverwriteMode mode_; }; @@ -894,18 +928,22 @@ void DeferredInlineBinaryOperation::Generate() { 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_); - } - __ jmp(&load_right); + 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); + __ bind(&left_smi); + } __ SmiUntag(left_); __ cvtsi2sd(xmm0, Operand(left_)); __ SmiTag(left_); @@ -917,23 +955,27 @@ void DeferredInlineBinaryOperation::Generate() { } __ 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_); - } - __ jmp(&do_op); + 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); + __ bind(&right_smi); + } __ SmiUntag(right_); __ cvtsi2sd(xmm1, Operand(right_)); __ SmiTag(right_); @@ -959,13 +1001,105 @@ void DeferredInlineBinaryOperation::Generate() { __ 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 32 bit integer. Smi property of inputs is preserved. + 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 an 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 an 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. + 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 +1155,11 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op, } // 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 +1180,10 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op, // 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 +1194,6 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op, } } - // 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 +1280,12 @@ bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) { } +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 +1366,8 @@ Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op, (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 +1465,11 @@ Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op, 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 +1539,12 @@ Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op, 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 +1613,16 @@ class DeferredInlineSmiOperation: public DeferredCode { 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 +1632,7 @@ class DeferredInlineSmiOperation: public DeferredCode { Token::Value op_; Register dst_; Register src_; + NumberInfo number_info_; Smi* value_; OverwriteMode overwrite_mode_; }; @@ -1548,7 +1643,8 @@ void DeferredInlineSmiOperation::Generate() { 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 +1658,11 @@ class DeferredInlineSmiOperationReversed: public DeferredCode { 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 +1674,7 @@ class DeferredInlineSmiOperationReversed: public DeferredCode { private: Token::Value op_; Register dst_; + NumberInfo number_info_; Smi* value_; Register src_; OverwriteMode overwrite_mode_; @@ -1583,7 +1682,11 @@ class DeferredInlineSmiOperationReversed: public DeferredCode { 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 +1698,14 @@ void DeferredInlineSmiOperationReversed::Generate() { 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 +1713,7 @@ class DeferredInlineSmiAdd: public DeferredCode { private: Register dst_; + NumberInfo number_info_; Smi* value_; OverwriteMode overwrite_mode_; }; @@ -1613,7 +1722,11 @@ class DeferredInlineSmiAdd: public DeferredCode { 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 +1738,13 @@ void DeferredInlineSmiAdd::Generate() { 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 +1752,7 @@ class DeferredInlineSmiAddReversed: public DeferredCode { private: Register dst_; + NumberInfo number_info_; Smi* value_; OverwriteMode overwrite_mode_; }; @@ -1643,7 +1761,11 @@ class DeferredInlineSmiAddReversed: public DeferredCode { 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 +1778,14 @@ void DeferredInlineSmiAddReversed::Generate() { 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 +1793,7 @@ class DeferredInlineSmiSub: public DeferredCode { private: Register dst_; + NumberInfo number_info_; Smi* value_; OverwriteMode overwrite_mode_; }; @@ -1674,7 +1802,11 @@ class DeferredInlineSmiSub: public DeferredCode { 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 +1850,21 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, 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; @@ -1743,24 +1879,29 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, answer = allocator()->Allocate(); ASSERT(answer.is_valid()); __ Set(answer.reg(), Immediate(value)); - deferred = new DeferredInlineSmiOperationReversed(op, - answer.reg(), - smi_value, - operand->reg(), - overwrite_mode); + deferred = + new DeferredInlineSmiOperationReversed(op, + answer.reg(), + smi_value, + operand->reg(), + operand->number_info(), + overwrite_mode); __ sub(answer.reg(), Operand(operand->reg())); } else { operand->ToRegister(); 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; @@ -1777,19 +1918,27 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, int shift_value = int_value & 0x1f; operand->ToRegister(); frame_->Spill(operand->reg()); - DeferredInlineSmiOperation* deferred = - new DeferredInlineSmiOperation(op, - operand->reg(), - operand->reg(), - smi_value, - overwrite_mode); - __ test(operand->reg(), Immediate(kSmiTagMask)); - deferred->Branch(not_zero); - if (shift_value > 0) { - __ sar(operand->reg(), shift_value); - __ and_(operand->reg(), ~kSmiTagMask); + if (!operand->number_info().IsSmi()) { + DeferredInlineSmiOperation* 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 (shift_value > 0) { + __ sar(operand->reg(), shift_value); + __ and_(operand->reg(), ~kSmiTagMask); + } + deferred->BindExit(); + } else { + if (shift_value > 0) { + __ sar(operand->reg(), shift_value); + __ and_(operand->reg(), ~kSmiTagMask); + } } - deferred->BindExit(); answer = *operand; } break; @@ -1810,10 +1959,13 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, 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 +2007,13 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, 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,6 +2032,7 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, new DeferredInlineSmiOperation(op, operand->reg(), operand->reg(), + operand->number_info(), smi_value, overwrite_mode); __ test(operand->reg(), Immediate(kSmiTagMask)); @@ -1891,10 +2047,13 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, 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. @@ -1918,20 +2077,25 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, frame_->Spill(operand->reg()); DeferredCode* deferred = NULL; if (reversed) { - deferred = new DeferredInlineSmiOperationReversed(op, - operand->reg(), - smi_value, - operand->reg(), - overwrite_mode); + deferred = + new DeferredInlineSmiOperationReversed(op, + operand->reg(), + smi_value, + operand->reg(), + operand->number_info(), + 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()) { + __ 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 +2122,7 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, 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 @@ -1989,11 +2154,13 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, (IsPowerOf2(int_value) || IsPowerOf2(-int_value))) { operand->ToRegister(); frame_->Spill(operand->reg()); - DeferredCode* deferred = new DeferredInlineSmiOperation(op, - operand->reg(), - operand->reg(), - smi_value, - overwrite_mode); + DeferredCode* deferred = + new DeferredInlineSmiOperation(op, + operand->reg(), + operand->reg(), + operand->number_info(), + smi_value, + overwrite_mode); // Check for negative or non-Smi left hand side. __ test(operand->reg(), Immediate(kSmiTagMask | 0x80000000)); deferred->Branch(not_zero); @@ -2027,6 +2194,8 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, 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 +7299,10 @@ Result CodeGenerator::EmitKeyedLoad() { 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 +7447,34 @@ Result CodeGenerator::EmitKeyedStore(StaticType* key_type) { #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 Reference::GetName() { ASSERT(type_ == NAMED); Property* property = expression_->AsProperty(); @@ -7776,6 +7975,22 @@ void GenericBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, Label* slow) { __ 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 +8327,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) { 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 +8335,11 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) { __ 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 +8355,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) { __ 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 +8409,10 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) { 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 +8941,29 @@ void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm) { // 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. @@ -8850,16 +9077,66 @@ void IntegerConvert(MacroAssembler* masm, // 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, - bool use_sse3, - Label* conversion_failure) { +void FloatingPointHelper::LoadNumbersAsIntegers(MacroAssembler* masm, + NumberInfo number_info, + bool use_sse3, + Label* conversion_failure) { // Check float operands. Label arg1_is_object, check_undefined_arg1; Label arg2_is_object, check_undefined_arg2; Label load_arg2, done; + if (!number_info.IsHeapNumber()) { + if (!number_info.IsSmi()) { + __ test(edx, Immediate(kSmiTagMask)); + __ j(not_zero, &arg1_is_object); + } + __ SmiUntag(edx); + __ jmp(&load_arg2); + } + + __ bind(&arg1_is_object); + + // Get the untagged integer version of the edx heap number in ecx. + 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); + if (!number_info.IsHeapNumber()) { + // 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); + } + + __ bind(&arg2_is_object); + + // Get the untagged integer version of the eax heap number in ecx. + IntegerConvert(masm, eax, number_info, use_sse3, conversion_failure); + __ bind(&done); + __ mov(eax, edx); +} + + +// 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::LoadUnknownsAsIntegers(MacroAssembler* masm, + bool use_sse3, + Label* conversion_failure) { + // Check float operands. + Label arg1_is_object, check_undefined_arg1; + Label arg2_is_object, check_undefined_arg2; + Label load_arg2, done; + + // Test if arg1 is a Smi. __ test(edx, Immediate(kSmiTagMask)); __ j(not_zero, &arg1_is_object); + __ SmiUntag(edx); __ jmp(&load_arg2); @@ -8874,15 +9151,22 @@ void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm, __ 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, + NumberInfo::Unknown(), + 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); @@ -8898,13 +9182,30 @@ void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm, __ 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, + NumberInfo::Unknown(), + use_sse3, + conversion_failure); __ bind(&done); __ mov(eax, edx); } +void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm, + NumberInfo number_info, + bool use_sse3, + Label* conversion_failure) { + if (number_info.IsNumber()) { + LoadNumbersAsIntegers(masm, number_info, use_sse3, conversion_failure); + } else { + LoadUnknownsAsIntegers(masm, use_sse3, conversion_failure); + } +} + + void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, Register number) { Label load_smi, done; @@ -9141,7 +9442,11 @@ void GenericUnaryOpStub::Generate(MacroAssembler* masm) { __ 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; diff --git a/src/ia32/codegen-ia32.h b/src/ia32/codegen-ia32.h index 0b605b606..36c975b64 100644 --- a/src/ia32/codegen-ia32.h +++ b/src/ia32/codegen-ia32.h @@ -496,8 +496,8 @@ class CodeGenerator: public AstVisitor { // To prevent long attacker-controlled byte sequences, integer constants // from the JavaScript source are loaded in two parts if they are larger - // than 16 bits. - static const int kMaxSmiInlinedBits = 16; + // than 17 bits. + static const int kMaxSmiInlinedBits = 17; bool IsUnsafeSmi(Handle value); // Load an integer constant x into a register target or into the stack using // at most 16 bits of user-controlled data per assembly operation. @@ -695,7 +695,7 @@ class GenericBinaryOpStub: public CodeStub { GenericBinaryOpStub(Token::Value op, OverwriteMode mode, GenericBinaryFlags flags, - NumberInfo::Type operands_type = NumberInfo::kUnknown) + NumberInfo operands_type) : op_(op), mode_(mode), flags_(flags), @@ -704,6 +704,9 @@ class GenericBinaryOpStub: public CodeStub { static_operands_type_(operands_type), runtime_operands_type_(BinaryOpIC::DEFAULT), name_(NULL) { + if (static_operands_type_.IsSmi()) { + mode_ = NO_OVERWRITE; + } use_sse3_ = CpuFeatures::IsSupported(SSE3); ASSERT(OpBits::is_valid(Token::NUM_TOKENS)); } @@ -715,7 +718,8 @@ class GenericBinaryOpStub: public CodeStub { args_in_registers_(ArgsInRegistersBits::decode(key)), args_reversed_(ArgsReversedBits::decode(key)), use_sse3_(SSE3Bits::decode(key)), - static_operands_type_(StaticTypeInfoBits::decode(key)), + static_operands_type_(NumberInfo::ExpandedRepresentation( + StaticTypeInfoBits::decode(key))), runtime_operands_type_(runtime_operands_type), name_(NULL) { } @@ -741,7 +745,7 @@ class GenericBinaryOpStub: public CodeStub { bool use_sse3_; // Number type information of operands, determined by code generator. - NumberInfo::Type static_operands_type_; + NumberInfo static_operands_type_; // Operand type information determined at runtime. BinaryOpIC::TypeInfo runtime_operands_type_; @@ -760,7 +764,7 @@ class GenericBinaryOpStub: public CodeStub { static_cast(flags_), static_cast(args_in_registers_), static_cast(args_reversed_), - NumberInfo::ToString(static_operands_type_)); + static_operands_type_.ToString()); } #endif @@ -771,7 +775,7 @@ class GenericBinaryOpStub: public CodeStub { class ArgsInRegistersBits: public BitField {}; class ArgsReversedBits: public BitField {}; class FlagBits: public BitField {}; - class StaticTypeInfoBits: public BitField {}; + class StaticTypeInfoBits: public BitField {}; class RuntimeTypeInfoBits: public BitField {}; Major MajorKey() { return GenericBinaryOp; } @@ -783,7 +787,8 @@ class GenericBinaryOpStub: public CodeStub { | SSE3Bits::encode(use_sse3_) | ArgsInRegistersBits::encode(args_in_registers_) | ArgsReversedBits::encode(args_reversed_) - | StaticTypeInfoBits::encode(static_operands_type_) + | StaticTypeInfoBits::encode( + static_operands_type_.ThreeBitRepresentation()) | RuntimeTypeInfoBits::encode(runtime_operands_type_); } diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index 6eefc024f..6e3ae105d 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -1130,7 +1130,8 @@ void FullCodeGenerator::EmitBinaryOp(Token::Value op, __ push(result_register()); GenericBinaryOpStub stub(op, NO_OVERWRITE, - NO_GENERIC_BINARY_FLAGS); + NO_GENERIC_BINARY_FLAGS, + NumberInfo::Unknown()); __ CallStub(&stub); Apply(context, eax); } @@ -1744,7 +1745,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { // Call stub for +1/-1. GenericBinaryOpStub stub(expr->binary_op(), NO_OVERWRITE, - NO_GENERIC_BINARY_FLAGS); + NO_GENERIC_BINARY_FLAGS, + NumberInfo::Unknown()); stub.GenerateCall(masm(), eax, Smi::FromInt(1)); __ bind(&done); diff --git a/src/ia32/register-allocator-ia32.cc b/src/ia32/register-allocator-ia32.cc index 20539bff9..3ccfe8cd0 100644 --- a/src/ia32/register-allocator-ia32.cc +++ b/src/ia32/register-allocator-ia32.cc @@ -49,6 +49,7 @@ void Result::ToRegister() { Immediate(handle())); } // This result becomes a copy of the fresh one. + fresh.set_number_info(number_info()); *this = fresh; } ASSERT(is_register()); diff --git a/src/ia32/virtual-frame-ia32.cc b/src/ia32/virtual-frame-ia32.cc index 97b075518..7b03a5b2f 100644 --- a/src/ia32/virtual-frame-ia32.cc +++ b/src/ia32/virtual-frame-ia32.cc @@ -162,7 +162,7 @@ void VirtualFrame::MakeMergable() { if (element.is_constant() || element.is_copy()) { if (element.is_synced()) { // Just spill. - elements_[i] = FrameElement::MemoryElement(NumberInfo::kUnknown); + elements_[i] = FrameElement::MemoryElement(NumberInfo::Unknown()); } else { // Allocate to a register. FrameElement backing_element; // Invalid if not a copy. @@ -174,7 +174,7 @@ void VirtualFrame::MakeMergable() { elements_[i] = FrameElement::RegisterElement(fresh.reg(), FrameElement::NOT_SYNCED, - NumberInfo::kUnknown); + NumberInfo::Unknown()); Use(fresh.reg(), i); // Emit a move. @@ -207,7 +207,7 @@ void VirtualFrame::MakeMergable() { // The copy flag is not relied on before the end of this loop, // including when registers are spilled. elements_[i].clear_copied(); - elements_[i].set_number_info(NumberInfo::kUnknown); + elements_[i].set_number_info(NumberInfo::Unknown()); } } } @@ -1062,7 +1062,7 @@ Result VirtualFrame::Pop() { ASSERT(element.is_valid()); // Get number type information of the result. - NumberInfo::Type info; + NumberInfo info; if (!element.is_copy()) { info = element.number_info(); } else { @@ -1137,7 +1137,7 @@ void VirtualFrame::EmitPop(Operand operand) { } -void VirtualFrame::EmitPush(Register reg, NumberInfo::Type info) { +void VirtualFrame::EmitPush(Register reg, NumberInfo info) { ASSERT(stack_pointer_ == element_count() - 1); elements_.Add(FrameElement::MemoryElement(info)); stack_pointer_++; @@ -1145,7 +1145,7 @@ void VirtualFrame::EmitPush(Register reg, NumberInfo::Type info) { } -void VirtualFrame::EmitPush(Operand operand, NumberInfo::Type info) { +void VirtualFrame::EmitPush(Operand operand, NumberInfo info) { ASSERT(stack_pointer_ == element_count() - 1); elements_.Add(FrameElement::MemoryElement(info)); stack_pointer_++; @@ -1153,7 +1153,7 @@ void VirtualFrame::EmitPush(Operand operand, NumberInfo::Type info) { } -void VirtualFrame::EmitPush(Immediate immediate, NumberInfo::Type info) { +void VirtualFrame::EmitPush(Immediate immediate, NumberInfo info) { ASSERT(stack_pointer_ == element_count() - 1); elements_.Add(FrameElement::MemoryElement(info)); stack_pointer_++; diff --git a/src/ia32/virtual-frame-ia32.h b/src/ia32/virtual-frame-ia32.h index 407e2a164..cd2d18f43 100644 --- a/src/ia32/virtual-frame-ia32.h +++ b/src/ia32/virtual-frame-ia32.h @@ -84,7 +84,7 @@ class VirtualFrame: public ZoneObject { // Create a duplicate of an existing valid frame element. FrameElement CopyElementAt(int index, - NumberInfo::Type info = NumberInfo::kUninitialized); + NumberInfo info = NumberInfo::Uninitialized()); // The number of elements on the virtual frame. int element_count() { return elements_.length(); } @@ -388,14 +388,14 @@ class VirtualFrame: public ZoneObject { // Push an element on top of the expression stack and emit a // corresponding push instruction. void EmitPush(Register reg, - NumberInfo::Type info = NumberInfo::kUnknown); + NumberInfo info = NumberInfo::Unknown()); void EmitPush(Operand operand, - NumberInfo::Type info = NumberInfo::kUnknown); + NumberInfo info = NumberInfo::Unknown()); void EmitPush(Immediate immediate, - NumberInfo::Type info = NumberInfo::kUnknown); + NumberInfo info = NumberInfo::Unknown()); // Push an element on the virtual frame. - inline void Push(Register reg, NumberInfo::Type info = NumberInfo::kUnknown); + inline void Push(Register reg, NumberInfo info = NumberInfo::Unknown()); inline void Push(Handle value); inline void Push(Smi* value); diff --git a/src/jump-target-inl.h b/src/jump-target-inl.h index 12fabc329..6db008153 100644 --- a/src/jump-target-inl.h +++ b/src/jump-target-inl.h @@ -46,7 +46,7 @@ void JumpTarget::InitializeEntryElement(int index, FrameElement* target) { entry_frame_->elements_[target->index()].set_copied(); } if (direction_ == BIDIRECTIONAL && !target->is_copy()) { - element->set_number_info(NumberInfo::kUnknown); + element->set_number_info(NumberInfo::Unknown()); } } diff --git a/src/jump-target.cc b/src/jump-target.cc index ab09870b9..7b1ced7eb 100644 --- a/src/jump-target.cc +++ b/src/jump-target.cc @@ -135,7 +135,7 @@ void JumpTarget::ComputeEntryFrame() { FrameElement* target = elements[index]; if (target == NULL) { entry_frame_->elements_.Add( - FrameElement::MemoryElement(NumberInfo::kUninitialized)); + FrameElement::MemoryElement(NumberInfo::Uninitialized())); } else { entry_frame_->elements_.Add(*target); InitializeEntryElement(index, target); @@ -152,12 +152,12 @@ void JumpTarget::ComputeEntryFrame() { RegisterFile candidate_registers; int best_count = kMinInt; int best_reg_num = RegisterAllocator::kInvalidRegister; - NumberInfo::Type info = NumberInfo::kUninitialized; + NumberInfo info = NumberInfo::Uninitialized(); for (int j = 0; j < reaching_frames_.length(); j++) { FrameElement element = reaching_frames_[j]->elements_[i]; if (direction_ == BIDIRECTIONAL) { - info = NumberInfo::kUnknown; + info = NumberInfo::Unknown(); } else if (!element.is_copy()) { info = NumberInfo::Combine(info, element.number_info()); } else { @@ -181,7 +181,7 @@ void JumpTarget::ComputeEntryFrame() { // We must have a number type information now (not for copied elements). ASSERT(entry_frame_->elements_[i].is_copy() - || info != NumberInfo::kUninitialized); + || !info.IsUninitialized()); // If the value is synced on all frames, put it in memory. This // costs nothing at the merge code but will incur a @@ -211,7 +211,7 @@ void JumpTarget::ComputeEntryFrame() { Register reg = RegisterAllocator::ToRegister(best_reg_num); entry_frame_->elements_[i] = FrameElement::RegisterElement(reg, FrameElement::NOT_SYNCED, - NumberInfo::kUninitialized); + NumberInfo::Uninitialized()); if (is_copied) entry_frame_->elements_[i].set_copied(); entry_frame_->set_register_location(reg, i); } @@ -225,8 +225,7 @@ void JumpTarget::ComputeEntryFrame() { if (direction_ == BIDIRECTIONAL) { for (int i = 0; i < length; ++i) { if (!entry_frame_->elements_[i].is_copy()) { - ASSERT(entry_frame_->elements_[i].number_info() == - NumberInfo::kUnknown); + ASSERT(entry_frame_->elements_[i].number_info().IsUnknown()); } } } diff --git a/src/number-info.h b/src/number-info.h index c6f32e47c..bfc0d9fd2 100644 --- a/src/number-info.h +++ b/src/number-info.h @@ -31,42 +31,160 @@ namespace v8 { namespace internal { -class NumberInfo : public AllStatic { +// Unknown +// | +// Number +// / | +// HeapNumber Integer32 +// | | +// | Smi +// | / +// Uninitialized. + +class NumberInfo { public: - enum Type { - kUnknown = 0, - kNumber = 1, - kSmi = 3, - kHeapNumber = 5, - kUninitialized = 7 - }; + NumberInfo() { } + + static inline NumberInfo Unknown(); + // We know it's a number of some sort. + static inline NumberInfo Number(); + // We know it's signed or unsigned 32 bit integer. + static inline NumberInfo Integer32(); + // We know it's a Smi. + static inline NumberInfo Smi(); + // We know it's a heap number. + static inline NumberInfo HeapNumber(); + // We haven't started collecting info yet. + static inline NumberInfo Uninitialized(); + + // Return compact representation. Very sensitive to enum values below! + int ThreeBitRepresentation() { + ASSERT(type_ != kUninitializedType); + int answer = type_ > 6 ? type_ -2 : type_; + ASSERT(answer >= 0); + ASSERT(answer <= 7); + return answer; + } + + // Decode compact representation. Very sensitive to enum values below! + static NumberInfo ExpandedRepresentation(int three_bit_representation) { + Type t = static_cast(three_bit_representation >= 6 ? + three_bit_representation + 2 : + three_bit_representation); + ASSERT(t == kUnknownType || + t == kNumberType || + t == kInteger32Type || + t == kSmiType || + t == kHeapNumberType); + return NumberInfo(t); + } + + int ToInt() { + return type_; + } + + static NumberInfo FromInt(int bit_representation) { + Type t = static_cast(bit_representation); + ASSERT(t == kUnknownType || + t == kNumberType || + t == kInteger32Type || + t == kSmiType || + t == kHeapNumberType); + return NumberInfo(t); + } // Return the weakest (least precise) common type. - static Type Combine(Type a, Type b) { - // Make use of the order of enum values. - return static_cast(a & b); + static NumberInfo Combine(NumberInfo a, NumberInfo b) { + return NumberInfo(static_cast(a.type_ & b.type_)); + } + + inline bool IsUnknown() { + return type_ == kUnknownType; + } + + inline bool IsNumber() { + ASSERT(type_ != kUninitializedType); + return ((type_ & kNumberType) == kNumberType); + } + + inline bool IsSmi() { + ASSERT(type_ != kUninitializedType); + return ((type_ & kSmiType) == kSmiType); + } + + inline bool IsInteger32() { + ASSERT(type_ != kUninitializedType); + return ((type_ & kInteger32Type) == kInteger32Type); + } + + inline bool IsHeapNumber() { + ASSERT(type_ != kUninitializedType); + return ((type_ & kHeapNumberType) == kHeapNumberType); } - static bool IsNumber(Type a) { - ASSERT(a != kUninitialized); - return ((a & kNumber) != 0); + inline bool IsUninitialized() { + return type_ == kUninitializedType; } - static const char* ToString(Type a) { - switch (a) { - case kUnknown: return "UnknownType"; - case kNumber: return "NumberType"; - case kSmi: return "SmiType"; - case kHeapNumber: return "HeapNumberType"; - case kUninitialized: + const char* ToString() { + switch (type_) { + case kUnknownType: return "UnknownType"; + case kNumberType: return "NumberType"; + case kSmiType: return "SmiType"; + case kHeapNumberType: return "HeapNumberType"; + case kInteger32Type: return "Integer32Type"; + case kUninitializedType: UNREACHABLE(); return "UninitializedType"; } UNREACHABLE(); return "Unreachable code"; } + + private: + enum Type { + kUnknownType = 0, + kNumberType = 1, + kInteger32Type = 3, + kSmiType = 7, + kHeapNumberType = 9, + kUninitializedType = 15 + }; + explicit inline NumberInfo(Type t) : type_(t) { } + + Type type_; }; + +NumberInfo NumberInfo::Unknown() { + return NumberInfo(kUnknownType); +} + + +NumberInfo NumberInfo::Number() { + return NumberInfo(kNumberType); +} + + +NumberInfo NumberInfo::Integer32() { + return NumberInfo(kInteger32Type); +} + + +NumberInfo NumberInfo::Smi() { + return NumberInfo(kSmiType); +} + + +NumberInfo NumberInfo::HeapNumber() { + return NumberInfo(kHeapNumberType); +} + + +NumberInfo NumberInfo::Uninitialized() { + return NumberInfo(kUninitializedType); +} + } } // namespace v8::internal #endif // V8_NUMBER_INFO_H_ diff --git a/src/register-allocator-inl.h b/src/register-allocator-inl.h index 718da3601..8453104ee 100644 --- a/src/register-allocator-inl.h +++ b/src/register-allocator-inl.h @@ -103,6 +103,45 @@ void RegisterAllocator::Unuse(Register reg) { registers_.Unuse(ToNumber(reg)); } + +NumberInfo Result::number_info() const { + ASSERT(is_valid()); + if (!is_constant()) { + return NumberInfo::FromInt(NumberInfoField::decode(value_)); + } + Handle value = handle(); + if (value->IsSmi()) return NumberInfo::Smi(); + if (value->IsHeapNumber()) return NumberInfo::HeapNumber(); + return NumberInfo::Unknown(); +} + + +void Result::set_number_info(NumberInfo info) { + ASSERT(is_valid()); + value_ &= ~NumberInfoField::mask(); + value_ |= NumberInfoField::encode(info.ToInt()); +} + + +bool Result::is_number() const { + return number_info().IsNumber(); +} + + +bool Result::is_smi() const { + return number_info().IsSmi(); +} + + +bool Result::is_integer32() const { + return number_info().IsInteger32(); +} + + +bool Result::is_heap_number() const { + return number_info().IsHeapNumber(); +} + } } // namespace v8::internal #endif // V8_REGISTER_ALLOCATOR_INL_H_ diff --git a/src/register-allocator.cc b/src/register-allocator.cc index 1655b4ac1..64e442879 100644 --- a/src/register-allocator.cc +++ b/src/register-allocator.cc @@ -38,11 +38,11 @@ namespace internal { // Result implementation. -Result::Result(Register reg, NumberInfo::Type info) { +Result::Result(Register reg, NumberInfo info) { ASSERT(reg.is_valid() && !RegisterAllocator::IsReserved(reg)); CodeGeneratorScope::Current()->allocator()->Use(reg); value_ = TypeField::encode(REGISTER) - | NumberInfoField::encode(info) + | NumberInfoField::encode(info.ToInt()) | DataField::encode(reg.code_); } @@ -53,23 +53,6 @@ Result::ZoneObjectList* Result::ConstantList() { } -NumberInfo::Type Result::number_info() { - ASSERT(is_valid()); - if (!is_constant()) return NumberInfoField::decode(value_); - Handle value = handle(); - if (value->IsSmi()) return NumberInfo::kSmi; - if (value->IsHeapNumber()) return NumberInfo::kHeapNumber; - return NumberInfo::kUnknown; -} - - -void Result::set_number_info(NumberInfo::Type info) { - ASSERT(is_valid()); - value_ = value_ & ~NumberInfoField::mask(); - value_ = value_ | NumberInfoField::encode(info); -} - - // ------------------------------------------------------------------------- // RegisterAllocator implementation. diff --git a/src/register-allocator.h b/src/register-allocator.h index 747200a05..2a7b820a5 100644 --- a/src/register-allocator.h +++ b/src/register-allocator.h @@ -65,12 +65,12 @@ class Result BASE_EMBEDDED { Result() { invalidate(); } // Construct a register Result. - explicit Result(Register reg, NumberInfo::Type info = NumberInfo::kUnknown); + explicit Result(Register reg, NumberInfo info = NumberInfo::Unknown()); // Construct a Result whose value is a compile-time constant. explicit Result(Handle value) { value_ = TypeField::encode(CONSTANT) - | NumberInfoField::encode(NumberInfo::kUninitialized) + | NumberInfoField::encode(NumberInfo::Uninitialized().ToInt()) | DataField::encode(ConstantList()->length()); ConstantList()->Add(value); } @@ -101,13 +101,12 @@ class Result BASE_EMBEDDED { void invalidate() { value_ = TypeField::encode(INVALID); } - NumberInfo::Type number_info(); - void set_number_info(NumberInfo::Type info); - bool is_number() { - return (number_info() & NumberInfo::kNumber) != 0; - } - bool is_smi() { return number_info() == NumberInfo::kSmi; } - bool is_heap_number() { return number_info() == NumberInfo::kHeapNumber; } + inline NumberInfo number_info() const; + inline void set_number_info(NumberInfo info); + inline bool is_number() const; + inline bool is_smi() const; + inline bool is_integer32() const; + inline bool is_heap_number() const; bool is_valid() const { return type() != INVALID; } bool is_register() const { return type() == REGISTER; } @@ -140,8 +139,8 @@ class Result BASE_EMBEDDED { uint32_t value_; class TypeField: public BitField {}; - class NumberInfoField : public BitField {}; - class DataField: public BitField {}; + class NumberInfoField : public BitField {}; + class DataField: public BitField {}; inline void CopyTo(Result* destination) const; diff --git a/src/virtual-frame-inl.h b/src/virtual-frame-inl.h index 9a744f550..9aa88fe18 100644 --- a/src/virtual-frame-inl.h +++ b/src/virtual-frame-inl.h @@ -40,7 +40,7 @@ VirtualFrame::VirtualFrame() : elements_(parameter_count() + local_count() + kPreallocatedElements), stack_pointer_(parameter_count() + 1) { // 0-based index of TOS. for (int i = 0; i <= stack_pointer_; i++) { - elements_.Add(FrameElement::MemoryElement(NumberInfo::kUnknown)); + elements_.Add(FrameElement::MemoryElement(NumberInfo::Unknown())); } for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) { register_locations_[i] = kIllegalIndex; @@ -65,7 +65,7 @@ void VirtualFrame::PushFrameSlotAt(int index) { } -void VirtualFrame::Push(Register reg, NumberInfo::Type info) { +void VirtualFrame::Push(Register reg, NumberInfo info) { if (is_used(reg)) { int index = register_location(reg); FrameElement element = CopyElementAt(index, info); diff --git a/src/virtual-frame.cc b/src/virtual-frame.cc index d5b5f42ae..8c13a6a86 100644 --- a/src/virtual-frame.cc +++ b/src/virtual-frame.cc @@ -43,7 +43,7 @@ namespace internal { // not conflict with the existing type information and must be equally or // more precise. The default parameter value kUninitialized means that there // is no additional information. -FrameElement VirtualFrame::CopyElementAt(int index, NumberInfo::Type info) { +FrameElement VirtualFrame::CopyElementAt(int index, NumberInfo info) { ASSERT(index >= 0); ASSERT(index < element_count()); @@ -74,14 +74,14 @@ FrameElement VirtualFrame::CopyElementAt(int index, NumberInfo::Type info) { result.set_index(index); elements_[index].set_copied(); // Update backing element's number information. - NumberInfo::Type existing = elements_[index].number_info(); - ASSERT(existing != NumberInfo::kUninitialized); + NumberInfo existing = elements_[index].number_info(); + ASSERT(!existing.IsUninitialized()); // Assert that the new type information (a) does not conflict with the // existing one and (b) is equally or more precise. - ASSERT((info == NumberInfo::kUninitialized) || - (existing | info) != NumberInfo::kUninitialized); - ASSERT(existing <= info); - elements_[index].set_number_info(info != NumberInfo::kUninitialized + ASSERT((info.ToInt() & existing.ToInt()) == existing.ToInt()); + ASSERT((info.ToInt() | existing.ToInt()) == info.ToInt()); + + elements_[index].set_number_info(!info.IsUninitialized() ? info : existing); break; @@ -104,7 +104,7 @@ void VirtualFrame::Adjust(int count) { ASSERT(stack_pointer_ == element_count() - 1); for (int i = 0; i < count; i++) { - elements_.Add(FrameElement::MemoryElement(NumberInfo::kUnknown)); + elements_.Add(FrameElement::MemoryElement(NumberInfo::Unknown())); } stack_pointer_ += count; } @@ -152,7 +152,7 @@ void VirtualFrame::SpillElementAt(int index) { SyncElementAt(index); // Number type information is preserved. // Copies get their number information from their backing element. - NumberInfo::Type info; + NumberInfo info; if (!elements_[index].is_copy()) { info = elements_[index].number_info(); } else { diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc index d3d2e55bc..e9dfe2901 100644 --- a/src/x64/codegen-x64.cc +++ b/src/x64/codegen-x64.cc @@ -5280,7 +5280,7 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op, } // Get number type of left and right sub-expressions. - NumberInfo::Type operands_type = + NumberInfo operands_type = NumberInfo::Combine(left.number_info(), right.number_info()); Result answer; @@ -5316,7 +5316,7 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op, // Set NumberInfo of result according to the operation performed. // We rely on the fact that smis have a 32 bit payload on x64. ASSERT(kSmiValueSize == 32); - NumberInfo::Type result_type = NumberInfo::kUnknown; + NumberInfo result_type = NumberInfo::Unknown(); switch (op) { case Token::COMMA: result_type = right.number_info(); @@ -5330,32 +5330,32 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op, case Token::BIT_XOR: case Token::BIT_AND: // Result is always a smi. - result_type = NumberInfo::kSmi; + result_type = NumberInfo::Smi(); break; case Token::SAR: case Token::SHL: // Result is always a smi. - result_type = NumberInfo::kSmi; + result_type = NumberInfo::Smi(); break; case Token::SHR: // Result of x >>> y is always a smi if y >= 1, otherwise a number. result_type = (right.is_constant() && right.handle()->IsSmi() && Smi::cast(*right.handle())->value() >= 1) - ? NumberInfo::kSmi - : NumberInfo::kNumber; + ? NumberInfo::Smi() + : NumberInfo::Number(); 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; + result_type = operands_type.IsNumber() + ? NumberInfo::Number() + : NumberInfo::Unknown(); break; case Token::SUB: case Token::MUL: case Token::DIV: case Token::MOD: // Result is always a number. - result_type = NumberInfo::kNumber; + result_type = NumberInfo::Number(); break; default: UNREACHABLE(); @@ -8332,7 +8332,7 @@ const char* GenericBinaryOpStub::GetName() { args_in_registers_ ? "RegArgs" : "StackArgs", args_reversed_ ? "_R" : "", use_sse3_ ? "SSE3" : "SSE2", - NumberInfo::ToString(operands_type_)); + operands_type_.ToString()); return name_; } @@ -8656,7 +8656,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) { case Token::DIV: { // rax: y // rdx: x - if (NumberInfo::IsNumber(operands_type_)) { + if (operands_type_.IsNumber()) { if (FLAG_debug_code) { // Assert at runtime that inputs are only numbers. __ AbortIfNotNumber(rdx, "GenericBinaryOpStub operand not a number."); diff --git a/src/x64/codegen-x64.h b/src/x64/codegen-x64.h index 62f82a28e..7c0883039 100644 --- a/src/x64/codegen-x64.h +++ b/src/x64/codegen-x64.h @@ -661,7 +661,7 @@ class GenericBinaryOpStub: public CodeStub { GenericBinaryOpStub(Token::Value op, OverwriteMode mode, GenericBinaryFlags flags, - NumberInfo::Type operands_type = NumberInfo::kUnknown) + NumberInfo operands_type = NumberInfo::Unknown()) : op_(op), mode_(mode), flags_(flags), @@ -693,7 +693,7 @@ class GenericBinaryOpStub: public CodeStub { bool args_reversed_; // Left and right argument are swapped. bool use_sse3_; char* name_; - NumberInfo::Type operands_type_; + NumberInfo operands_type_; const char* GetName(); @@ -707,7 +707,7 @@ class GenericBinaryOpStub: public CodeStub { static_cast(flags_), static_cast(args_in_registers_), static_cast(args_reversed_), - NumberInfo::ToString(operands_type_)); + operands_type_.ToString()); } #endif @@ -718,7 +718,7 @@ class GenericBinaryOpStub: public CodeStub { class ArgsInRegistersBits: public BitField {}; class ArgsReversedBits: public BitField {}; class FlagBits: public BitField {}; - class NumberInfoBits: public BitField {}; + class NumberInfoBits: public BitField {}; Major MajorKey() { return GenericBinaryOp; } int MinorKey() { @@ -729,7 +729,7 @@ class GenericBinaryOpStub: public CodeStub { | SSE3Bits::encode(use_sse3_) | ArgsInRegistersBits::encode(args_in_registers_) | ArgsReversedBits::encode(args_reversed_) - | NumberInfoBits::encode(operands_type_); + | NumberInfoBits::encode(operands_type_.ThreeBitRepresentation()); } void Generate(MacroAssembler* masm); diff --git a/src/x64/virtual-frame-x64.cc b/src/x64/virtual-frame-x64.cc index de27ddacc..79be20b1b 100644 --- a/src/x64/virtual-frame-x64.cc +++ b/src/x64/virtual-frame-x64.cc @@ -177,7 +177,7 @@ void VirtualFrame::EmitPop(const Operand& operand) { } -void VirtualFrame::EmitPush(Register reg, NumberInfo::Type info) { +void VirtualFrame::EmitPush(Register reg, NumberInfo info) { ASSERT(stack_pointer_ == element_count() - 1); elements_.Add(FrameElement::MemoryElement(info)); stack_pointer_++; @@ -185,7 +185,7 @@ void VirtualFrame::EmitPush(Register reg, NumberInfo::Type info) { } -void VirtualFrame::EmitPush(const Operand& operand, NumberInfo::Type info) { +void VirtualFrame::EmitPush(const Operand& operand, NumberInfo info) { ASSERT(stack_pointer_ == element_count() - 1); elements_.Add(FrameElement::MemoryElement(info)); stack_pointer_++; @@ -193,7 +193,7 @@ void VirtualFrame::EmitPush(const Operand& operand, NumberInfo::Type info) { } -void VirtualFrame::EmitPush(Immediate immediate, NumberInfo::Type info) { +void VirtualFrame::EmitPush(Immediate immediate, NumberInfo info) { ASSERT(stack_pointer_ == element_count() - 1); elements_.Add(FrameElement::MemoryElement(info)); stack_pointer_++; @@ -203,7 +203,7 @@ void VirtualFrame::EmitPush(Immediate immediate, NumberInfo::Type info) { void VirtualFrame::EmitPush(Smi* smi_value) { ASSERT(stack_pointer_ == element_count() - 1); - elements_.Add(FrameElement::MemoryElement(NumberInfo::kSmi)); + elements_.Add(FrameElement::MemoryElement(NumberInfo::Smi())); stack_pointer_++; __ Push(smi_value); } @@ -211,11 +211,11 @@ void VirtualFrame::EmitPush(Smi* smi_value) { void VirtualFrame::EmitPush(Handle value) { ASSERT(stack_pointer_ == element_count() - 1); - NumberInfo::Type info = NumberInfo::kUnknown; + NumberInfo info = NumberInfo::Unknown(); if (value->IsSmi()) { - info = NumberInfo::kSmi; + info = NumberInfo::Smi(); } else if (value->IsHeapNumber()) { - info = NumberInfo::kHeapNumber; + info = NumberInfo::HeapNumber(); } elements_.Add(FrameElement::MemoryElement(info)); stack_pointer_++; @@ -223,7 +223,7 @@ void VirtualFrame::EmitPush(Handle value) { } -void VirtualFrame::EmitPush(Heap::RootListIndex index, NumberInfo::Type info) { +void VirtualFrame::EmitPush(Heap::RootListIndex index, NumberInfo info) { ASSERT(stack_pointer_ == element_count() - 1); elements_.Add(FrameElement::MemoryElement(info)); stack_pointer_++; @@ -480,7 +480,7 @@ void VirtualFrame::MakeMergable() { if (element.is_constant() || element.is_copy()) { if (element.is_synced()) { // Just spill. - elements_[i] = FrameElement::MemoryElement(NumberInfo::kUnknown); + elements_[i] = FrameElement::MemoryElement(NumberInfo::Unknown()); } else { // Allocate to a register. FrameElement backing_element; // Invalid if not a copy. @@ -492,7 +492,7 @@ void VirtualFrame::MakeMergable() { elements_[i] = FrameElement::RegisterElement(fresh.reg(), FrameElement::NOT_SYNCED, - NumberInfo::kUnknown); + NumberInfo::Unknown()); Use(fresh.reg(), i); // Emit a move. @@ -521,7 +521,7 @@ void VirtualFrame::MakeMergable() { // The copy flag is not relied on before the end of this loop, // including when registers are spilled. elements_[i].clear_copied(); - elements_[i].set_number_info(NumberInfo::kUnknown); + elements_[i].set_number_info(NumberInfo::Unknown()); } } } @@ -728,7 +728,7 @@ Result VirtualFrame::Pop() { ASSERT(element.is_valid()); // Get number type information of the result. - NumberInfo::Type info; + NumberInfo info; if (!element.is_copy()) { info = element.number_info(); } else { diff --git a/src/x64/virtual-frame-x64.h b/src/x64/virtual-frame-x64.h index 7f747e3b3..ddd606bf4 100644 --- a/src/x64/virtual-frame-x64.h +++ b/src/x64/virtual-frame-x64.h @@ -83,7 +83,7 @@ class VirtualFrame : public ZoneObject { // Create a duplicate of an existing valid frame element. FrameElement CopyElementAt(int index, - NumberInfo::Type info = NumberInfo::kUninitialized); + NumberInfo info = NumberInfo::Uninitialized()); // The number of elements on the virtual frame. int element_count() { return elements_.length(); } @@ -383,19 +383,19 @@ class VirtualFrame : public ZoneObject { // Push an element on top of the expression stack and emit a // corresponding push instruction. void EmitPush(Register reg, - NumberInfo::Type info = NumberInfo::kUnknown); + NumberInfo info = NumberInfo::Unknown()); void EmitPush(const Operand& operand, - NumberInfo::Type info = NumberInfo::kUnknown); + NumberInfo info = NumberInfo::Unknown()); void EmitPush(Heap::RootListIndex index, - NumberInfo::Type info = NumberInfo::kUnknown); + NumberInfo info = NumberInfo::Unknown()); void EmitPush(Immediate immediate, - NumberInfo::Type info = NumberInfo::kUnknown); + NumberInfo info = NumberInfo::Unknown()); void EmitPush(Smi* value); // Uses kScratchRegister, emits appropriate relocation info. void EmitPush(Handle value); // Push an element on the virtual frame. - inline void Push(Register reg, NumberInfo::Type info = NumberInfo::kUnknown); + inline void Push(Register reg, NumberInfo info = NumberInfo::Unknown()); inline void Push(Handle value); inline void Push(Smi* value); -- 2.34.1