Replace tagged keys for fast access by smi, and use smi in boundscheck.

BUG=
R=jkummerow@chromium.org

Review URL: https://chromiumcodereview.appspot.com/15763004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14794 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
verwaest@chromium.org 2013-05-24 08:52:35 +00:00
parent 94b4240f5c
commit c9a22a3c8d
11 changed files with 44 additions and 120 deletions

View File

@ -2029,12 +2029,6 @@ LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
}
LInstruction* LChunkBuilder::DoCheckSmiOrInt32(HCheckSmiOrInt32* instr) {
LOperand* value = UseRegisterAtStart(instr->value());
return AssignEnvironment(new(zone()) LCheckSmi(value));
}
LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
LOperand* value = UseRegisterAtStart(instr->value());
return AssignEnvironment(new(zone()) LCheckFunction(value));
@ -2079,7 +2073,7 @@ LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
return DefineAsRegister(new(zone()) LConstantI);
} else if (r.IsDouble()) {
return DefineAsRegister(new(zone()) LConstantD);
} else if (r.IsTagged() || r.IsSmi()) {
} else if (r.IsSmiOrTagged()) {
return DefineAsRegister(new(zone()) LConstantT);
} else {
UNREACHABLE();
@ -2191,7 +2185,7 @@ LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged());
instr->key()->representation().IsSmi());
ElementsKind elements_kind = instr->elements_kind();
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
LLoadKeyed* result = NULL;

View File

@ -3276,7 +3276,7 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
key = ToRegister(instr->key());
}
int element_size_shift = ElementsKindToShiftSize(elements_kind);
int shift_size = (instr->hydrogen()->key()->representation().IsTagged())
int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
? (element_size_shift - kSmiTagSize) : element_size_shift;
int additional_offset = instr->additional_index() << element_size_shift;
@ -3348,7 +3348,7 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
Register scratch = scratch0();
int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
int shift_size = (instr->hydrogen()->key()->representation().IsTagged())
int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
? (element_size_shift - kSmiTagSize) : element_size_shift;
int constant_key = 0;
if (key_is_constant) {
@ -3393,7 +3393,7 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
// representation for the key to be an integer, the input gets replaced
// during bound check elimination with the index argument to the bounds
// check, which can be tagged, so that case must be handled here, too.
if (instr->hydrogen()->key()->representation().IsTagged()) {
if (instr->hydrogen()->key()->representation().IsSmi()) {
__ add(scratch, elements, Operand::PointerOffsetFromSmiKey(key));
} else {
__ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2));
@ -4329,7 +4329,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
if (instr->index()->IsConstantOperand()) {
int constant_index =
ToInteger32(LConstantOperand::cast(instr->index()));
if (instr->hydrogen()->length()->representation().IsTagged()) {
if (instr->hydrogen()->length()->representation().IsSmi()) {
__ mov(ip, Operand(Smi::FromInt(constant_index)));
} else {
__ mov(ip, Operand(constant_index));
@ -4357,7 +4357,7 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
key = ToRegister(instr->key());
}
int element_size_shift = ElementsKindToShiftSize(elements_kind);
int shift_size = (instr->hydrogen()->key()->representation().IsTagged())
int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
? (element_size_shift - kSmiTagSize) : element_size_shift;
int additional_offset = instr->additional_index() << element_size_shift;
@ -4430,7 +4430,7 @@ void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
key = ToRegister(instr->key());
}
int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
int shift_size = (instr->hydrogen()->key()->representation().IsTagged())
int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
? (element_size_shift - kSmiTagSize) : element_size_shift;
Operand operand = key_is_constant
? Operand((constant_key << element_size_shift) +
@ -4476,7 +4476,7 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
// representation for the key to be an integer, the input gets replaced
// during bound check elimination with the index argument to the bounds
// check, which can be tagged, so that case must be handled here, too.
if (instr->hydrogen()->key()->representation().IsTagged()) {
if (instr->hydrogen()->key()->representation().IsSmi()) {
__ add(scratch, elements, Operand::PointerOffsetFromSmiKey(key));
} else {
__ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2));

View File

@ -410,7 +410,7 @@ HValue* CodeStubGraphBuilder<KeyedLoadFastElementStub>::BuildCodeStub() {
HInstruction* load = BuildUncheckedMonomorphicElementAccess(
GetParameter(0), GetParameter(1), NULL, NULL,
casted_stub()->is_js_array(), casted_stub()->elements_kind(),
false, NEVER_RETURN_HOLE, STANDARD_STORE, Representation::Tagged());
false, NEVER_RETURN_HOLE, STANDARD_STORE, Representation::Smi());
return load;
}
@ -456,7 +456,7 @@ HValue* CodeStubGraphBuilder<KeyedStoreFastElementStub>::BuildCodeStub() {
GetParameter(0), GetParameter(1), GetParameter(2), NULL,
casted_stub()->is_js_array(), casted_stub()->elements_kind(),
true, NEVER_RETURN_HOLE, casted_stub()->store_mode(),
Representation::Tagged());
Representation::Smi());
return GetParameter(2);
}
@ -572,11 +572,9 @@ HValue* CodeStubGraphBuilder<ArraySingleArgumentConstructorStub>::
new(zone()) HConstant(initial_capacity, Representation::Tagged());
AddInstruction(initial_capacity_node);
// Since we're forcing Integer32 representation for this HBoundsCheck,
// there's no need to Smi-check the index.
HBoundsCheck* checked_arg = AddBoundsCheck(argument, max_alloc_length,
ALLOW_SMI_KEY,
Representation::Tagged());
Representation::Smi());
IfBuilder if_builder(this);
if_builder.IfCompare(checked_arg, constant_zero, Token::EQ);
if_builder.Then();

