Commit 00a44ae5 authored by erik.corry@gmail.com's avatar erik.corry@gmail.com

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
parent 77d63cc2
......@@ -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);
}
......
......@@ -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<Object> value);
inline void Push(Smi* value);
......
......@@ -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<Object> 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<Type, 0, 3> {};
class CopiedField: public BitField<bool, 3, 1> {};
class SyncedField: public BitField<bool, 4, 1> {};
class NumberInfoField: public BitField<NumberInfo::Type, 5, 3> {};
class DataField: public BitField<uint32_t, 8, 32 - 8> {};
class NumberInfoField: public BitField<int, 5, 4> {};
class DataField: public BitField<uint32_t, 9, 32 - 9> {};
friend class VirtualFrame;
};
......
......@@ -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<String> 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;
......
......@@ -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<Object> 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<int>(flags_),
static_cast<int>(args_in_registers_),
static_cast<int>(args_reversed_),
NumberInfo::ToString(static_operands_type_));
static_operands_type_.ToString());
}
#endif
......@@ -771,7 +775,7 @@ class GenericBinaryOpStub: public CodeStub {
class ArgsInRegistersBits: public BitField<bool, 10, 1> {};
class ArgsReversedBits: public BitField<bool, 11, 1> {};
class FlagBits: public BitField<GenericBinaryFlags, 12, 1> {};
class StaticTypeInfoBits: public BitField<NumberInfo::Type, 13, 3> {};
class StaticTypeInfoBits: public BitField<int, 13, 3> {};
class RuntimeTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 16, 2> {};
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_);
}
......
......@@ -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);
......
......@@ -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());
......
......@@ -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_++;
......
......@@ -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<Object> value);
inline void Push(Smi* value);
......
......@@ -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());
}
}
......
......@@ -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());
}
}
}
......
......@@ -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<Type>(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<Type>(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<Type>(a & b);
static NumberInfo Combine(NumberInfo a, NumberInfo b) {
return NumberInfo(static_cast<Type>(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_
......@@ -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<Object> 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_
......@@ -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<Object> 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.
......
......@@ -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<Object> 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<Type, 0, 2> {};
class NumberInfoField : public BitField<NumberInfo::Type, 2, 3> {};
class DataField: public BitField<uint32_t, 5, 32 - 5> {};
class NumberInfoField : public BitField<int, 2, 4> {};
class DataField: public BitField<uint32_t, 6, 32 - 6> {};
inline void CopyTo(Result* destination) const;
......
......@@ -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);
......
......@@ -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 {
......
......@@ -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.");
......
......@@ -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<int>(flags_),
static_cast<int>(args_in_registers_),
static_cast<int>(args_reversed_),
NumberInfo::ToString(operands_type_));
operands_type_.ToString());
}
#endif
......@@ -718,7 +718,7 @@ class GenericBinaryOpStub: public CodeStub {
class ArgsInRegistersBits: public BitField<bool, 10, 1> {};
class ArgsReversedBits: public BitField<bool, 11, 1> {};
class FlagBits: public BitField<GenericBinaryFlags, 12, 1> {};
class NumberInfoBits: public BitField<NumberInfo::Type, 13, 3> {};
class NumberInfoBits: public BitField<int, 13, 3> {};
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);
......
......@@ -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<Object> 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<Object> 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 {
......
......@@ -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<Object> 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<Object> value);
inline void Push(Smi* value);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment