From 9641c25573ef6e78f8644d3c2a09a922b768b996 Mon Sep 17 00:00:00 2001 From: "danno@chromium.org" Date: Tue, 31 Jul 2012 08:44:51 +0000 Subject: [PATCH] Improve constant element index access code generation R=jkummerow@chromium.org Review URL: https://chromiumcodereview.appspot.com/10831049 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12232 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/lithium-arm.cc | 4 +-- src/arm/lithium-codegen-arm.cc | 55 ++++++++++++++++++++++++++++------------ src/hydrogen-instructions.h | 22 ++++++++++++---- src/hydrogen.cc | 3 ++- src/ia32/lithium-codegen-ia32.cc | 14 ++++++++-- src/x64/lithium-codegen-x64.cc | 33 ++++++++++++++++++++++-- 6 files changed, 103 insertions(+), 28 deletions(-) diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index 91afec5..0dda5bd 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc @@ -1546,7 +1546,7 @@ LInstruction* LChunkBuilder::DoDateField(HDateField* instr) { LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { - LOperand* value = UseRegisterAtStart(instr->index()); + LOperand* value = UseRegisterOrConstantAtStart(instr->index()); LOperand* length = UseRegister(instr->length()); return AssignEnvironment(new(zone()) LBoundsCheck(value, length)); } @@ -1838,7 +1838,7 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement( ASSERT(instr->key()->representation().IsInteger32() || instr->key()->representation().IsTagged()); LOperand* obj = UseRegisterAtStart(instr->object()); - LOperand* key = UseRegisterAtStart(instr->key()); + LOperand* key = UseRegisterOrConstantAtStart(instr->key()); LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj, key); if (instr->RequiresHoleCheck()) AssignEnvironment(result); return DefineAsRegister(result); diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index 7e138cb..d915c7d 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -2779,20 +2779,31 @@ void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { Register elements = ToRegister(instr->elements()); - Register key = EmitLoadRegister(instr->key(), scratch0()); Register result = ToRegister(instr->result()); Register scratch = scratch0(); - // Load the result. - if (instr->hydrogen()->key()->representation().IsTagged()) { - __ add(scratch, elements, - Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize)); + if (instr->key()->IsConstantOperand()) { + LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); + int offset = + (ToInteger32(const_operand) + instr->additional_index()) * kPointerSize + + FixedArray::kHeaderSize; + __ ldr(result, FieldMemOperand(elements, offset)); } else { - __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); + Register key = EmitLoadRegister(instr->key(), scratch0()); + // Even though the HLoadKeyedFastElement instruction forces the input + // 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()) { + __ add(scratch, elements, + Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize)); + } else { + __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); + } + uint32_t offset = FixedArray::kHeaderSize + + (instr->additional_index() << kPointerSizeLog2); + __ ldr(result, FieldMemOperand(scratch, offset)); } - uint32_t offset = FixedArray::kHeaderSize + - (instr->additional_index() << kPointerSizeLog2); - __ ldr(result, FieldMemOperand(scratch, offset)); // Check for the hole value. if (instr->hydrogen()->RequiresHoleCheck()) { @@ -3817,7 +3828,18 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { - __ cmp(ToRegister(instr->index()), ToRegister(instr->length())); + if (instr->index()->IsConstantOperand()) { + int constant_index = + ToInteger32(LConstantOperand::cast(instr->index())); + if (instr->hydrogen()->length()->representation().IsTagged()) { + __ mov(ip, Operand(Smi::FromInt(constant_index))); + } else { + __ mov(ip, Operand(constant_index)); + } + __ cmp(ip, ToRegister(instr->length())); + } else { + __ cmp(ToRegister(instr->index()), ToRegister(instr->length())); + } DeoptimizeIf(hs, instr->environment()); } @@ -3837,18 +3859,19 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { + FixedArray::kHeaderSize; __ str(value, FieldMemOperand(elements, offset)); } else { + // Even though the HLoadKeyedFastElement instruction forces the input + // 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()) { __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize)); } else { __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); } - if (instr->additional_index() != 0) { - __ add(scratch, - scratch, - Operand(instr->additional_index() << kPointerSizeLog2)); - } - __ str(value, FieldMemOperand(scratch, FixedArray::kHeaderSize)); + uint32_t offset = FixedArray::kHeaderSize + + (instr->additional_index() << kPointerSizeLog2); + __ str(value, FieldMemOperand(scratch, offset)); } if (instr->hydrogen()->NeedsWriteBarrier()) { diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index c2cb271..a4377de 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -2776,13 +2776,25 @@ class HBoundsCheck: public HTemplateInstruction<2> { } virtual Representation RequiredInputRepresentation(int arg_index) { - if (index()->representation().IsTagged() && - !index()->IsConstant() && - key_mode_ == ALLOW_SMI_KEY) { - return Representation::Tagged(); - } else { + if (key_mode_ == DONT_ALLOW_SMI_KEY || + !length()->representation().IsTagged()) { return Representation::Integer32(); } + // If the index is tagged and isn't constant, then 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. + if (index()->representation().IsTagged() && !index()->IsConstant()) { + return Representation::Tagged(); + } + // Also allow the length to be tagged if the index is constant, because + // it can be tagged to allow direct comparison. + if (index()->IsConstant() && + index()->representation().IsInteger32() && + arg_index == 1) { + return Representation::Tagged(); + } + return Representation::Integer32(); } virtual void PrintDataTo(StringStream* stream); diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 73c9173..7d3f1f3 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -5900,7 +5900,8 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( } else { length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); } - checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); + checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length, + ALLOW_SMI_KEY)); return BuildFastElementAccess(elements, checked_key, val, mapcheck, map->elements_kind(), is_store); } diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index 36d9146..8869a3e 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -2705,6 +2705,10 @@ Operand LCodeGen::BuildFastArrayOperand( uint32_t additional_index) { Register elements_pointer_reg = ToRegister(elements_pointer); int shift_size = ElementsKindToShiftSize(elements_kind); + // Even though the HLoad/StoreKeyedFastElement instructions force the input + // 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 (key_representation.IsTagged() && (shift_size >= 1)) { shift_size -= kSmiTagSize; } @@ -3672,8 +3676,14 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { if (instr->index()->IsConstantOperand()) { - __ cmp(ToOperand(instr->length()), - Immediate(ToInteger32(LConstantOperand::cast(instr->index())))); + int constant_index = + ToInteger32(LConstantOperand::cast(instr->index())); + if (instr->hydrogen()->length()->representation().IsTagged()) { + __ cmp(ToOperand(instr->length()), + Immediate(Smi::FromInt(constant_index))); + } else { + __ cmp(ToOperand(instr->length()), Immediate(constant_index)); + } DeoptimizeIf(below_equal, instr->environment()); } else { __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index 36de28f..1caf110 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -2506,6 +2506,10 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { LOperand* key = instr->key(); if (!key->IsConstantOperand()) { Register key_reg = ToRegister(key); + // Even though the HLoad/StoreKeyedFastElement instructions force the input + // 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()) { __ SmiToInteger64(key_reg, key_reg); } else if (instr->hydrogen()->IsDehoisted()) { @@ -2542,6 +2546,10 @@ void LCodeGen::DoLoadKeyedFastDoubleElement( LOperand* key = instr->key(); if (!key->IsConstantOperand()) { Register key_reg = ToRegister(key); + // Even though the HLoad/StoreKeyedFastElement instructions force the input + // 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()) { __ SmiToInteger64(key_reg, key_reg); } else if (instr->hydrogen()->IsDehoisted()) { @@ -2606,6 +2614,10 @@ void LCodeGen::DoLoadKeyedSpecializedArrayElement( LOperand* key = instr->key(); if (!key->IsConstantOperand()) { Register key_reg = ToRegister(key); + // Even though the HLoad/StoreKeyedFastElement instructions force the input + // 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()) { __ SmiToInteger64(key_reg, key_reg); } else if (instr->hydrogen()->IsDehoisted()) { @@ -3549,6 +3561,10 @@ void LCodeGen::DoStoreKeyedSpecializedArrayElement( LOperand* key = instr->key(); if (!key->IsConstantOperand()) { Register key_reg = ToRegister(key); + // Even though the HLoad/StoreKeyedFastElement instructions force the input + // 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()) { __ SmiToInteger64(key_reg, key_reg); } else if (instr->hydrogen()->IsDehoisted()) { @@ -3611,8 +3627,13 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { __ AbortIfNotZeroExtended(reg); } if (instr->index()->IsConstantOperand()) { - __ cmpq(reg, - Immediate(ToInteger32(LConstantOperand::cast(instr->index())))); + int constant_index = + ToInteger32(LConstantOperand::cast(instr->index())); + if (instr->hydrogen()->length()->representation().IsTagged()) { + __ Cmp(reg, Smi::FromInt(constant_index)); + } else { + __ cmpq(reg, Immediate(constant_index)); + } } else { Register reg2 = ToRegister(instr->index()); if (FLAG_debug_code && @@ -3639,6 +3660,10 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { LOperand* key = instr->key(); if (!key->IsConstantOperand()) { Register key_reg = ToRegister(key); + // Even though the HLoad/StoreKeyedFastElement instructions force the input + // 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()) { __ SmiToInteger64(key_reg, key_reg); } else if (instr->hydrogen()->IsDehoisted()) { @@ -3682,6 +3707,10 @@ void LCodeGen::DoStoreKeyedFastDoubleElement( LOperand* key = instr->key(); if (!key->IsConstantOperand()) { Register key_reg = ToRegister(key); + // Even though the HLoad/StoreKeyedFastElement instructions force the input + // 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()) { __ SmiToInteger64(key_reg, key_reg); } else if (instr->hydrogen()->IsDehoisted()) { -- 2.7.4