View File

@ -1143,16 +1143,15 @@ void HBoundsCheck::InferRepresentation(HInferRepresentation* h_infer) {
HValue* actual_length = length()->ActualValue();
HValue* actual_index = index()->ActualValue();
if (key_mode_ == DONT_ALLOW_SMI_KEY ||
!actual_length->representation().IsTagged()) {
!actual_length->representation().IsSmiOrTagged()) {
r = Representation::Integer32();
} else if (actual_index->representation().IsTagged() ||
} else if (actual_index->representation().IsSmiOrTagged() ||
(actual_index->IsConstant() &&
HConstant::cast(actual_index)->HasSmiValue())) {
// If the index is tagged, or a constant that holds a Smi, allow the length
// to be tagged, since it is usually already tagged from loading it out of
// the length field of a JSArray. This allows for direct comparison without
// untagging.
r = Representation::Tagged();
// If the index is smi, or a constant that holds a Smi, allow the length to
// be smi, since it is usually already smi from loading it out of the length
// field of a JSArray. This allows for direct comparison without untagging.
r = Representation::Smi();
} else {
r = Representation::Integer32();
}
@ -2945,15 +2944,6 @@ HType HCheckSmi::CalculateInferredType() {
}
void HCheckSmiOrInt32::InferRepresentation(HInferRepresentation* h_infer) {
ASSERT(CheckFlag(kFlexibleRepresentation));
ASSERT(UseCount() == 1);
HUseIterator use = uses();
Representation r = use.value()->RequiredInputRepresentation(use.index());
UpdateRepresentation(r, h_infer, "checksmiorint32");
}
HType HPhi::CalculateInferredType() {
HType result = HType::Uninitialized();
for (int i = 0; i < OperandCount(); ++i) {

View File

@ -93,7 +93,6 @@ class LChunkBuilder;
V(CheckNonSmi) \
V(CheckPrototypeMaps) \
V(CheckSmi) \
V(CheckSmiOrInt32) \
V(ClampToUint8) \
V(ClassOfTestAndBranch) \
V(CompareIDAndBranch) \
@ -1721,7 +1720,7 @@ class HChange: public HUnaryOperation {
SetFlag(kUseGVN);
if (deoptimize_on_undefined) SetFlag(kDeoptimizeOnUndefined);
if (is_truncating) SetFlag(kTruncatingToInt32);
if (value->type().IsSmi()) {
if (value->representation().IsSmi() || value->type().IsSmi()) {
set_type(HType::Smi());
} else {
set_type(HType::TaggedNumber());
@ -2952,38 +2951,6 @@ class HCheckSmi: public HUnaryOperation {
};
class HCheckSmiOrInt32: public HUnaryOperation {
public:
explicit HCheckSmiOrInt32(HValue* value) : HUnaryOperation(value) {
SetFlag(kFlexibleRepresentation);
SetFlag(kUseGVN);
}
virtual int RedefinedOperandIndex() { return 0; }
virtual Representation RequiredInputRepresentation(int index) {
return representation();
}
virtual void InferRepresentation(HInferRepresentation* h_infer);
virtual Representation observed_input_representation(int index) {
return Representation::Integer32();
}
virtual HValue* Canonicalize() {
if (representation().IsTagged() && !value()->type().IsSmi()) {
return this;
} else {
return value();
}
}
DECLARE_CONCRETE_INSTRUCTION(CheckSmiOrInt32)
protected:
virtual bool DataEquals(HValue* other) { return true; }
};
class HPhi: public HValue {
public:
HPhi(int merged_index, Zone* zone)
@ -3578,8 +3545,7 @@ class HBoundsCheckBaseIndexInformation;
class HBoundsCheck: public HTemplateInstruction<2> {
public:
// Normally HBoundsCheck should be created using the
// HGraphBuilder::AddBoundsCheck() helper, which also guards the index with
// a HCheckSmiOrInt32 check.
// HGraphBuilder::AddBoundsCheck() helper.
// However when building stubs, where we know that the arguments are Int32,
// it makes sense to invoke this constructor directly.
HBoundsCheck(HValue* index,
@ -5459,7 +5425,7 @@ class ArrayInstructionInterface {
static Representation KeyedAccessIndexRequirement(Representation r) {
return r.IsInteger32() ? Representation::Integer32()
: Representation::Tagged();
: Representation::Smi();
}
};

View File

@ -1003,14 +1003,6 @@ HBoundsCheck* HGraphBuilder::AddBoundsCheck(HValue* index,
HValue* length,
BoundsCheckKeyMode key_mode,
Representation r) {
if (!index->type().IsSmi()) {
index = new(graph()->zone()) HCheckSmiOrInt32(index);
AddInstruction(HCheckSmiOrInt32::cast(index));
}
if (!length->type().IsSmi()) {
length = new(graph()->zone()) HCheckSmiOrInt32(length);
AddInstruction(HCheckSmiOrInt32::cast(length));
}
HBoundsCheck* result = new(graph()->zone()) HBoundsCheck(
index, length, key_mode, r);
AddInstruction(result);
@ -1333,11 +1325,7 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
elements = BuildCheckForCapacityGrow(object, elements, elements_kind,
length, key, is_js_array);
if (!key->type().IsSmi()) {
checked_key = AddInstruction(new(zone) HCheckSmiOrInt32(key));
} else {
checked_key = key;
}
} else {
checked_key = AddBoundsCheck(
key, length, ALLOW_SMI_KEY, checked_index_representation);

View File

@ -3364,7 +3364,7 @@ Operand LCodeGen::BuildFastArrayOperand(
+ offset);
} else {
// Take the tag bit into account while computing the shift size.
if (key_representation.IsTagged() && (shift_size >= 1)) {
if (key_representation.IsSmi() && (shift_size >= 1)) {
shift_size -= kSmiTagSize;
}
ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
@ -4359,7 +4359,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
if (instr->index()->IsConstantOperand()) {
int constant_index =
ToInteger32(LConstantOperand::cast(instr->index()));
if (instr->hydrogen()->length()->representation().IsTagged()) {
if (instr->hydrogen()->length()->representation().IsSmi()) {
__ cmp(ToOperand(instr->length()),
Immediate(Smi::FromInt(constant_index)));
} else {

View File

@ -2068,12 +2068,6 @@ LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
}
LInstruction* LChunkBuilder::DoCheckSmiOrInt32(HCheckSmiOrInt32* instr) {
LOperand* value = UseAtStart(instr->value());
return AssignEnvironment(new(zone()) LCheckSmi(value));
}
LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
// If the target is in new space, we'll emit a global cell compare and so
// want the value in a register. If the target gets promoted before we
@ -2144,7 +2138,7 @@ LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
} else {
return DefineX87TOS(new(zone()) LConstantD(NULL));
}
} else if (r.IsTagged()) {
} else if (r.IsSmiOrTagged()) {
return DefineAsRegister(new(zone()) LConstantT);
} else {
UNREACHABLE();
@ -2261,7 +2255,7 @@ LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged());
instr->key()->representation().IsSmi());
ElementsKind elements_kind = instr->elements_kind();
bool clobbers_key = ExternalArrayOpRequiresTemp(
instr->key()->representation(), elements_kind);
@ -2330,7 +2324,7 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
if (!instr->is_external()) {
ASSERT(instr->elements()->representation().IsTagged());
ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged());
instr->key()->representation().IsSmi());
if (instr->value()->representation().IsDouble()) {
LOperand* object = UseRegisterAtStart(instr->elements());

View File

@ -1596,7 +1596,7 @@ inline static bool ExternalArrayOpRequiresTemp(
// Operations that require the key to be divided by two to be converted into
// an index cannot fold the scale operation into a load and need an extra
// temp register to do the work.
return key_representation.IsTagged() &&
return key_representation.IsSmi() &&
(elements_kind == EXTERNAL_BYTE_ELEMENTS ||
elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS ||
elements_kind == EXTERNAL_PIXEL_ELEMENTS);

View File

@ -2922,7 +2922,7 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
// gets replaced during bound check elimination with the index argument
// to the bounds check, which can be tagged, so that case must be
// handled here, too.
if (instr->hydrogen()->key()->representation().IsTagged()) {
if (instr->hydrogen()->key()->representation().IsSmi()) {
__ SmiToInteger64(key_reg, key_reg);
} else if (instr->hydrogen()->IsDehoisted()) {
// Sign extend key because it could be a 32 bit negative value
@ -2995,7 +2995,7 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
// representation for the key to be an integer, the input gets replaced
// during bound check elimination with the index argument to the bounds
// check, which can be tagged, so that case must be handled here, too.
if (instr->hydrogen()->key()->representation().IsTagged()) {
if (instr->hydrogen()->key()->representation().IsSmi()) {
__ SmiToInteger64(key_reg, key_reg);
} else if (instr->hydrogen()->IsDehoisted()) {
// Sign extend key because it could be a 32 bit negative value
@ -3037,7 +3037,7 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
// gets replaced during bound check elimination with the index
// argument to the bounds check, which can be tagged, so that
// case must be handled here, too.
if (instr->hydrogen()->key()->representation().IsTagged()) {
if (instr->hydrogen()->key()->representation().IsSmi()) {
__ SmiToInteger64(key_reg, key_reg);
} else if (instr->hydrogen()->IsDehoisted()) {
// Sign extend key because it could be a 32 bit negative value
@ -4042,20 +4042,20 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
if (instr->length()->IsRegister()) {
Register reg = ToRegister(instr->length());
if (!instr->hydrogen()->length()->representation().IsTagged()) {
if (!instr->hydrogen()->length()->representation().IsSmi()) {
__ AssertZeroExtended(reg);
}
if (instr->index()->IsConstantOperand()) {
int constant_index =
ToInteger32(LConstantOperand::cast(instr->index()));
if (instr->hydrogen()->length()->representation().IsTagged()) {
if (instr->hydrogen()->length()->representation().IsSmi()) {
__ Cmp(reg, Smi::FromInt(constant_index));
} else {
__ cmpq(reg, Immediate(constant_index));
}
} else {
Register reg2 = ToRegister(instr->index());
if (!instr->hydrogen()->index()->representation().IsTagged()) {
if (!instr->hydrogen()->index()->representation().IsSmi()) {
__ AssertZeroExtended(reg2);
}
__ cmpq(reg, reg2);
@ -4065,7 +4065,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
if (instr->index()->IsConstantOperand()) {
int constant_index =
ToInteger32(LConstantOperand::cast(instr->index()));
if (instr->hydrogen()->length()->representation().IsTagged()) {
if (instr->hydrogen()->length()->representation().IsSmi()) {
__ Cmp(length, Smi::FromInt(constant_index));
} else {
__ cmpq(length, Immediate(constant_index));
@ -4088,7 +4088,7 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
// gets replaced during bound check elimination with the index
// argument to the bounds check, which can be tagged, so that case
// must be handled here, too.
if (instr->hydrogen()->key()->representation().IsTagged()) {
if (instr->hydrogen()->key()->representation().IsSmi()) {
__ SmiToInteger64(key_reg, key_reg);
} else if (instr->hydrogen()->IsDehoisted()) {
// Sign extend key because it could be a 32 bit negative value
@ -4152,7 +4152,7 @@ void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
// input gets replaced during bound check elimination with the index
// argument to the bounds check, which can be tagged, so that case
// must be handled here, too.
if (instr->hydrogen()->key()->representation().IsTagged()) {
if (instr->hydrogen()->key()->representation().IsSmi()) {
__ SmiToInteger64(key_reg, key_reg);
} else if (instr->hydrogen()->IsDehoisted()) {
// Sign extend key because it could be a 32 bit negative value
@ -4195,7 +4195,7 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
// input gets replaced during bound check elimination with the index
// argument to the bounds check, which can be tagged, so that case
// must be handled here, too.
if (instr->hydrogen()->key()->representation().IsTagged()) {
if (instr->hydrogen()->key()->representation().IsSmi()) {
__ SmiToInteger64(key_reg, key_reg);
} else if (instr->hydrogen()->IsDehoisted()) {
// Sign extend key because it could be a 32 bit negative value

View File

@ -1946,12 +1946,6 @@ LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
}
LInstruction* LChunkBuilder::DoCheckSmiOrInt32(HCheckSmiOrInt32* instr) {
LOperand* value = UseRegisterAtStart(instr->value());
return AssignEnvironment(new(zone()) LCheckSmi(value));
}
LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
LOperand* value = UseRegisterAtStart(instr->value());
return AssignEnvironment(new(zone()) LCheckFunction(value));
@ -1998,7 +1992,7 @@ LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
} else if (r.IsDouble()) {
LOperand* temp = TempRegister();
return DefineAsRegister(new(zone()) LConstantD(temp));
} else if (r.IsTagged()) {
} else if (r.IsSmiOrTagged()) {
return DefineAsRegister(new(zone()) LConstantT);
} else {
UNREACHABLE();
@ -2113,9 +2107,9 @@ LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged());
instr->key()->representation().IsSmi());
ElementsKind elements_kind = instr->elements_kind();
bool clobbers_key = instr->key()->representation().IsTagged();
bool clobbers_key = instr->key()->representation().IsSmi();
LOperand* key = clobbers_key
? UseTempRegister(instr->key())
: UseRegisterOrConstantAtStart(instr->key());
@ -2156,7 +2150,7 @@ LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
ElementsKind elements_kind = instr->elements_kind();
bool clobbers_key = instr->key()->representation().IsTagged();
bool clobbers_key = instr->key()->representation().IsSmi();
if (!instr->is_external()) {
ASSERT(instr->elements()->representation().IsTagged());