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
This commit is contained in:
parent
c09a137013
commit
8c89cc4cab
@ -1835,7 +1835,8 @@ LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
|
||||
LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
|
||||
HLoadKeyedFastElement* instr) {
|
||||
ASSERT(instr->representation().IsTagged());
|
||||
ASSERT(instr->key()->representation().IsInteger32());
|
||||
ASSERT(instr->key()->representation().IsInteger32() ||
|
||||
instr->key()->representation().IsTagged());
|
||||
LOperand* obj = UseRegisterAtStart(instr->object());
|
||||
LOperand* key = UseRegisterAtStart(instr->key());
|
||||
LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj, key);
|
||||
@ -1847,7 +1848,8 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
|
||||
LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
|
||||
HLoadKeyedFastDoubleElement* instr) {
|
||||
ASSERT(instr->representation().IsDouble());
|
||||
ASSERT(instr->key()->representation().IsInteger32());
|
||||
ASSERT(instr->key()->representation().IsInteger32() ||
|
||||
instr->key()->representation().IsTagged());
|
||||
LOperand* elements = UseTempRegister(instr->elements());
|
||||
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
|
||||
LLoadKeyedFastDoubleElement* result =
|
||||
@ -1866,7 +1868,8 @@ LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
|
||||
(instr->representation().IsDouble() &&
|
||||
((elements_kind == EXTERNAL_FLOAT_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* key = UseRegisterOrConstant(instr->key());
|
||||
LLoadKeyedSpecializedArrayElement* result =
|
||||
@ -1894,7 +1897,8 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
|
||||
bool needs_write_barrier = instr->NeedsWriteBarrier();
|
||||
ASSERT(instr->value()->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* val = needs_write_barrier
|
||||
@ -1911,7 +1915,8 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
|
||||
HStoreKeyedFastDoubleElement* instr) {
|
||||
ASSERT(instr->value()->representation().IsDouble());
|
||||
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* val = UseTempRegister(instr->value());
|
||||
@ -1932,7 +1937,8 @@ LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
|
||||
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
|
||||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
|
||||
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());
|
||||
bool val_is_temp_register =
|
||||
|
@ -859,6 +859,7 @@ class LBoundsCheck: public LTemplateInstruction<0, 2, 0> {
|
||||
LOperand* length() { return inputs_[1]; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check")
|
||||
DECLARE_HYDROGEN_ACCESSOR(BoundsCheck)
|
||||
};
|
||||
|
||||
|
||||
|
@ -2784,7 +2784,12 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
|
||||
Register scratch = scratch0();
|
||||
|
||||
// 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 +
|
||||
(instr->additional_index() << kPointerSizeLog2);
|
||||
__ ldr(result, FieldMemOperand(scratch, offset));
|
||||
@ -2811,8 +2816,9 @@ void LCodeGen::DoLoadKeyedFastDoubleElement(
|
||||
DwVfpRegister result = ToDoubleRegister(instr->result());
|
||||
Register scratch = scratch0();
|
||||
|
||||
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;
|
||||
int constant_key = 0;
|
||||
if (key_is_constant) {
|
||||
constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
|
||||
@ -2824,14 +2830,15 @@ void LCodeGen::DoLoadKeyedFastDoubleElement(
|
||||
}
|
||||
|
||||
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)
|
||||
: Operand(key, LSL, shift_size);
|
||||
__ add(elements, elements, operand);
|
||||
if (!key_is_constant) {
|
||||
__ add(elements, elements,
|
||||
Operand((FixedDoubleArray::kHeaderSize - kHeapObjectTag) +
|
||||
(instr->additional_index() << shift_size)));
|
||||
(instr->additional_index() << element_size_shift)));
|
||||
}
|
||||
|
||||
if (instr->hydrogen()->RequiresHoleCheck()) {
|
||||
@ -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(
|
||||
LLoadKeyedSpecializedArrayElement* instr) {
|
||||
Register external_pointer = ToRegister(instr->external_pointer());
|
||||
@ -2859,15 +2902,17 @@ void LCodeGen::DoLoadKeyedSpecializedArrayElement(
|
||||
} else {
|
||||
key = ToRegister(instr->key());
|
||||
}
|
||||
int shift_size = ElementsKindToShiftSize(elements_kind);
|
||||
int additional_offset = instr->additional_index() << shift_size;
|
||||
int element_size_shift = ElementsKindToShiftSize(elements_kind);
|
||||
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 ||
|
||||
elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
|
||||
CpuFeatures::Scope scope(VFP3);
|
||||
DwVfpRegister result = ToDoubleRegister(instr->result());
|
||||
Operand operand = key_is_constant
|
||||
? Operand(constant_key << shift_size)
|
||||
? Operand(constant_key << element_size_shift)
|
||||
: Operand(key, LSL, shift_size);
|
||||
__ add(scratch0(), external_pointer, operand);
|
||||
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
|
||||
@ -2878,15 +2923,10 @@ void LCodeGen::DoLoadKeyedSpecializedArrayElement(
|
||||
}
|
||||
} else {
|
||||
Register result = ToRegister(instr->result());
|
||||
if (instr->additional_index() != 0 && !key_is_constant) {
|
||||
__ add(scratch0(), key, Operand(instr->additional_index()));
|
||||
}
|
||||
MemOperand mem_operand(key_is_constant
|
||||
? 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)));
|
||||
MemOperand mem_operand = PrepareKeyedOperand(
|
||||
key, external_pointer, key_is_constant, constant_key,
|
||||
element_size_shift, shift_size,
|
||||
instr->additional_index(), additional_offset);
|
||||
switch (elements_kind) {
|
||||
case EXTERNAL_BYTE_ELEMENTS:
|
||||
__ ldrsb(result, mem_operand);
|
||||
@ -3803,7 +3843,12 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
|
||||
+ FixedArray::kHeaderSize;
|
||||
__ str(value, FieldMemOperand(elements, offset));
|
||||
} 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) {
|
||||
__ add(scratch,
|
||||
scratch,
|
||||
@ -3848,9 +3893,11 @@ void LCodeGen::DoStoreKeyedFastDoubleElement(
|
||||
} else {
|
||||
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((constant_key << shift_size) +
|
||||
? Operand((constant_key << element_size_shift) +
|
||||
FixedDoubleArray::kHeaderSize - kHeapObjectTag)
|
||||
: Operand(key, LSL, shift_size);
|
||||
__ add(scratch, elements, operand);
|
||||
@ -3868,7 +3915,7 @@ void LCodeGen::DoStoreKeyedFastDoubleElement(
|
||||
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(
|
||||
} else {
|
||||
key = ToRegister(instr->key());
|
||||
}
|
||||
int shift_size = ElementsKindToShiftSize(elements_kind);
|
||||
int additional_offset = instr->additional_index() << shift_size;
|
||||
int element_size_shift = ElementsKindToShiftSize(elements_kind);
|
||||
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 ||
|
||||
elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
|
||||
CpuFeatures::Scope scope(VFP3);
|
||||
DwVfpRegister value(ToDoubleRegister(instr->value()));
|
||||
Operand operand(key_is_constant ? Operand(constant_key << shift_size)
|
||||
: Operand(key, LSL, shift_size));
|
||||
Operand operand(key_is_constant
|
||||
? Operand(constant_key << element_size_shift)
|
||||
: Operand(key, LSL, shift_size));
|
||||
__ add(scratch0(), external_pointer, operand);
|
||||
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
|
||||
__ vcvt_f32_f64(double_scratch0().low(), value);
|
||||
@ -3906,16 +3956,10 @@ void LCodeGen::DoStoreKeyedSpecializedArrayElement(
|
||||
}
|
||||
} else {
|
||||
Register value(ToRegister(instr->value()));
|
||||
if (instr->additional_index() != 0 && !key_is_constant) {
|
||||
__ add(scratch0(), key, Operand(instr->additional_index()));
|
||||
}
|
||||
MemOperand mem_operand(key_is_constant
|
||||
? 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)));
|
||||
MemOperand mem_operand = PrepareKeyedOperand(
|
||||
key, external_pointer, key_is_constant, constant_key,
|
||||
element_size_shift, shift_size,
|
||||
instr->additional_index(), additional_offset);
|
||||
switch (elements_kind) {
|
||||
case EXTERNAL_PIXEL_ELEMENTS:
|
||||
case EXTERNAL_BYTE_ELEMENTS:
|
||||
|
@ -132,6 +132,15 @@ class LCodeGen BASE_EMBEDDED {
|
||||
void DoParallelMove(LParallelMove* move);
|
||||
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.
|
||||
void WriteTranslation(LEnvironment* environment, Translation* translation);
|
||||
|
||||
|
@ -1888,6 +1888,7 @@ class HJSArrayLength: public HTemplateInstruction<2> {
|
||||
class HFixedArrayBaseLength: public HUnaryOperation {
|
||||
public:
|
||||
explicit HFixedArrayBaseLength(HValue* value) : HUnaryOperation(value) {
|
||||
set_type(HType::Smi());
|
||||
set_representation(Representation::Tagged());
|
||||
SetFlag(kUseGVN);
|
||||
SetGVNFlag(kDependsOnArrayLengths);
|
||||
@ -2757,17 +2758,31 @@ class HAccessArgumentsAt: public HTemplateInstruction<3> {
|
||||
};
|
||||
|
||||
|
||||
enum BoundsCheckKeyMode {
|
||||
DONT_ALLOW_SMI_KEY,
|
||||
ALLOW_SMI_KEY
|
||||
};
|
||||
|
||||
|
||||
class HBoundsCheck: public HTemplateInstruction<2> {
|
||||
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(1, length);
|
||||
set_representation(Representation::Integer32());
|
||||
SetFlag(kUseGVN);
|
||||
}
|
||||
|
||||
virtual Representation RequiredInputRepresentation(int index) {
|
||||
return Representation::Integer32();
|
||||
virtual Representation RequiredInputRepresentation(int arg_index) {
|
||||
if (index()->representation().IsTagged() &&
|
||||
!index()->IsConstant() &&
|
||||
key_mode_ == ALLOW_SMI_KEY) {
|
||||
return Representation::Tagged();
|
||||
} else {
|
||||
return Representation::Integer32();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void PrintDataTo(StringStream* stream);
|
||||
@ -2779,6 +2794,7 @@ class HBoundsCheck: public HTemplateInstruction<2> {
|
||||
|
||||
protected:
|
||||
virtual bool DataEquals(HValue* other) { return true; }
|
||||
BoundsCheckKeyMode key_mode_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -5842,7 +5842,8 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
||||
HInstruction* checked_key = NULL;
|
||||
if (map->has_external_array_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 =
|
||||
new(zone()) HLoadExternalArrayPointer(elements);
|
||||
AddInstruction(external_elements);
|
||||
@ -6077,7 +6078,8 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
|
||||
HInstruction* length;
|
||||
length = AddInstruction(new(zone()) HJSArrayLength(object, typecheck,
|
||||
HType::Smi()));
|
||||
checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
|
||||
checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length,
|
||||
ALLOW_SMI_KEY));
|
||||
access = AddInstruction(BuildFastElementAccess(
|
||||
elements, checked_key, val, elements_kind, is_store));
|
||||
if (!is_store) {
|
||||
@ -6092,7 +6094,8 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
|
||||
|
||||
set_current_block(if_fastobject);
|
||||
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(
|
||||
elements, checked_key, val, elements_kind, is_store));
|
||||
} else if (elements_kind == DICTIONARY_ELEMENTS) {
|
||||
|
@ -2650,6 +2650,7 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
|
||||
__ mov(result,
|
||||
BuildFastArrayOperand(instr->elements(),
|
||||
instr->key(),
|
||||
instr->hydrogen()->key()->representation(),
|
||||
FAST_ELEMENTS,
|
||||
FixedArray::kHeaderSize - kHeapObjectTag,
|
||||
instr->additional_index()));
|
||||
@ -2676,6 +2677,7 @@ void LCodeGen::DoLoadKeyedFastDoubleElement(
|
||||
sizeof(kHoleNanLower32);
|
||||
Operand hole_check_operand = BuildFastArrayOperand(
|
||||
instr->elements(), instr->key(),
|
||||
instr->hydrogen()->key()->representation(),
|
||||
FAST_DOUBLE_ELEMENTS,
|
||||
offset,
|
||||
instr->additional_index());
|
||||
@ -2686,6 +2688,7 @@ void LCodeGen::DoLoadKeyedFastDoubleElement(
|
||||
Operand double_load_operand = BuildFastArrayOperand(
|
||||
instr->elements(),
|
||||
instr->key(),
|
||||
instr->hydrogen()->key()->representation(),
|
||||
FAST_DOUBLE_ELEMENTS,
|
||||
FixedDoubleArray::kHeaderSize - kHeapObjectTag,
|
||||
instr->additional_index());
|
||||
@ -2696,11 +2699,15 @@ void LCodeGen::DoLoadKeyedFastDoubleElement(
|
||||
Operand LCodeGen::BuildFastArrayOperand(
|
||||
LOperand* elements_pointer,
|
||||
LOperand* key,
|
||||
Representation key_representation,
|
||||
ElementsKind elements_kind,
|
||||
uint32_t offset,
|
||||
uint32_t additional_index) {
|
||||
Register elements_pointer_reg = ToRegister(elements_pointer);
|
||||
int shift_size = ElementsKindToShiftSize(elements_kind);
|
||||
if (key_representation.IsTagged() && (shift_size >= 1)) {
|
||||
shift_size -= kSmiTagSize;
|
||||
}
|
||||
if (key->IsConstantOperand()) {
|
||||
int constant_value = ToInteger32(LConstantOperand::cast(key));
|
||||
if (constant_value & 0xF0000000) {
|
||||
@ -2722,11 +2729,19 @@ Operand LCodeGen::BuildFastArrayOperand(
|
||||
void LCodeGen::DoLoadKeyedSpecializedArrayElement(
|
||||
LLoadKeyedSpecializedArrayElement* instr) {
|
||||
ElementsKind elements_kind = instr->elements_kind();
|
||||
Operand operand(BuildFastArrayOperand(instr->external_pointer(),
|
||||
instr->key(),
|
||||
elements_kind,
|
||||
0,
|
||||
instr->additional_index()));
|
||||
LOperand* key = instr->key();
|
||||
if (!key->IsConstantOperand() &&
|
||||
ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
|
||||
elements_kind)) {
|
||||
__ 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) {
|
||||
XMMRegister result(ToDoubleRegister(instr->result()));
|
||||
__ movss(result, operand);
|
||||
@ -3679,11 +3694,19 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
|
||||
void LCodeGen::DoStoreKeyedSpecializedArrayElement(
|
||||
LStoreKeyedSpecializedArrayElement* instr) {
|
||||
ElementsKind elements_kind = instr->elements_kind();
|
||||
Operand operand(BuildFastArrayOperand(instr->external_pointer(),
|
||||
instr->key(),
|
||||
elements_kind,
|
||||
0,
|
||||
instr->additional_index()));
|
||||
LOperand* key = instr->key();
|
||||
if (!key->IsConstantOperand() &&
|
||||
ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
|
||||
elements_kind)) {
|
||||
__ 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) {
|
||||
__ cvtsd2ss(xmm0, ToDoubleRegister(instr->value()));
|
||||
__ movss(operand, xmm0);
|
||||
@ -3730,6 +3753,7 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
|
||||
Operand operand = BuildFastArrayOperand(
|
||||
instr->object(),
|
||||
instr->key(),
|
||||
instr->hydrogen()->key()->representation(),
|
||||
FAST_ELEMENTS,
|
||||
FixedArray::kHeaderSize - kHeapObjectTag,
|
||||
instr->additional_index());
|
||||
@ -3771,6 +3795,7 @@ void LCodeGen::DoStoreKeyedFastDoubleElement(
|
||||
Operand double_store_operand = BuildFastArrayOperand(
|
||||
instr->elements(),
|
||||
instr->key(),
|
||||
instr->hydrogen()->key()->representation(),
|
||||
FAST_DOUBLE_ELEMENTS,
|
||||
FixedDoubleArray::kHeaderSize - kHeapObjectTag,
|
||||
instr->additional_index());
|
||||
|
@ -246,6 +246,7 @@ class LCodeGen BASE_EMBEDDED {
|
||||
double ToDouble(LConstantOperand* op) const;
|
||||
Operand BuildFastArrayOperand(LOperand* elements_pointer,
|
||||
LOperand* key,
|
||||
Representation key_representation,
|
||||
ElementsKind elements_kind,
|
||||
uint32_t offset,
|
||||
uint32_t additional_index = 0);
|
||||
|
@ -1900,7 +1900,8 @@ LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
|
||||
LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
|
||||
HLoadKeyedFastElement* instr) {
|
||||
ASSERT(instr->representation().IsTagged());
|
||||
ASSERT(instr->key()->representation().IsInteger32());
|
||||
ASSERT(instr->key()->representation().IsInteger32() ||
|
||||
instr->key()->representation().IsTagged());
|
||||
LOperand* obj = UseRegisterAtStart(instr->object());
|
||||
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
|
||||
LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj, key);
|
||||
@ -1912,7 +1913,8 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
|
||||
LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
|
||||
HLoadKeyedFastDoubleElement* instr) {
|
||||
ASSERT(instr->representation().IsDouble());
|
||||
ASSERT(instr->key()->representation().IsInteger32());
|
||||
ASSERT(instr->key()->representation().IsInteger32() ||
|
||||
instr->key()->representation().IsTagged());
|
||||
LOperand* elements = UseRegisterAtStart(instr->elements());
|
||||
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
|
||||
LLoadKeyedFastDoubleElement* result =
|
||||
@ -1931,11 +1933,17 @@ LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
|
||||
(instr->representation().IsDouble() &&
|
||||
((elements_kind == EXTERNAL_FLOAT_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* 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 =
|
||||
new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key);
|
||||
new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key);
|
||||
LInstruction* load_instr = DefineAsRegister(result);
|
||||
// An unsigned int array load might overflow and cause a deopt, make sure it
|
||||
// has an environment.
|
||||
@ -1961,7 +1969,8 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
|
||||
bool needs_write_barrier = instr->NeedsWriteBarrier();
|
||||
ASSERT(instr->value()->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* val = needs_write_barrier
|
||||
@ -1978,7 +1987,8 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
|
||||
HStoreKeyedFastDoubleElement* instr) {
|
||||
ASSERT(instr->value()->representation().IsDouble());
|
||||
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* val = UseTempRegister(instr->value());
|
||||
@ -1999,10 +2009,10 @@ LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
|
||||
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
|
||||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
|
||||
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* key = UseRegisterOrConstant(instr->key());
|
||||
LOperand* val = NULL;
|
||||
if (elements_kind == EXTERNAL_BYTE_ELEMENTS ||
|
||||
elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS ||
|
||||
@ -2012,7 +2022,11 @@ LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
|
||||
} else {
|
||||
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,
|
||||
key,
|
||||
val);
|
||||
|
@ -872,6 +872,7 @@ class LBoundsCheck: public LTemplateInstruction<0, 2, 0> {
|
||||
LOperand* length() { return inputs_[1]; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check")
|
||||
DECLARE_HYDROGEN_ACCESSOR(BoundsCheck)
|
||||
};
|
||||
|
||||
|
||||
@ -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> {
|
||||
public:
|
||||
LLoadKeyedSpecializedArrayElement(LOperand* external_pointer, LOperand* key) {
|
||||
|
@ -2503,18 +2503,22 @@ void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
|
||||
|
||||
void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
|
||||
Register result = ToRegister(instr->result());
|
||||
|
||||
if (instr->hydrogen()->IsDehoisted() && !instr->key()->IsConstantOperand()) {
|
||||
// Sign extend key because it could be a 32 bit negative value
|
||||
// and the dehoisted address computation happens in 64 bits.
|
||||
Register key_reg = ToRegister(instr->key());
|
||||
__ movsxlq(key_reg, key_reg);
|
||||
LOperand* key = instr->key();
|
||||
if (!key->IsConstantOperand()) {
|
||||
Register key_reg = ToRegister(key);
|
||||
if (instr->hydrogen()->key()->representation().IsTagged()) {
|
||||
__ SmiToInteger64(key_reg, key_reg);
|
||||
} else if (instr->hydrogen()->IsDehoisted()) {
|
||||
// Sign extend key because it could be a 32 bit negative value
|
||||
// and the dehoisted address computation happens in 64 bits
|
||||
__ movsxlq(key_reg, key_reg);
|
||||
}
|
||||
}
|
||||
|
||||
// Load the result.
|
||||
__ movq(result,
|
||||
BuildFastArrayOperand(instr->elements(),
|
||||
instr->key(),
|
||||
key,
|
||||
FAST_ELEMENTS,
|
||||
FixedArray::kHeaderSize - kHeapObjectTag,
|
||||
instr->additional_index()));
|
||||
@ -2535,12 +2539,16 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
|
||||
void LCodeGen::DoLoadKeyedFastDoubleElement(
|
||||
LLoadKeyedFastDoubleElement* instr) {
|
||||
XMMRegister result(ToDoubleRegister(instr->result()));
|
||||
|
||||
if (instr->hydrogen()->IsDehoisted() && !instr->key()->IsConstantOperand()) {
|
||||
// Sign extend key because it could be a 32 bit negative value
|
||||
// and the dehoisted address computation happens in 64 bits
|
||||
Register key_reg = ToRegister(instr->key());
|
||||
__ movsxlq(key_reg, key_reg);
|
||||
LOperand* key = instr->key();
|
||||
if (!key->IsConstantOperand()) {
|
||||
Register key_reg = ToRegister(key);
|
||||
if (instr->hydrogen()->key()->representation().IsTagged()) {
|
||||
__ SmiToInteger64(key_reg, key_reg);
|
||||
} else if (instr->hydrogen()->IsDehoisted()) {
|
||||
// Sign extend key because it could be a 32 bit negative value
|
||||
// and the dehoisted address computation happens in 64 bits
|
||||
__ movsxlq(key_reg, key_reg);
|
||||
}
|
||||
}
|
||||
|
||||
if (instr->hydrogen()->RequiresHoleCheck()) {
|
||||
@ -2548,7 +2556,7 @@ void LCodeGen::DoLoadKeyedFastDoubleElement(
|
||||
sizeof(kHoleNanLower32);
|
||||
Operand hole_check_operand = BuildFastArrayOperand(
|
||||
instr->elements(),
|
||||
instr->key(),
|
||||
key,
|
||||
FAST_DOUBLE_ELEMENTS,
|
||||
offset,
|
||||
instr->additional_index());
|
||||
@ -2558,7 +2566,7 @@ void LCodeGen::DoLoadKeyedFastDoubleElement(
|
||||
|
||||
Operand double_load_operand = BuildFastArrayOperand(
|
||||
instr->elements(),
|
||||
instr->key(),
|
||||
key,
|
||||
FAST_DOUBLE_ELEMENTS,
|
||||
FixedDoubleArray::kHeaderSize - kHeapObjectTag,
|
||||
instr->additional_index());
|
||||
@ -2595,17 +2603,23 @@ Operand LCodeGen::BuildFastArrayOperand(
|
||||
void LCodeGen::DoLoadKeyedSpecializedArrayElement(
|
||||
LLoadKeyedSpecializedArrayElement* instr) {
|
||||
ElementsKind elements_kind = instr->elements_kind();
|
||||
Operand operand(BuildFastArrayOperand(instr->external_pointer(),
|
||||
instr->key(),
|
||||
elements_kind,
|
||||
0,
|
||||
instr->additional_index()));
|
||||
if (instr->hydrogen()->IsDehoisted() && !instr->key()->IsConstantOperand()) {
|
||||
// Sign extend key because it could be a 32 bit negative value
|
||||
// and the dehoisted address computation happens in 64 bits
|
||||
Register key_reg = ToRegister(instr->key());
|
||||
__ movsxlq(key_reg, key_reg);
|
||||
LOperand* key = instr->key();
|
||||
if (!key->IsConstantOperand()) {
|
||||
Register key_reg = ToRegister(key);
|
||||
if (instr->hydrogen()->key()->representation().IsTagged()) {
|
||||
__ SmiToInteger64(key_reg, key_reg);
|
||||
} else if (instr->hydrogen()->IsDehoisted()) {
|
||||
// Sign extend key because it could be a 32 bit negative value
|
||||
// and the dehoisted address computation happens in 64 bits
|
||||
__ movsxlq(key_reg, key_reg);
|
||||
}
|
||||
}
|
||||
Operand operand(BuildFastArrayOperand(
|
||||
instr->external_pointer(),
|
||||
key,
|
||||
elements_kind,
|
||||
0,
|
||||
instr->additional_index()));
|
||||
|
||||
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
|
||||
XMMRegister result(ToDoubleRegister(instr->result()));
|
||||
@ -3538,18 +3552,23 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
|
||||
void LCodeGen::DoStoreKeyedSpecializedArrayElement(
|
||||
LStoreKeyedSpecializedArrayElement* instr) {
|
||||
ElementsKind elements_kind = instr->elements_kind();
|
||||
Operand operand(BuildFastArrayOperand(instr->external_pointer(),
|
||||
instr->key(),
|
||||
elements_kind,
|
||||
0,
|
||||
instr->additional_index()));
|
||||
|
||||
if (instr->hydrogen()->IsDehoisted() && !instr->key()->IsConstantOperand()) {
|
||||
// Sign extend key because it could be a 32 bit negative value
|
||||
// and the dehoisted address computation happens in 64 bits
|
||||
Register key_reg = ToRegister(instr->key());
|
||||
__ movsxlq(key_reg, key_reg);
|
||||
LOperand* key = instr->key();
|
||||
if (!key->IsConstantOperand()) {
|
||||
Register key_reg = ToRegister(key);
|
||||
if (instr->hydrogen()->key()->representation().IsTagged()) {
|
||||
__ SmiToInteger64(key_reg, key_reg);
|
||||
} else if (instr->hydrogen()->IsDehoisted()) {
|
||||
// Sign extend key because it could be a 32 bit negative value
|
||||
// and the dehoisted address computation happens in 64 bits
|
||||
__ movsxlq(key_reg, key_reg);
|
||||
}
|
||||
}
|
||||
Operand operand(BuildFastArrayOperand(
|
||||
instr->external_pointer(),
|
||||
key,
|
||||
elements_kind,
|
||||
0,
|
||||
instr->additional_index()));
|
||||
|
||||
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
|
||||
XMMRegister value(ToDoubleRegister(instr->value()));
|
||||
@ -3593,7 +3612,8 @@ void LCodeGen::DoStoreKeyedSpecializedArrayElement(
|
||||
void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
|
||||
if (instr->length()->IsRegister()) {
|
||||
Register reg = ToRegister(instr->length());
|
||||
if (FLAG_debug_code) {
|
||||
if (FLAG_debug_code &&
|
||||
!instr->hydrogen()->index()->representation().IsTagged()) {
|
||||
__ AbortIfNotZeroExtended(reg);
|
||||
}
|
||||
if (instr->index()->IsConstantOperand()) {
|
||||
@ -3601,7 +3621,8 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
|
||||
Immediate(ToInteger32(LConstantOperand::cast(instr->index()))));
|
||||
} else {
|
||||
Register reg2 = ToRegister(instr->index());
|
||||
if (FLAG_debug_code) {
|
||||
if (FLAG_debug_code &&
|
||||
!instr->hydrogen()->index()->representation().IsTagged()) {
|
||||
__ AbortIfNotZeroExtended(reg2);
|
||||
}
|
||||
__ cmpq(reg, reg2);
|
||||
@ -3621,37 +3642,42 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
|
||||
void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
|
||||
Register value = ToRegister(instr->value());
|
||||
Register elements = ToRegister(instr->object());
|
||||
Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;
|
||||
LOperand* key = instr->key();
|
||||
if (!key->IsConstantOperand()) {
|
||||
Register key_reg = ToRegister(key);
|
||||
if (instr->hydrogen()->key()->representation().IsTagged()) {
|
||||
__ SmiToInteger64(key_reg, key_reg);
|
||||
} else if (instr->hydrogen()->IsDehoisted()) {
|
||||
// Sign extend key because it could be a 32 bit negative value
|
||||
// and the dehoisted address computation happens in 64 bits
|
||||
__ movsxlq(key_reg, key_reg);
|
||||
}
|
||||
}
|
||||
|
||||
Operand operand =
|
||||
BuildFastArrayOperand(instr->object(),
|
||||
instr->key(),
|
||||
key,
|
||||
FAST_ELEMENTS,
|
||||
FixedArray::kHeaderSize - kHeapObjectTag,
|
||||
instr->additional_index());
|
||||
|
||||
if (instr->hydrogen()->IsDehoisted() && !instr->key()->IsConstantOperand()) {
|
||||
// Sign extend key because it could be a 32 bit negative value
|
||||
// and the dehoisted address computation happens in 64 bits
|
||||
Register key_reg = ToRegister(instr->key());
|
||||
__ movsxlq(key_reg, key_reg);
|
||||
}
|
||||
|
||||
__ movq(operand, value);
|
||||
|
||||
if (instr->hydrogen()->NeedsWriteBarrier()) {
|
||||
ASSERT(!instr->key()->IsConstantOperand());
|
||||
HType type = instr->hydrogen()->value()->type();
|
||||
SmiCheck check_needed =
|
||||
type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
|
||||
// Compute address of modified element and store it into key register.
|
||||
__ lea(key, operand);
|
||||
Register key_reg(ToRegister(key));
|
||||
__ lea(key_reg, operand);
|
||||
__ movq(Operand(key_reg, 0), value);
|
||||
__ RecordWrite(elements,
|
||||
key,
|
||||
key_reg,
|
||||
value,
|
||||
kSaveFPRegs,
|
||||
EMIT_REMEMBERED_SET,
|
||||
check_needed);
|
||||
} else {
|
||||
__ movq(operand, value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3659,6 +3685,17 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
|
||||
void LCodeGen::DoStoreKeyedFastDoubleElement(
|
||||
LStoreKeyedFastDoubleElement* instr) {
|
||||
XMMRegister value = ToDoubleRegister(instr->value());
|
||||
LOperand* key = instr->key();
|
||||
if (!key->IsConstantOperand()) {
|
||||
Register key_reg = ToRegister(key);
|
||||
if (instr->hydrogen()->key()->representation().IsTagged()) {
|
||||
__ SmiToInteger64(key_reg, key_reg);
|
||||
} else if (instr->hydrogen()->IsDehoisted()) {
|
||||
// Sign extend key because it could be a 32 bit negative value
|
||||
// and the dehoisted address computation happens in 64 bits
|
||||
__ movsxlq(key_reg, key_reg);
|
||||
}
|
||||
}
|
||||
|
||||
if (instr->NeedsCanonicalization()) {
|
||||
Label have_value;
|
||||
@ -3675,18 +3712,11 @@ void LCodeGen::DoStoreKeyedFastDoubleElement(
|
||||
|
||||
Operand double_store_operand = BuildFastArrayOperand(
|
||||
instr->elements(),
|
||||
instr->key(),
|
||||
key,
|
||||
FAST_DOUBLE_ELEMENTS,
|
||||
FixedDoubleArray::kHeaderSize - kHeapObjectTag,
|
||||
instr->additional_index());
|
||||
|
||||
if (instr->hydrogen()->IsDehoisted() && !instr->key()->IsConstantOperand()) {
|
||||
// Sign extend key because it could be a 32 bit negative value
|
||||
// and the dehoisted address computation happens in 64 bits
|
||||
Register key_reg = ToRegister(instr->key());
|
||||
__ movsxlq(key_reg, key_reg);
|
||||
}
|
||||
|
||||
__ movsd(double_store_operand, value);
|
||||
}
|
||||
|
||||
|
@ -1815,10 +1815,15 @@ LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
|
||||
LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
|
||||
HLoadKeyedFastElement* instr) {
|
||||
ASSERT(instr->representation().IsTagged());
|
||||
ASSERT(instr->key()->representation().IsInteger32());
|
||||
ASSERT(instr->key()->representation().IsInteger32() ||
|
||||
instr->key()->representation().IsTagged());
|
||||
LOperand* obj = UseRegisterAtStart(instr->object());
|
||||
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
|
||||
LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj, key);
|
||||
bool clobbers_key = instr->key()->representation().IsTagged();
|
||||
LOperand* key = clobbers_key
|
||||
? UseTempRegister(instr->key())
|
||||
: UseRegisterOrConstantAtStart(instr->key());
|
||||
LLoadKeyedFastElement* result =
|
||||
new(zone()) LLoadKeyedFastElement(obj, key);
|
||||
if (instr->RequiresHoleCheck()) AssignEnvironment(result);
|
||||
return DefineAsRegister(result);
|
||||
}
|
||||
@ -1827,9 +1832,13 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
|
||||
LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
|
||||
HLoadKeyedFastDoubleElement* instr) {
|
||||
ASSERT(instr->representation().IsDouble());
|
||||
ASSERT(instr->key()->representation().IsInteger32());
|
||||
ASSERT(instr->key()->representation().IsInteger32() ||
|
||||
instr->key()->representation().IsTagged());
|
||||
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 =
|
||||
new(zone()) LLoadKeyedFastDoubleElement(elements, key);
|
||||
return AssignEnvironment(DefineAsRegister(result));
|
||||
@ -1846,9 +1855,13 @@ LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
|
||||
(instr->representation().IsDouble() &&
|
||||
((elements_kind == EXTERNAL_FLOAT_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* key = UseRegisterOrConstant(instr->key());
|
||||
bool clobbers_key = instr->key()->representation().IsTagged();
|
||||
LOperand* key = clobbers_key
|
||||
? UseTempRegister(instr->key())
|
||||
: UseRegisterOrConstantAtStart(instr->key());
|
||||
LLoadKeyedSpecializedArrayElement* result =
|
||||
new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key);
|
||||
LInstruction* load_instr = DefineAsRegister(result);
|
||||
@ -1873,13 +1886,16 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
|
||||
bool needs_write_barrier = instr->NeedsWriteBarrier();
|
||||
ASSERT(instr->value()->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* val = needs_write_barrier
|
||||
? UseTempRegister(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())
|
||||
: UseRegisterOrConstantAtStart(instr->key());
|
||||
return new(zone()) LStoreKeyedFastElement(obj, key, val);
|
||||
@ -1890,12 +1906,15 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
|
||||
HStoreKeyedFastDoubleElement* instr) {
|
||||
ASSERT(instr->value()->representation().IsDouble());
|
||||
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* 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);
|
||||
}
|
||||
|
||||
@ -1911,7 +1930,8 @@ LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
|
||||
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
|
||||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
|
||||
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());
|
||||
bool val_is_temp_register =
|
||||
@ -1920,11 +1940,12 @@ LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
|
||||
LOperand* val = val_is_temp_register
|
||||
? UseTempRegister(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,
|
||||
key,
|
||||
val);
|
||||
key, val);
|
||||
}
|
||||
|
||||
|
||||
|
@ -857,6 +857,7 @@ class LBoundsCheck: public LTemplateInstruction<0, 2, 0> {
|
||||
LOperand* length() { return inputs_[1]; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check")
|
||||
DECLARE_HYDROGEN_ACCESSOR(BoundsCheck)
|
||||
};
|
||||
|
||||
|
||||
|
@ -663,3 +663,54 @@ assertArrayPrefix([4, 5, 6], Int8Array(b2))
|
||||
var b3 = b0.slice(2, 4)
|
||||
assertEquals(2, b3.byteLength)
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user