Commit 8c89cc4c authored by danno@chromium.org's avatar danno@chromium.org

Optimize Smi keys for KeyedLoads

Allows KeyeLoad/KeyedStore operations where the key is a Smi to fold the untagging of the key into the element offset calculation.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12156 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent c09a1370
...@@ -1835,7 +1835,8 @@ LInstruction* LChunkBuilder::DoLoadExternalArrayPointer( ...@@ -1835,7 +1835,8 @@ LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
LInstruction* LChunkBuilder::DoLoadKeyedFastElement( LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
HLoadKeyedFastElement* instr) { HLoadKeyedFastElement* instr) {
ASSERT(instr->representation().IsTagged()); ASSERT(instr->representation().IsTagged());
ASSERT(instr->key()->representation().IsInteger32()); ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged());
LOperand* obj = UseRegisterAtStart(instr->object()); LOperand* obj = UseRegisterAtStart(instr->object());
LOperand* key = UseRegisterAtStart(instr->key()); LOperand* key = UseRegisterAtStart(instr->key());
LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj, key); LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj, key);
...@@ -1847,7 +1848,8 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement( ...@@ -1847,7 +1848,8 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement( LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
HLoadKeyedFastDoubleElement* instr) { HLoadKeyedFastDoubleElement* instr) {
ASSERT(instr->representation().IsDouble()); ASSERT(instr->representation().IsDouble());
ASSERT(instr->key()->representation().IsInteger32()); ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged());
LOperand* elements = UseTempRegister(instr->elements()); LOperand* elements = UseTempRegister(instr->elements());
LOperand* key = UseRegisterOrConstantAtStart(instr->key()); LOperand* key = UseRegisterOrConstantAtStart(instr->key());
LLoadKeyedFastDoubleElement* result = LLoadKeyedFastDoubleElement* result =
...@@ -1866,7 +1868,8 @@ LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement( ...@@ -1866,7 +1868,8 @@ LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
(instr->representation().IsDouble() && (instr->representation().IsDouble() &&
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) || ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS)))); (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
ASSERT(instr->key()->representation().IsInteger32()); ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged());
LOperand* external_pointer = UseRegister(instr->external_pointer()); LOperand* external_pointer = UseRegister(instr->external_pointer());
LOperand* key = UseRegisterOrConstant(instr->key()); LOperand* key = UseRegisterOrConstant(instr->key());
LLoadKeyedSpecializedArrayElement* result = LLoadKeyedSpecializedArrayElement* result =
...@@ -1894,7 +1897,8 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement( ...@@ -1894,7 +1897,8 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
bool needs_write_barrier = instr->NeedsWriteBarrier(); bool needs_write_barrier = instr->NeedsWriteBarrier();
ASSERT(instr->value()->representation().IsTagged()); ASSERT(instr->value()->representation().IsTagged());
ASSERT(instr->object()->representation().IsTagged()); ASSERT(instr->object()->representation().IsTagged());
ASSERT(instr->key()->representation().IsInteger32()); ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged());
LOperand* obj = UseTempRegister(instr->object()); LOperand* obj = UseTempRegister(instr->object());
LOperand* val = needs_write_barrier LOperand* val = needs_write_barrier
...@@ -1911,7 +1915,8 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement( ...@@ -1911,7 +1915,8 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
HStoreKeyedFastDoubleElement* instr) { HStoreKeyedFastDoubleElement* instr) {
ASSERT(instr->value()->representation().IsDouble()); ASSERT(instr->value()->representation().IsDouble());
ASSERT(instr->elements()->representation().IsTagged()); ASSERT(instr->elements()->representation().IsTagged());
ASSERT(instr->key()->representation().IsInteger32()); ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged());
LOperand* elements = UseRegisterAtStart(instr->elements()); LOperand* elements = UseRegisterAtStart(instr->elements());
LOperand* val = UseTempRegister(instr->value()); LOperand* val = UseTempRegister(instr->value());
...@@ -1932,7 +1937,8 @@ LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement( ...@@ -1932,7 +1937,8 @@ LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) || ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS)))); (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
ASSERT(instr->external_pointer()->representation().IsExternal()); ASSERT(instr->external_pointer()->representation().IsExternal());
ASSERT(instr->key()->representation().IsInteger32()); ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged());
LOperand* external_pointer = UseRegister(instr->external_pointer()); LOperand* external_pointer = UseRegister(instr->external_pointer());
bool val_is_temp_register = bool val_is_temp_register =
......
...@@ -859,6 +859,7 @@ class LBoundsCheck: public LTemplateInstruction<0, 2, 0> { ...@@ -859,6 +859,7 @@ class LBoundsCheck: public LTemplateInstruction<0, 2, 0> {
LOperand* length() { return inputs_[1]; } LOperand* length() { return inputs_[1]; }
DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check") DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check")
DECLARE_HYDROGEN_ACCESSOR(BoundsCheck)
}; };
......
...@@ -2784,7 +2784,12 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { ...@@ -2784,7 +2784,12 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
Register scratch = scratch0(); Register scratch = scratch0();
// Load the result. // Load the result.
__ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); 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 + uint32_t offset = FixedArray::kHeaderSize +
(instr->additional_index() << kPointerSizeLog2); (instr->additional_index() << kPointerSizeLog2);
__ ldr(result, FieldMemOperand(scratch, offset)); __ ldr(result, FieldMemOperand(scratch, offset));
...@@ -2811,8 +2816,9 @@ void LCodeGen::DoLoadKeyedFastDoubleElement( ...@@ -2811,8 +2816,9 @@ void LCodeGen::DoLoadKeyedFastDoubleElement(
DwVfpRegister result = ToDoubleRegister(instr->result()); DwVfpRegister result = ToDoubleRegister(instr->result());
Register scratch = scratch0(); Register scratch = scratch0();
int shift_size = int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS); int shift_size = (instr->hydrogen()->key()->representation().IsTagged())
? (element_size_shift - kSmiTagSize) : element_size_shift;
int constant_key = 0; int constant_key = 0;
if (key_is_constant) { if (key_is_constant) {
constant_key = ToInteger32(LConstantOperand::cast(instr->key())); constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
...@@ -2824,14 +2830,15 @@ void LCodeGen::DoLoadKeyedFastDoubleElement( ...@@ -2824,14 +2830,15 @@ void LCodeGen::DoLoadKeyedFastDoubleElement(
} }
Operand operand = key_is_constant Operand operand = key_is_constant
? Operand(((constant_key + instr->additional_index()) << shift_size) + ? Operand(((constant_key + instr->additional_index()) <<
element_size_shift) +
FixedDoubleArray::kHeaderSize - kHeapObjectTag) FixedDoubleArray::kHeaderSize - kHeapObjectTag)
: Operand(key, LSL, shift_size); : Operand(key, LSL, shift_size);
__ add(elements, elements, operand); __ add(elements, elements, operand);
if (!key_is_constant) { if (!key_is_constant) {
__ add(elements, elements, __ add(elements, elements,
Operand((FixedDoubleArray::kHeaderSize - kHeapObjectTag) + Operand((FixedDoubleArray::kHeaderSize - kHeapObjectTag) +
(instr->additional_index() << shift_size))); (instr->additional_index() << element_size_shift)));
} }
if (instr->hydrogen()->RequiresHoleCheck()) { if (instr->hydrogen()->RequiresHoleCheck()) {
...@@ -2844,6 +2851,42 @@ void LCodeGen::DoLoadKeyedFastDoubleElement( ...@@ -2844,6 +2851,42 @@ void LCodeGen::DoLoadKeyedFastDoubleElement(
} }
MemOperand LCodeGen::PrepareKeyedOperand(Register key,
Register base,
bool key_is_constant,
int constant_key,
int element_size,
int shift_size,
int additional_index,
int additional_offset) {
if (additional_index != 0 && !key_is_constant) {
additional_index *= 1 << (element_size - shift_size);
__ add(scratch0(), key, Operand(additional_index));
}
if (key_is_constant) {
return MemOperand(base,
(constant_key << element_size) + additional_offset);
}
if (additional_index == 0) {
if (shift_size >= 0) {
return MemOperand(base, key, LSL, shift_size);
} else {
ASSERT_EQ(-1, shift_size);
return MemOperand(base, key, LSR, 1);
}
}
if (shift_size >= 0) {
return MemOperand(base, scratch0(), LSL, shift_size);
} else {
ASSERT_EQ(-1, shift_size);
return MemOperand(base, scratch0(), LSR, 1);
}
}
void LCodeGen::DoLoadKeyedSpecializedArrayElement( void LCodeGen::DoLoadKeyedSpecializedArrayElement(
LLoadKeyedSpecializedArrayElement* instr) { LLoadKeyedSpecializedArrayElement* instr) {
Register external_pointer = ToRegister(instr->external_pointer()); Register external_pointer = ToRegister(instr->external_pointer());
...@@ -2859,15 +2902,17 @@ void LCodeGen::DoLoadKeyedSpecializedArrayElement( ...@@ -2859,15 +2902,17 @@ void LCodeGen::DoLoadKeyedSpecializedArrayElement(
} else { } else {
key = ToRegister(instr->key()); key = ToRegister(instr->key());
} }
int shift_size = ElementsKindToShiftSize(elements_kind); int element_size_shift = ElementsKindToShiftSize(elements_kind);
int additional_offset = instr->additional_index() << shift_size; int shift_size = (instr->hydrogen()->key()->representation().IsTagged())
? (element_size_shift - kSmiTagSize) : element_size_shift;
int additional_offset = instr->additional_index() << element_size_shift;
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
CpuFeatures::Scope scope(VFP3); CpuFeatures::Scope scope(VFP3);
DwVfpRegister result = ToDoubleRegister(instr->result()); DwVfpRegister result = ToDoubleRegister(instr->result());
Operand operand = key_is_constant Operand operand = key_is_constant
? Operand(constant_key << shift_size) ? Operand(constant_key << element_size_shift)
: Operand(key, LSL, shift_size); : Operand(key, LSL, shift_size);
__ add(scratch0(), external_pointer, operand); __ add(scratch0(), external_pointer, operand);
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
...@@ -2878,15 +2923,10 @@ void LCodeGen::DoLoadKeyedSpecializedArrayElement( ...@@ -2878,15 +2923,10 @@ void LCodeGen::DoLoadKeyedSpecializedArrayElement(
} }
} else { } else {
Register result = ToRegister(instr->result()); Register result = ToRegister(instr->result());
if (instr->additional_index() != 0 && !key_is_constant) { MemOperand mem_operand = PrepareKeyedOperand(
__ add(scratch0(), key, Operand(instr->additional_index())); key, external_pointer, key_is_constant, constant_key,
} element_size_shift, shift_size,
MemOperand mem_operand(key_is_constant instr->additional_index(), additional_offset);
? MemOperand(external_pointer,
(constant_key << shift_size) + additional_offset)
: (instr->additional_index() == 0
? MemOperand(external_pointer, key, LSL, shift_size)
: MemOperand(external_pointer, scratch0(), LSL, shift_size)));
switch (elements_kind) { switch (elements_kind) {
case EXTERNAL_BYTE_ELEMENTS: case EXTERNAL_BYTE_ELEMENTS:
__ ldrsb(result, mem_operand); __ ldrsb(result, mem_operand);
...@@ -3803,7 +3843,12 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { ...@@ -3803,7 +3843,12 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
+ FixedArray::kHeaderSize; + FixedArray::kHeaderSize;
__ str(value, FieldMemOperand(elements, offset)); __ str(value, FieldMemOperand(elements, offset));
} else { } else {
__ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); 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) { if (instr->additional_index() != 0) {
__ add(scratch, __ add(scratch,
scratch, scratch,
...@@ -3848,9 +3893,11 @@ void LCodeGen::DoStoreKeyedFastDoubleElement( ...@@ -3848,9 +3893,11 @@ void LCodeGen::DoStoreKeyedFastDoubleElement(
} else { } else {
key = ToRegister(instr->key()); key = ToRegister(instr->key());
} }
int shift_size = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS); int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
int shift_size = (instr->hydrogen()->key()->representation().IsTagged())
? (element_size_shift - kSmiTagSize) : element_size_shift;
Operand operand = key_is_constant Operand operand = key_is_constant
? Operand((constant_key << shift_size) + ? Operand((constant_key << element_size_shift) +
FixedDoubleArray::kHeaderSize - kHeapObjectTag) FixedDoubleArray::kHeaderSize - kHeapObjectTag)
: Operand(key, LSL, shift_size); : Operand(key, LSL, shift_size);
__ add(scratch, elements, operand); __ add(scratch, elements, operand);
...@@ -3868,7 +3915,7 @@ void LCodeGen::DoStoreKeyedFastDoubleElement( ...@@ -3868,7 +3915,7 @@ void LCodeGen::DoStoreKeyedFastDoubleElement(
vs); vs);
} }
__ vstr(value, scratch, instr->additional_index() << shift_size); __ vstr(value, scratch, instr->additional_index() << element_size_shift);
} }
...@@ -3888,15 +3935,18 @@ void LCodeGen::DoStoreKeyedSpecializedArrayElement( ...@@ -3888,15 +3935,18 @@ void LCodeGen::DoStoreKeyedSpecializedArrayElement(
} else { } else {
key = ToRegister(instr->key()); key = ToRegister(instr->key());
} }
int shift_size = ElementsKindToShiftSize(elements_kind); int element_size_shift = ElementsKindToShiftSize(elements_kind);
int additional_offset = instr->additional_index() << shift_size; int shift_size = (instr->hydrogen()->key()->representation().IsTagged())
? (element_size_shift - kSmiTagSize) : element_size_shift;
int additional_offset = instr->additional_index() << element_size_shift;
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
CpuFeatures::Scope scope(VFP3); CpuFeatures::Scope scope(VFP3);
DwVfpRegister value(ToDoubleRegister(instr->value())); DwVfpRegister value(ToDoubleRegister(instr->value()));
Operand operand(key_is_constant ? Operand(constant_key << shift_size) Operand operand(key_is_constant
: Operand(key, LSL, shift_size)); ? Operand(constant_key << element_size_shift)
: Operand(key, LSL, shift_size));
__ add(scratch0(), external_pointer, operand); __ add(scratch0(), external_pointer, operand);
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
__ vcvt_f32_f64(double_scratch0().low(), value); __ vcvt_f32_f64(double_scratch0().low(), value);
...@@ -3906,16 +3956,10 @@ void LCodeGen::DoStoreKeyedSpecializedArrayElement( ...@@ -3906,16 +3956,10 @@ void LCodeGen::DoStoreKeyedSpecializedArrayElement(
} }
} else { } else {
Register value(ToRegister(instr->value())); Register value(ToRegister(instr->value()));
if (instr->additional_index() != 0 && !key_is_constant) { MemOperand mem_operand = PrepareKeyedOperand(
__ add(scratch0(), key, Operand(instr->additional_index())); key, external_pointer, key_is_constant, constant_key,
} element_size_shift, shift_size,
MemOperand mem_operand(key_is_constant instr->additional_index(), additional_offset);
? MemOperand(external_pointer,
((constant_key + instr->additional_index())
<< shift_size))
: (instr->additional_index() == 0
? MemOperand(external_pointer, key, LSL, shift_size)
: MemOperand(external_pointer, scratch0(), LSL, shift_size)));
switch (elements_kind) { switch (elements_kind) {
case EXTERNAL_PIXEL_ELEMENTS: case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_BYTE_ELEMENTS: case EXTERNAL_BYTE_ELEMENTS:
......
...@@ -132,6 +132,15 @@ class LCodeGen BASE_EMBEDDED { ...@@ -132,6 +132,15 @@ class LCodeGen BASE_EMBEDDED {
void DoParallelMove(LParallelMove* move); void DoParallelMove(LParallelMove* move);
void DoGap(LGap* instr); void DoGap(LGap* instr);
MemOperand PrepareKeyedOperand(Register key,
Register base,
bool key_is_constant,
int constant_key,
int element_size,
int shift_size,
int additional_index,
int additional_offset);
// Emit frame translation commands for an environment. // Emit frame translation commands for an environment.
void WriteTranslation(LEnvironment* environment, Translation* translation); void WriteTranslation(LEnvironment* environment, Translation* translation);
......
...@@ -1888,6 +1888,7 @@ class HJSArrayLength: public HTemplateInstruction<2> { ...@@ -1888,6 +1888,7 @@ class HJSArrayLength: public HTemplateInstruction<2> {
class HFixedArrayBaseLength: public HUnaryOperation { class HFixedArrayBaseLength: public HUnaryOperation {
public: public:
explicit HFixedArrayBaseLength(HValue* value) : HUnaryOperation(value) { explicit HFixedArrayBaseLength(HValue* value) : HUnaryOperation(value) {
set_type(HType::Smi());
set_representation(Representation::Tagged()); set_representation(Representation::Tagged());
SetFlag(kUseGVN); SetFlag(kUseGVN);
SetGVNFlag(kDependsOnArrayLengths); SetGVNFlag(kDependsOnArrayLengths);
...@@ -2757,17 +2758,31 @@ class HAccessArgumentsAt: public HTemplateInstruction<3> { ...@@ -2757,17 +2758,31 @@ class HAccessArgumentsAt: public HTemplateInstruction<3> {
}; };
enum BoundsCheckKeyMode {
DONT_ALLOW_SMI_KEY,
ALLOW_SMI_KEY
};
class HBoundsCheck: public HTemplateInstruction<2> { class HBoundsCheck: public HTemplateInstruction<2> {
public: public:
HBoundsCheck(HValue* index, HValue* length) { HBoundsCheck(HValue* index, HValue* length,
BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY)
: key_mode_(key_mode) {
SetOperandAt(0, index); SetOperandAt(0, index);
SetOperandAt(1, length); SetOperandAt(1, length);
set_representation(Representation::Integer32()); set_representation(Representation::Integer32());
SetFlag(kUseGVN); SetFlag(kUseGVN);
} }
virtual Representation RequiredInputRepresentation(int index) { virtual Representation RequiredInputRepresentation(int arg_index) {
return Representation::Integer32(); if (index()->representation().IsTagged() &&
!index()->IsConstant() &&
key_mode_ == ALLOW_SMI_KEY) {
return Representation::Tagged();
} else {
return Representation::Integer32();
}
} }
virtual void PrintDataTo(StringStream* stream); virtual void PrintDataTo(StringStream* stream);
...@@ -2779,6 +2794,7 @@ class HBoundsCheck: public HTemplateInstruction<2> { ...@@ -2779,6 +2794,7 @@ class HBoundsCheck: public HTemplateInstruction<2> {
protected: protected:
virtual bool DataEquals(HValue* other) { return true; } virtual bool DataEquals(HValue* other) { return true; }
BoundsCheckKeyMode key_mode_;
}; };
......
...@@ -5842,7 +5842,8 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( ...@@ -5842,7 +5842,8 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
HInstruction* checked_key = NULL; HInstruction* checked_key = NULL;
if (map->has_external_array_elements()) { if (map->has_external_array_elements()) {
length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); 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));
HLoadExternalArrayPointer* external_elements = HLoadExternalArrayPointer* external_elements =
new(zone()) HLoadExternalArrayPointer(elements); new(zone()) HLoadExternalArrayPointer(elements);
AddInstruction(external_elements); AddInstruction(external_elements);
...@@ -6077,7 +6078,8 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object, ...@@ -6077,7 +6078,8 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
HInstruction* length; HInstruction* length;
length = AddInstruction(new(zone()) HJSArrayLength(object, typecheck, length = AddInstruction(new(zone()) HJSArrayLength(object, typecheck,
HType::Smi())); HType::Smi()));
checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length,
ALLOW_SMI_KEY));
access = AddInstruction(BuildFastElementAccess( access = AddInstruction(BuildFastElementAccess(
elements, checked_key, val, elements_kind, is_store)); elements, checked_key, val, elements_kind, is_store));
if (!is_store) { if (!is_store) {
...@@ -6092,7 +6094,8 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object, ...@@ -6092,7 +6094,8 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
set_current_block(if_fastobject); set_current_block(if_fastobject);
length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); 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));
access = AddInstruction(BuildFastElementAccess( access = AddInstruction(BuildFastElementAccess(
elements, checked_key, val, elements_kind, is_store)); elements, checked_key, val, elements_kind, is_store));
} else if (elements_kind == DICTIONARY_ELEMENTS) { } else if (elements_kind == DICTIONARY_ELEMENTS) {
......
...@@ -2650,6 +2650,7 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { ...@@ -2650,6 +2650,7 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
__ mov(result, __ mov(result,
BuildFastArrayOperand(instr->elements(), BuildFastArrayOperand(instr->elements(),
instr->key(), instr->key(),
instr->hydrogen()->key()->representation(),
FAST_ELEMENTS, FAST_ELEMENTS,
FixedArray::kHeaderSize - kHeapObjectTag, FixedArray::kHeaderSize - kHeapObjectTag,
instr->additional_index())); instr->additional_index()));
...@@ -2676,6 +2677,7 @@ void LCodeGen::DoLoadKeyedFastDoubleElement( ...@@ -2676,6 +2677,7 @@ void LCodeGen::DoLoadKeyedFastDoubleElement(
sizeof(kHoleNanLower32); sizeof(kHoleNanLower32);
Operand hole_check_operand = BuildFastArrayOperand( Operand hole_check_operand = BuildFastArrayOperand(
instr->elements(), instr->key(), instr->elements(), instr->key(),
instr->hydrogen()->key()->representation(),
FAST_DOUBLE_ELEMENTS, FAST_DOUBLE_ELEMENTS,
offset, offset,
instr->additional_index()); instr->additional_index());
...@@ -2686,6 +2688,7 @@ void LCodeGen::DoLoadKeyedFastDoubleElement( ...@@ -2686,6 +2688,7 @@ void LCodeGen::DoLoadKeyedFastDoubleElement(
Operand double_load_operand = BuildFastArrayOperand( Operand double_load_operand = BuildFastArrayOperand(
instr->elements(), instr->elements(),
instr->key(), instr->key(),
instr->hydrogen()->key()->representation(),
FAST_DOUBLE_ELEMENTS, FAST_DOUBLE_ELEMENTS,
FixedDoubleArray::kHeaderSize - kHeapObjectTag, FixedDoubleArray::kHeaderSize - kHeapObjectTag,
instr->additional_index()); instr->additional_index());
...@@ -2696,11 +2699,15 @@ void LCodeGen::DoLoadKeyedFastDoubleElement( ...@@ -2696,11 +2699,15 @@ void LCodeGen::DoLoadKeyedFastDoubleElement(
Operand LCodeGen::BuildFastArrayOperand( Operand LCodeGen::BuildFastArrayOperand(
LOperand* elements_pointer, LOperand* elements_pointer,
LOperand* key, LOperand* key,
Representation key_representation,
ElementsKind elements_kind, ElementsKind elements_kind,
uint32_t offset, uint32_t offset,
uint32_t additional_index) { uint32_t additional_index) {
Register elements_pointer_reg = ToRegister(elements_pointer); Register elements_pointer_reg = ToRegister(elements_pointer);
int shift_size = ElementsKindToShiftSize(elements_kind); int shift_size = ElementsKindToShiftSize(elements_kind);
if (key_representation.IsTagged() && (shift_size >= 1)) {
shift_size -= kSmiTagSize;
}
if (key->IsConstantOperand()) { if (key->IsConstantOperand()) {
int constant_value = ToInteger32(LConstantOperand::cast(key)); int constant_value = ToInteger32(LConstantOperand::cast(key));
if (constant_value & 0xF0000000) { if (constant_value & 0xF0000000) {
...@@ -2722,11 +2729,19 @@ Operand LCodeGen::BuildFastArrayOperand( ...@@ -2722,11 +2729,19 @@ Operand LCodeGen::BuildFastArrayOperand(
void LCodeGen::DoLoadKeyedSpecializedArrayElement( void LCodeGen::DoLoadKeyedSpecializedArrayElement(
LLoadKeyedSpecializedArrayElement* instr) { LLoadKeyedSpecializedArrayElement* instr) {
ElementsKind elements_kind = instr->elements_kind(); ElementsKind elements_kind = instr->elements_kind();
Operand operand(BuildFastArrayOperand(instr->external_pointer(), LOperand* key = instr->key();
instr->key(), if (!key->IsConstantOperand() &&
elements_kind, ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
0, elements_kind)) {
instr->additional_index())); __ SmiUntag(ToRegister(key));
}
Operand operand(BuildFastArrayOperand(
instr->external_pointer(),
key,
instr->hydrogen()->key()->representation(),
elements_kind,
0,
instr->additional_index()));
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
XMMRegister result(ToDoubleRegister(instr->result())); XMMRegister result(ToDoubleRegister(instr->result()));
__ movss(result, operand); __ movss(result, operand);
...@@ -3679,11 +3694,19 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { ...@@ -3679,11 +3694,19 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
void LCodeGen::DoStoreKeyedSpecializedArrayElement( void LCodeGen::DoStoreKeyedSpecializedArrayElement(
LStoreKeyedSpecializedArrayElement* instr) { LStoreKeyedSpecializedArrayElement* instr) {
ElementsKind elements_kind = instr->elements_kind(); ElementsKind elements_kind = instr->elements_kind();
Operand operand(BuildFastArrayOperand(instr->external_pointer(), LOperand* key = instr->key();
instr->key(), if (!key->IsConstantOperand() &&
elements_kind, ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
0, elements_kind)) {
instr->additional_index())); __ SmiUntag(ToRegister(key));
}
Operand operand(BuildFastArrayOperand(
instr->external_pointer(),
key,
instr->hydrogen()->key()->representation(),
elements_kind,
0,
instr->additional_index()));
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
__ cvtsd2ss(xmm0, ToDoubleRegister(instr->value())); __ cvtsd2ss(xmm0, ToDoubleRegister(instr->value()));
__ movss(operand, xmm0); __ movss(operand, xmm0);
...@@ -3730,6 +3753,7 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { ...@@ -3730,6 +3753,7 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
Operand operand = BuildFastArrayOperand( Operand operand = BuildFastArrayOperand(
instr->object(), instr->object(),
instr->key(), instr->key(),
instr->hydrogen()->key()->representation(),
FAST_ELEMENTS, FAST_ELEMENTS,
FixedArray::kHeaderSize - kHeapObjectTag, FixedArray::kHeaderSize - kHeapObjectTag,
instr->additional_index()); instr->additional_index());
...@@ -3771,6 +3795,7 @@ void LCodeGen::DoStoreKeyedFastDoubleElement( ...@@ -3771,6 +3795,7 @@ void LCodeGen::DoStoreKeyedFastDoubleElement(
Operand double_store_operand = BuildFastArrayOperand( Operand double_store_operand = BuildFastArrayOperand(
instr->elements(), instr->elements(),
instr->key(), instr->key(),
instr->hydrogen()->key()->representation(),
FAST_DOUBLE_ELEMENTS, FAST_DOUBLE_ELEMENTS,
FixedDoubleArray::kHeaderSize - kHeapObjectTag, FixedDoubleArray::kHeaderSize - kHeapObjectTag,
instr->additional_index()); instr->additional_index());
......
...@@ -246,6 +246,7 @@ class LCodeGen BASE_EMBEDDED { ...@@ -246,6 +246,7 @@ class LCodeGen BASE_EMBEDDED {
double ToDouble(LConstantOperand* op) const; double ToDouble(LConstantOperand* op) const;
Operand BuildFastArrayOperand(LOperand* elements_pointer, Operand BuildFastArrayOperand(LOperand* elements_pointer,
LOperand* key, LOperand* key,
Representation key_representation,
ElementsKind elements_kind, ElementsKind elements_kind,
uint32_t offset, uint32_t offset,
uint32_t additional_index = 0); uint32_t additional_index = 0);
......
...@@ -1900,7 +1900,8 @@ LInstruction* LChunkBuilder::DoLoadExternalArrayPointer( ...@@ -1900,7 +1900,8 @@ LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
LInstruction* LChunkBuilder::DoLoadKeyedFastElement( LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
HLoadKeyedFastElement* instr) { HLoadKeyedFastElement* instr) {
ASSERT(instr->representation().IsTagged()); ASSERT(instr->representation().IsTagged());
ASSERT(instr->key()->representation().IsInteger32()); ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged());
LOperand* obj = UseRegisterAtStart(instr->object()); LOperand* obj = UseRegisterAtStart(instr->object());
LOperand* key = UseRegisterOrConstantAtStart(instr->key()); LOperand* key = UseRegisterOrConstantAtStart(instr->key());
LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj, key); LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj, key);
...@@ -1912,7 +1913,8 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement( ...@@ -1912,7 +1913,8 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement( LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
HLoadKeyedFastDoubleElement* instr) { HLoadKeyedFastDoubleElement* instr) {
ASSERT(instr->representation().IsDouble()); ASSERT(instr->representation().IsDouble());
ASSERT(instr->key()->representation().IsInteger32()); ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged());
LOperand* elements = UseRegisterAtStart(instr->elements()); LOperand* elements = UseRegisterAtStart(instr->elements());
LOperand* key = UseRegisterOrConstantAtStart(instr->key()); LOperand* key = UseRegisterOrConstantAtStart(instr->key());
LLoadKeyedFastDoubleElement* result = LLoadKeyedFastDoubleElement* result =
...@@ -1931,11 +1933,17 @@ LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement( ...@@ -1931,11 +1933,17 @@ LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
(instr->representation().IsDouble() && (instr->representation().IsDouble() &&
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) || ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS)))); (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
ASSERT(instr->key()->representation().IsInteger32()); ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged());
LOperand* external_pointer = UseRegister(instr->external_pointer()); LOperand* external_pointer = UseRegister(instr->external_pointer());
LOperand* key = UseRegisterOrConstant(instr->key()); bool clobbers_key = ExternalArrayOpRequiresTemp(
instr->key()->representation(), elements_kind);
LOperand* key = clobbers_key
? UseTempRegister(instr->key())
: UseRegisterOrConstant(instr->key());
LLoadKeyedSpecializedArrayElement* result = LLoadKeyedSpecializedArrayElement* result =
new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key); new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key);
LInstruction* load_instr = DefineAsRegister(result); LInstruction* load_instr = DefineAsRegister(result);
// An unsigned int array load might overflow and cause a deopt, make sure it // An unsigned int array load might overflow and cause a deopt, make sure it
// has an environment. // has an environment.
...@@ -1961,7 +1969,8 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement( ...@@ -1961,7 +1969,8 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
bool needs_write_barrier = instr->NeedsWriteBarrier(); bool needs_write_barrier = instr->NeedsWriteBarrier();
ASSERT(instr->value()->representation().IsTagged()); ASSERT(instr->value()->representation().IsTagged());
ASSERT(instr->object()->representation().IsTagged()); ASSERT(instr->object()->representation().IsTagged());
ASSERT(instr->key()->representation().IsInteger32()); ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged());
LOperand* obj = UseRegister(instr->object()); LOperand* obj = UseRegister(instr->object());
LOperand* val = needs_write_barrier LOperand* val = needs_write_barrier
...@@ -1978,7 +1987,8 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement( ...@@ -1978,7 +1987,8 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
HStoreKeyedFastDoubleElement* instr) { HStoreKeyedFastDoubleElement* instr) {
ASSERT(instr->value()->representation().IsDouble()); ASSERT(instr->value()->representation().IsDouble());
ASSERT(instr->elements()->representation().IsTagged()); ASSERT(instr->elements()->representation().IsTagged());
ASSERT(instr->key()->representation().IsInteger32()); ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged());
LOperand* elements = UseRegisterAtStart(instr->elements()); LOperand* elements = UseRegisterAtStart(instr->elements());
LOperand* val = UseTempRegister(instr->value()); LOperand* val = UseTempRegister(instr->value());
...@@ -1999,10 +2009,10 @@ LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement( ...@@ -1999,10 +2009,10 @@ LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) || ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS)))); (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
ASSERT(instr->external_pointer()->representation().IsExternal()); ASSERT(instr->external_pointer()->representation().IsExternal());
ASSERT(instr->key()->representation().IsInteger32()); ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged());
LOperand* external_pointer = UseRegister(instr->external_pointer()); LOperand* external_pointer = UseRegister(instr->external_pointer());
LOperand* key = UseRegisterOrConstant(instr->key());
LOperand* val = NULL; LOperand* val = NULL;
if (elements_kind == EXTERNAL_BYTE_ELEMENTS || if (elements_kind == EXTERNAL_BYTE_ELEMENTS ||
elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS || elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS ||
...@@ -2012,7 +2022,11 @@ LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement( ...@@ -2012,7 +2022,11 @@ LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
} else { } else {
val = UseRegister(instr->value()); val = UseRegister(instr->value());
} }
bool clobbers_key = ExternalArrayOpRequiresTemp(
instr->key()->representation(), elements_kind);
LOperand* key = clobbers_key
? UseTempRegister(instr->key())
: UseRegisterOrConstant(instr->key());
return new(zone()) LStoreKeyedSpecializedArrayElement(external_pointer, return new(zone()) LStoreKeyedSpecializedArrayElement(external_pointer,
key, key,
val); val);
......
...@@ -872,6 +872,7 @@ class LBoundsCheck: public LTemplateInstruction<0, 2, 0> { ...@@ -872,6 +872,7 @@ class LBoundsCheck: public LTemplateInstruction<0, 2, 0> {
LOperand* length() { return inputs_[1]; } LOperand* length() { return inputs_[1]; }
DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check") DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check")
DECLARE_HYDROGEN_ACCESSOR(BoundsCheck)
}; };
...@@ -1277,6 +1278,19 @@ class LLoadKeyedFastDoubleElement: public LTemplateInstruction<1, 2, 0> { ...@@ -1277,6 +1278,19 @@ class LLoadKeyedFastDoubleElement: public LTemplateInstruction<1, 2, 0> {
}; };
inline static bool ExternalArrayOpRequiresTemp(
Representation key_representation,
ElementsKind elements_kind) {
// 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() &&
(elements_kind == EXTERNAL_BYTE_ELEMENTS ||
elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS ||
elements_kind == EXTERNAL_PIXEL_ELEMENTS);
}
class LLoadKeyedSpecializedArrayElement: public LTemplateInstruction<1, 2, 0> { class LLoadKeyedSpecializedArrayElement: public LTemplateInstruction<1, 2, 0> {
public: public:
LLoadKeyedSpecializedArrayElement(LOperand* external_pointer, LOperand* key) { LLoadKeyedSpecializedArrayElement(LOperand* external_pointer, LOperand* key) {
......
This diff is collapsed.
...@@ -1815,10 +1815,15 @@ LInstruction* LChunkBuilder::DoLoadExternalArrayPointer( ...@@ -1815,10 +1815,15 @@ LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
LInstruction* LChunkBuilder::DoLoadKeyedFastElement( LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
HLoadKeyedFastElement* instr) { HLoadKeyedFastElement* instr) {
ASSERT(instr->representation().IsTagged()); ASSERT(instr->representation().IsTagged());
ASSERT(instr->key()->representation().IsInteger32()); ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged());
LOperand* obj = UseRegisterAtStart(instr->object()); LOperand* obj = UseRegisterAtStart(instr->object());
LOperand* key = UseRegisterOrConstantAtStart(instr->key()); bool clobbers_key = instr->key()->representation().IsTagged();
LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj, key); LOperand* key = clobbers_key
? UseTempRegister(instr->key())
: UseRegisterOrConstantAtStart(instr->key());
LLoadKeyedFastElement* result =
new(zone()) LLoadKeyedFastElement(obj, key);
if (instr->RequiresHoleCheck()) AssignEnvironment(result); if (instr->RequiresHoleCheck()) AssignEnvironment(result);
return DefineAsRegister(result); return DefineAsRegister(result);
} }
...@@ -1827,9 +1832,13 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement( ...@@ -1827,9 +1832,13 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement( LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
HLoadKeyedFastDoubleElement* instr) { HLoadKeyedFastDoubleElement* instr) {
ASSERT(instr->representation().IsDouble()); ASSERT(instr->representation().IsDouble());
ASSERT(instr->key()->representation().IsInteger32()); ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged());
LOperand* elements = UseRegisterAtStart(instr->elements()); LOperand* elements = UseRegisterAtStart(instr->elements());
LOperand* key = UseRegisterOrConstantAtStart(instr->key()); bool clobbers_key = instr->key()->representation().IsTagged();
LOperand* key = clobbers_key
? UseTempRegister(instr->key())
: UseRegisterOrConstantAtStart(instr->key());
LLoadKeyedFastDoubleElement* result = LLoadKeyedFastDoubleElement* result =
new(zone()) LLoadKeyedFastDoubleElement(elements, key); new(zone()) LLoadKeyedFastDoubleElement(elements, key);
return AssignEnvironment(DefineAsRegister(result)); return AssignEnvironment(DefineAsRegister(result));
...@@ -1846,9 +1855,13 @@ LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement( ...@@ -1846,9 +1855,13 @@ LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
(instr->representation().IsDouble() && (instr->representation().IsDouble() &&
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) || ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS)))); (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
ASSERT(instr->key()->representation().IsInteger32()); ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged());
LOperand* external_pointer = UseRegister(instr->external_pointer()); LOperand* external_pointer = UseRegister(instr->external_pointer());
LOperand* key = UseRegisterOrConstant(instr->key()); bool clobbers_key = instr->key()->representation().IsTagged();
LOperand* key = clobbers_key
? UseTempRegister(instr->key())
: UseRegisterOrConstantAtStart(instr->key());
LLoadKeyedSpecializedArrayElement* result = LLoadKeyedSpecializedArrayElement* result =
new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key); new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key);
LInstruction* load_instr = DefineAsRegister(result); LInstruction* load_instr = DefineAsRegister(result);
...@@ -1873,13 +1886,16 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement( ...@@ -1873,13 +1886,16 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
bool needs_write_barrier = instr->NeedsWriteBarrier(); bool needs_write_barrier = instr->NeedsWriteBarrier();
ASSERT(instr->value()->representation().IsTagged()); ASSERT(instr->value()->representation().IsTagged());
ASSERT(instr->object()->representation().IsTagged()); ASSERT(instr->object()->representation().IsTagged());
ASSERT(instr->key()->representation().IsInteger32()); ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged());
LOperand* obj = UseTempRegister(instr->object()); LOperand* obj = UseTempRegister(instr->object());
LOperand* val = needs_write_barrier LOperand* val = needs_write_barrier
? UseTempRegister(instr->value()) ? UseTempRegister(instr->value())
: UseRegisterAtStart(instr->value()); : UseRegisterAtStart(instr->value());
LOperand* key = needs_write_barrier bool clobbers_key = needs_write_barrier ||
instr->key()->representation().IsTagged();
LOperand* key = clobbers_key
? UseTempRegister(instr->key()) ? UseTempRegister(instr->key())
: UseRegisterOrConstantAtStart(instr->key()); : UseRegisterOrConstantAtStart(instr->key());
return new(zone()) LStoreKeyedFastElement(obj, key, val); return new(zone()) LStoreKeyedFastElement(obj, key, val);
...@@ -1890,12 +1906,15 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement( ...@@ -1890,12 +1906,15 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
HStoreKeyedFastDoubleElement* instr) { HStoreKeyedFastDoubleElement* instr) {
ASSERT(instr->value()->representation().IsDouble()); ASSERT(instr->value()->representation().IsDouble());
ASSERT(instr->elements()->representation().IsTagged()); ASSERT(instr->elements()->representation().IsTagged());
ASSERT(instr->key()->representation().IsInteger32()); ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged());
LOperand* elements = UseRegisterAtStart(instr->elements()); LOperand* elements = UseRegisterAtStart(instr->elements());
LOperand* val = UseTempRegister(instr->value()); LOperand* val = UseTempRegister(instr->value());
LOperand* key = UseRegisterOrConstantAtStart(instr->key()); bool clobbers_key = instr->key()->representation().IsTagged();
LOperand* key = clobbers_key
? UseTempRegister(instr->key())
: UseRegisterOrConstantAtStart(instr->key());
return new(zone()) LStoreKeyedFastDoubleElement(elements, key, val); return new(zone()) LStoreKeyedFastDoubleElement(elements, key, val);
} }
...@@ -1911,7 +1930,8 @@ LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement( ...@@ -1911,7 +1930,8 @@ LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) || ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS)))); (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
ASSERT(instr->external_pointer()->representation().IsExternal()); ASSERT(instr->external_pointer()->representation().IsExternal());
ASSERT(instr->key()->representation().IsInteger32()); ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged());
LOperand* external_pointer = UseRegister(instr->external_pointer()); LOperand* external_pointer = UseRegister(instr->external_pointer());
bool val_is_temp_register = bool val_is_temp_register =
...@@ -1920,11 +1940,12 @@ LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement( ...@@ -1920,11 +1940,12 @@ LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
LOperand* val = val_is_temp_register LOperand* val = val_is_temp_register
? UseTempRegister(instr->value()) ? UseTempRegister(instr->value())
: UseRegister(instr->value()); : UseRegister(instr->value());
LOperand* key = UseRegisterOrConstant(instr->key()); bool clobbers_key = instr->key()->representation().IsTagged();
LOperand* key = clobbers_key
? UseTempRegister(instr->key())
: UseRegisterOrConstantAtStart(instr->key());
return new(zone()) LStoreKeyedSpecializedArrayElement(external_pointer, return new(zone()) LStoreKeyedSpecializedArrayElement(external_pointer,
key, key, val);
val);
} }
......
...@@ -857,6 +857,7 @@ class LBoundsCheck: public LTemplateInstruction<0, 2, 0> { ...@@ -857,6 +857,7 @@ class LBoundsCheck: public LTemplateInstruction<0, 2, 0> {
LOperand* length() { return inputs_[1]; } LOperand* length() { return inputs_[1]; }
DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check") DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check")
DECLARE_HYDROGEN_ACCESSOR(BoundsCheck)
}; };
......
...@@ -663,3 +663,54 @@ assertArrayPrefix([4, 5, 6], Int8Array(b2)) ...@@ -663,3 +663,54 @@ assertArrayPrefix([4, 5, 6], Int8Array(b2))
var b3 = b0.slice(2, 4) var b3 = b0.slice(2, 4)
assertEquals(2, b3.byteLength) assertEquals(2, b3.byteLength)
assertArrayPrefix([3, 4], Int8Array(b3)) assertArrayPrefix([3, 4], Int8Array(b3))
function goo(a, i) {
return a[i];
}
function boo(a, i, v) {
return a[i] = v;
}
function do_tagged_index_external_array_test(constructor) {
var t_array = new constructor([1, 2, 3, 4, 5, 6]);
assertEquals(1, goo(t_array, 0));
assertEquals(1, goo(t_array, 0));
boo(t_array, 0, 13);
assertEquals(13, goo(t_array, 0));
%OptimizeFunctionOnNextCall(goo);
%OptimizeFunctionOnNextCall(boo);
boo(t_array, 0, 15);
assertEquals(15, goo(t_array, 0));
%ClearFunctionTypeFeedback(goo);
%ClearFunctionTypeFeedback(boo);
}
do_tagged_index_external_array_test(Int8Array);
do_tagged_index_external_array_test(Uint8Array);
do_tagged_index_external_array_test(Int16Array);
do_tagged_index_external_array_test(Uint16Array);
do_tagged_index_external_array_test(Int32Array);
do_tagged_index_external_array_test(Uint32Array);
do_tagged_index_external_array_test(Float32Array);
do_tagged_index_external_array_test(Float64Array);
var built_in_array = new Array(1, 2, 3, 4, 5, 6);
assertEquals(1, goo(built_in_array, 0));
assertEquals(1, goo(built_in_array, 0));
%OptimizeFunctionOnNextCall(goo);
%OptimizeFunctionOnNextCall(boo);
boo(built_in_array, 0, 11);
assertEquals(11, goo(built_in_array, 0));
%ClearFunctionTypeFeedback(goo);
%ClearFunctionTypeFeedback(boo);
built_in_array = new Array(1.5, 2, 3, 4, 5, 6);
assertEquals(1.5, goo(built_in_array, 0));
assertEquals(1.5, goo(built_in_array, 0));
%OptimizeFunctionOnNextCall(goo);
%OptimizeFunctionOnNextCall(boo);
boo(built_in_array, 0, 2.5);
assertEquals(2.5, goo(built_in_array, 0));
%ClearFunctionTypeFeedback(goo);
%ClearFunctionTypeFeedback(boo);
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