Avoid using a register for constant external array indices.
This CL is based on and obsoletes CL 6879037. TEST=mjsunit/external-array.js Review URL: http://codereview.chromium.org/6902112 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7844 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
1eedd8056d
commit
944a388412
@ -1861,7 +1861,7 @@ LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
|
||||
array_type == kExternalDoubleArray)));
|
||||
ASSERT(instr->key()->representation().IsInteger32());
|
||||
LOperand* external_pointer = UseRegister(instr->external_pointer());
|
||||
LOperand* key = UseRegister(instr->key());
|
||||
LOperand* key = UseRegisterOrConstant(instr->key());
|
||||
LLoadKeyedSpecializedArrayElement* result =
|
||||
new LLoadKeyedSpecializedArrayElement(external_pointer, key);
|
||||
LInstruction* load_instr = DefineAsRegister(result);
|
||||
@ -1919,7 +1919,7 @@ LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
|
||||
LOperand* val = val_is_temp_register
|
||||
? UseTempRegister(instr->value())
|
||||
: UseRegister(instr->value());
|
||||
LOperand* key = UseRegister(instr->key());
|
||||
LOperand* key = UseRegisterOrConstant(instr->key());
|
||||
|
||||
return new LStoreKeyedSpecializedArrayElement(external_pointer,
|
||||
key,
|
||||
|
@ -2484,40 +2484,56 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
|
||||
void LCodeGen::DoLoadKeyedSpecializedArrayElement(
|
||||
LLoadKeyedSpecializedArrayElement* instr) {
|
||||
Register external_pointer = ToRegister(instr->external_pointer());
|
||||
Register key = ToRegister(instr->key());
|
||||
Register key = no_reg;
|
||||
ExternalArrayType array_type = instr->array_type();
|
||||
if (array_type == kExternalFloatArray) {
|
||||
bool key_is_constant = instr->key()->IsConstantOperand();
|
||||
int constant_key = 0;
|
||||
if (key_is_constant) {
|
||||
constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
|
||||
if (constant_key & 0xF0000000) {
|
||||
Abort("array index constant value too big.");
|
||||
}
|
||||
} else {
|
||||
key = ToRegister(instr->key());
|
||||
}
|
||||
int shift_size = ExternalArrayTypeToShiftSize(array_type);
|
||||
|
||||
if (array_type == kExternalFloatArray || array_type == kExternalDoubleArray) {
|
||||
CpuFeatures::Scope scope(VFP3);
|
||||
DwVfpRegister result(ToDoubleRegister(instr->result()));
|
||||
__ add(scratch0(), external_pointer, Operand(key, LSL, 2));
|
||||
__ vldr(result.low(), scratch0(), 0);
|
||||
__ vcvt_f64_f32(result, result.low());
|
||||
} else if (array_type == kExternalDoubleArray) {
|
||||
CpuFeatures::Scope scope(VFP3);
|
||||
DwVfpRegister result(ToDoubleRegister(instr->result()));
|
||||
__ add(scratch0(), external_pointer, Operand(key, LSL, 3));
|
||||
__ vldr(result, scratch0(), 0);
|
||||
Operand operand(key_is_constant ? Operand(constant_key * (1 << shift_size))
|
||||
: Operand(key, LSL, shift_size));
|
||||
__ add(scratch0(), external_pointer, operand);
|
||||
if (array_type == kExternalFloatArray) {
|
||||
__ vldr(result.low(), scratch0(), 0);
|
||||
__ vcvt_f64_f32(result, result.low());
|
||||
} else { // i.e. array_type == kExternalDoubleArray
|
||||
__ vldr(result, scratch0(), 0);
|
||||
}
|
||||
} else {
|
||||
Register result(ToRegister(instr->result()));
|
||||
MemOperand mem_operand(key_is_constant
|
||||
? MemOperand(external_pointer, constant_key * (1 << shift_size))
|
||||
: MemOperand(external_pointer, key, LSL, shift_size));
|
||||
switch (array_type) {
|
||||
case kExternalByteArray:
|
||||
__ ldrsb(result, MemOperand(external_pointer, key));
|
||||
__ ldrsb(result, mem_operand);
|
||||
break;
|
||||
case kExternalUnsignedByteArray:
|
||||
case kExternalPixelArray:
|
||||
__ ldrb(result, MemOperand(external_pointer, key));
|
||||
__ ldrb(result, mem_operand);
|
||||
break;
|
||||
case kExternalShortArray:
|
||||
__ ldrsh(result, MemOperand(external_pointer, key, LSL, 1));
|
||||
__ ldrsh(result, mem_operand);
|
||||
break;
|
||||
case kExternalUnsignedShortArray:
|
||||
__ ldrh(result, MemOperand(external_pointer, key, LSL, 1));
|
||||
__ ldrh(result, mem_operand);
|
||||
break;
|
||||
case kExternalIntArray:
|
||||
__ ldr(result, MemOperand(external_pointer, key, LSL, 2));
|
||||
__ ldr(result, mem_operand);
|
||||
break;
|
||||
case kExternalUnsignedIntArray:
|
||||
__ ldr(result, MemOperand(external_pointer, key, LSL, 2));
|
||||
__ ldr(result, mem_operand);
|
||||
__ cmp(result, Operand(0x80000000));
|
||||
// TODO(danno): we could be more clever here, perhaps having a special
|
||||
// version of the stub that detects if the overflow case actually
|
||||
@ -3247,39 +3263,53 @@ void LCodeGen::DoStoreKeyedSpecializedArrayElement(
|
||||
LStoreKeyedSpecializedArrayElement* instr) {
|
||||
|
||||
Register external_pointer = ToRegister(instr->external_pointer());
|
||||
Register key = ToRegister(instr->key());
|
||||
Register key = no_reg;
|
||||
ExternalArrayType array_type = instr->array_type();
|
||||
bool key_is_constant = instr->key()->IsConstantOperand();
|
||||
int constant_key = 0;
|
||||
if (key_is_constant) {
|
||||
constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
|
||||
if (constant_key & 0xF0000000) {
|
||||
Abort("array index constant value too big.");
|
||||
}
|
||||
} else {
|
||||
key = ToRegister(instr->key());
|
||||
}
|
||||
int shift_size = ExternalArrayTypeToShiftSize(array_type);
|
||||
|
||||
if (array_type == kExternalFloatArray) {
|
||||
if (array_type == kExternalFloatArray || array_type == kExternalDoubleArray) {
|
||||
CpuFeatures::Scope scope(VFP3);
|
||||
DwVfpRegister value(ToDoubleRegister(instr->value()));
|
||||
__ add(scratch0(), external_pointer, Operand(key, LSL, 2));
|
||||
__ vcvt_f32_f64(double_scratch0().low(), value);
|
||||
__ vstr(double_scratch0().low(), scratch0(), 0);
|
||||
} else if (array_type == kExternalDoubleArray) {
|
||||
CpuFeatures::Scope scope(VFP3);
|
||||
DwVfpRegister value(ToDoubleRegister(instr->value()));
|
||||
__ add(scratch0(), external_pointer, Operand(key, LSL, 3));
|
||||
__ vstr(value, scratch0(), 0);
|
||||
Operand operand(key_is_constant ? Operand(constant_key * (1 << shift_size))
|
||||
: Operand(key, LSL, shift_size));
|
||||
__ add(scratch0(), external_pointer, operand);
|
||||
if (array_type == kExternalFloatArray) {
|
||||
__ vcvt_f32_f64(double_scratch0().low(), value);
|
||||
__ vstr(double_scratch0().low(), scratch0(), 0);
|
||||
} else { // i.e. array_type == kExternalDoubleArray
|
||||
__ vstr(value, scratch0(), 0);
|
||||
}
|
||||
} else {
|
||||
Register value(ToRegister(instr->value()));
|
||||
MemOperand mem_operand(key_is_constant
|
||||
? MemOperand(external_pointer, constant_key * (1 << shift_size))
|
||||
: MemOperand(external_pointer, key, LSL, shift_size));
|
||||
switch (array_type) {
|
||||
case kExternalPixelArray:
|
||||
// Clamp the value to [0..255].
|
||||
__ Usat(value, 8, Operand(value));
|
||||
__ strb(value, MemOperand(external_pointer, key));
|
||||
break;
|
||||
// Fall through to the next case for the store instruction:
|
||||
case kExternalByteArray:
|
||||
case kExternalUnsignedByteArray:
|
||||
__ strb(value, MemOperand(external_pointer, key));
|
||||
__ strb(value, mem_operand);
|
||||
break;
|
||||
case kExternalShortArray:
|
||||
case kExternalUnsignedShortArray:
|
||||
__ strh(value, MemOperand(external_pointer, key, LSL, 1));
|
||||
__ strh(value, mem_operand);
|
||||
break;
|
||||
case kExternalIntArray:
|
||||
case kExternalUnsignedIntArray:
|
||||
__ str(value, MemOperand(external_pointer, key, LSL, 2));
|
||||
__ str(value, mem_operand);
|
||||
break;
|
||||
case kExternalFloatArray:
|
||||
case kExternalDoubleArray:
|
||||
|
@ -2392,39 +2392,56 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
|
||||
}
|
||||
|
||||
|
||||
Operand LCodeGen::BuildExternalArrayOperand(LOperand* external_pointer,
|
||||
LOperand* key,
|
||||
ExternalArrayType array_type) {
|
||||
Register external_pointer_reg = ToRegister(external_pointer);
|
||||
int shift_size = ExternalArrayTypeToShiftSize(array_type);
|
||||
if (key->IsConstantOperand()) {
|
||||
int constant_value = ToInteger32(LConstantOperand::cast(key));
|
||||
if (constant_value & 0xF0000000) {
|
||||
Abort("array index constant value too big");
|
||||
}
|
||||
return Operand(external_pointer_reg, constant_value * (1 << shift_size));
|
||||
} else {
|
||||
ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
|
||||
return Operand(external_pointer_reg, ToRegister(key), scale_factor, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::DoLoadKeyedSpecializedArrayElement(
|
||||
LLoadKeyedSpecializedArrayElement* instr) {
|
||||
Register external_pointer = ToRegister(instr->external_pointer());
|
||||
Register key = ToRegister(instr->key());
|
||||
ExternalArrayType array_type = instr->array_type();
|
||||
Operand operand(BuildExternalArrayOperand(instr->external_pointer(),
|
||||
instr->key(), array_type));
|
||||
if (array_type == kExternalFloatArray) {
|
||||
XMMRegister result(ToDoubleRegister(instr->result()));
|
||||
__ movss(result, Operand(external_pointer, key, times_4, 0));
|
||||
__ movss(result, operand);
|
||||
__ cvtss2sd(result, result);
|
||||
} else if (array_type == kExternalDoubleArray) {
|
||||
__ movdbl(ToDoubleRegister(instr->result()),
|
||||
Operand(external_pointer, key, times_8, 0));
|
||||
__ movdbl(ToDoubleRegister(instr->result()), operand);
|
||||
} else {
|
||||
Register result(ToRegister(instr->result()));
|
||||
switch (array_type) {
|
||||
case kExternalByteArray:
|
||||
__ movsx_b(result, Operand(external_pointer, key, times_1, 0));
|
||||
__ movsx_b(result, operand);
|
||||
break;
|
||||
case kExternalUnsignedByteArray:
|
||||
case kExternalPixelArray:
|
||||
__ movzx_b(result, Operand(external_pointer, key, times_1, 0));
|
||||
__ movzx_b(result, operand);
|
||||
break;
|
||||
case kExternalShortArray:
|
||||
__ movsx_w(result, Operand(external_pointer, key, times_2, 0));
|
||||
__ movsx_w(result, operand);
|
||||
break;
|
||||
case kExternalUnsignedShortArray:
|
||||
__ movzx_w(result, Operand(external_pointer, key, times_2, 0));
|
||||
__ movzx_w(result, operand);
|
||||
break;
|
||||
case kExternalIntArray:
|
||||
__ mov(result, Operand(external_pointer, key, times_4, 0));
|
||||
__ mov(result, operand);
|
||||
break;
|
||||
case kExternalUnsignedIntArray:
|
||||
__ mov(result, Operand(external_pointer, key, times_4, 0));
|
||||
__ mov(result, operand);
|
||||
__ test(result, Operand(result));
|
||||
// TODO(danno): we could be more clever here, perhaps having a special
|
||||
// version of the stub that detects if the overflow case actually
|
||||
@ -3108,15 +3125,14 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
|
||||
|
||||
void LCodeGen::DoStoreKeyedSpecializedArrayElement(
|
||||
LStoreKeyedSpecializedArrayElement* instr) {
|
||||
Register external_pointer = ToRegister(instr->external_pointer());
|
||||
Register key = ToRegister(instr->key());
|
||||
ExternalArrayType array_type = instr->array_type();
|
||||
Operand operand(BuildExternalArrayOperand(instr->external_pointer(),
|
||||
instr->key(), array_type));
|
||||
if (array_type == kExternalFloatArray) {
|
||||
__ cvtsd2ss(xmm0, ToDoubleRegister(instr->value()));
|
||||
__ movss(Operand(external_pointer, key, times_4, 0), xmm0);
|
||||
__ movss(operand, xmm0);
|
||||
} else if (array_type == kExternalDoubleArray) {
|
||||
__ movdbl(Operand(external_pointer, key, times_8, 0),
|
||||
ToDoubleRegister(instr->value()));
|
||||
__ movdbl(operand, ToDoubleRegister(instr->value()));
|
||||
} else {
|
||||
Register value = ToRegister(instr->value());
|
||||
switch (array_type) {
|
||||
@ -3135,20 +3151,20 @@ void LCodeGen::DoStoreKeyedSpecializedArrayElement(
|
||||
__ setcc(negative, temp); // 1 if negative, 0 if positive.
|
||||
__ dec_b(temp); // 0 if negative, 255 if positive.
|
||||
__ bind(&done);
|
||||
__ mov_b(Operand(external_pointer, key, times_1, 0), temp);
|
||||
__ mov_b(operand, temp);
|
||||
break;
|
||||
}
|
||||
case kExternalByteArray:
|
||||
case kExternalUnsignedByteArray:
|
||||
__ mov_b(Operand(external_pointer, key, times_1, 0), value);
|
||||
__ mov_b(operand, value);
|
||||
break;
|
||||
case kExternalShortArray:
|
||||
case kExternalUnsignedShortArray:
|
||||
__ mov_w(Operand(external_pointer, key, times_2, 0), value);
|
||||
__ mov_w(operand, value);
|
||||
break;
|
||||
case kExternalIntArray:
|
||||
case kExternalUnsignedIntArray:
|
||||
__ mov(Operand(external_pointer, key, times_4, 0), value);
|
||||
__ mov(operand, value);
|
||||
break;
|
||||
case kExternalFloatArray:
|
||||
case kExternalDoubleArray:
|
||||
|
@ -229,6 +229,9 @@ class LCodeGen BASE_EMBEDDED {
|
||||
Register ToRegister(int index) const;
|
||||
XMMRegister ToDoubleRegister(int index) const;
|
||||
int ToInteger32(LConstantOperand* op) const;
|
||||
Operand BuildExternalArrayOperand(LOperand* external_pointer,
|
||||
LOperand* key,
|
||||
ExternalArrayType array_type);
|
||||
|
||||
// Specific math operations - used from DoUnaryMathOperation.
|
||||
void EmitIntegerMathAbs(LUnaryMathOperation* instr);
|
||||
|
@ -1895,7 +1895,7 @@ LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
|
||||
array_type == kExternalDoubleArray)));
|
||||
ASSERT(instr->key()->representation().IsInteger32());
|
||||
LOperand* external_pointer = UseRegister(instr->external_pointer());
|
||||
LOperand* key = UseRegister(instr->key());
|
||||
LOperand* key = UseRegisterOrConstant(instr->key());
|
||||
LLoadKeyedSpecializedArrayElement* result =
|
||||
new LLoadKeyedSpecializedArrayElement(external_pointer,
|
||||
key);
|
||||
@ -1950,7 +1950,7 @@ LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
|
||||
ASSERT(instr->key()->representation().IsInteger32());
|
||||
|
||||
LOperand* external_pointer = UseRegister(instr->external_pointer());
|
||||
LOperand* key = UseRegister(instr->key());
|
||||
LOperand* key = UseRegisterOrConstant(instr->key());
|
||||
LOperand* temp = NULL;
|
||||
|
||||
if (array_type == kExternalPixelArray) {
|
||||
|
@ -166,4 +166,25 @@ void LPointerMap::PrintTo(StringStream* stream) {
|
||||
}
|
||||
|
||||
|
||||
int ExternalArrayTypeToShiftSize(ExternalArrayType type) {
|
||||
switch (type) {
|
||||
case kExternalByteArray:
|
||||
case kExternalUnsignedByteArray:
|
||||
case kExternalPixelArray:
|
||||
return 0;
|
||||
case kExternalShortArray:
|
||||
case kExternalUnsignedShortArray:
|
||||
return 1;
|
||||
case kExternalIntArray:
|
||||
case kExternalUnsignedIntArray:
|
||||
case kExternalFloatArray:
|
||||
return 2;
|
||||
case kExternalDoubleArray:
|
||||
return 3;
|
||||
}
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
@ -588,6 +588,10 @@ class DeepIterator BASE_EMBEDDED {
|
||||
ShallowIterator current_iterator_;
|
||||
};
|
||||
|
||||
|
||||
int ExternalArrayTypeToShiftSize(ExternalArrayType type);
|
||||
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
||||
#endif // V8_LITHIUM_H_
|
||||
|
@ -2403,39 +2403,56 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
|
||||
}
|
||||
|
||||
|
||||
Operand LCodeGen::BuildExternalArrayOperand(LOperand* external_pointer,
|
||||
LOperand* key,
|
||||
ExternalArrayType array_type) {
|
||||
Register external_pointer_reg = ToRegister(external_pointer);
|
||||
int shift_size = ExternalArrayTypeToShiftSize(array_type);
|
||||
if (key->IsConstantOperand()) {
|
||||
int constant_value = ToInteger32(LConstantOperand::cast(key));
|
||||
if (constant_value & 0xF0000000) {
|
||||
Abort("array index constant value too big");
|
||||
}
|
||||
return Operand(external_pointer_reg, constant_value * (1 << shift_size));
|
||||
} else {
|
||||
ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
|
||||
return Operand(external_pointer_reg, ToRegister(key), scale_factor, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::DoLoadKeyedSpecializedArrayElement(
|
||||
LLoadKeyedSpecializedArrayElement* instr) {
|
||||
Register external_pointer = ToRegister(instr->external_pointer());
|
||||
Register key = ToRegister(instr->key());
|
||||
ExternalArrayType array_type = instr->array_type();
|
||||
Operand operand(BuildExternalArrayOperand(instr->external_pointer(),
|
||||
instr->key(), array_type));
|
||||
if (array_type == kExternalFloatArray) {
|
||||
XMMRegister result(ToDoubleRegister(instr->result()));
|
||||
__ movss(result, Operand(external_pointer, key, times_4, 0));
|
||||
__ movss(result, operand);
|
||||
__ cvtss2sd(result, result);
|
||||
} else if (array_type == kExternalDoubleArray) {
|
||||
__ movsd(ToDoubleRegister(instr->result()),
|
||||
Operand(external_pointer, key, times_8, 0));
|
||||
__ movsd(ToDoubleRegister(instr->result()), operand);
|
||||
} else {
|
||||
Register result(ToRegister(instr->result()));
|
||||
switch (array_type) {
|
||||
case kExternalByteArray:
|
||||
__ movsxbq(result, Operand(external_pointer, key, times_1, 0));
|
||||
__ movsxbq(result, operand);
|
||||
break;
|
||||
case kExternalUnsignedByteArray:
|
||||
case kExternalPixelArray:
|
||||
__ movzxbq(result, Operand(external_pointer, key, times_1, 0));
|
||||
__ movzxbq(result, operand);
|
||||
break;
|
||||
case kExternalShortArray:
|
||||
__ movsxwq(result, Operand(external_pointer, key, times_2, 0));
|
||||
__ movsxwq(result, operand);
|
||||
break;
|
||||
case kExternalUnsignedShortArray:
|
||||
__ movzxwq(result, Operand(external_pointer, key, times_2, 0));
|
||||
__ movzxwq(result, operand);
|
||||
break;
|
||||
case kExternalIntArray:
|
||||
__ movsxlq(result, Operand(external_pointer, key, times_4, 0));
|
||||
__ movsxlq(result, operand);
|
||||
break;
|
||||
case kExternalUnsignedIntArray:
|
||||
__ movl(result, Operand(external_pointer, key, times_4, 0));
|
||||
__ movl(result, operand);
|
||||
__ testl(result, result);
|
||||
// TODO(danno): we could be more clever here, perhaps having a special
|
||||
// version of the stub that detects if the overflow case actually
|
||||
@ -3097,16 +3114,15 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
|
||||
|
||||
void LCodeGen::DoStoreKeyedSpecializedArrayElement(
|
||||
LStoreKeyedSpecializedArrayElement* instr) {
|
||||
Register external_pointer = ToRegister(instr->external_pointer());
|
||||
Register key = ToRegister(instr->key());
|
||||
ExternalArrayType array_type = instr->array_type();
|
||||
Operand operand(BuildExternalArrayOperand(instr->external_pointer(),
|
||||
instr->key(), array_type));
|
||||
if (array_type == kExternalFloatArray) {
|
||||
XMMRegister value(ToDoubleRegister(instr->value()));
|
||||
__ cvtsd2ss(value, value);
|
||||
__ movss(Operand(external_pointer, key, times_4, 0), value);
|
||||
__ movss(operand, value);
|
||||
} else if (array_type == kExternalDoubleArray) {
|
||||
__ movsd(Operand(external_pointer, key, times_8, 0),
|
||||
ToDoubleRegister(instr->value()));
|
||||
__ movsd(operand, ToDoubleRegister(instr->value()));
|
||||
} else {
|
||||
Register value(ToRegister(instr->value()));
|
||||
switch (array_type) {
|
||||
@ -3118,20 +3134,20 @@ void LCodeGen::DoStoreKeyedSpecializedArrayElement(
|
||||
__ setcc(negative, value); // 1 if negative, 0 if positive.
|
||||
__ decb(value); // 0 if negative, 255 if positive.
|
||||
__ bind(&done);
|
||||
__ movb(Operand(external_pointer, key, times_1, 0), value);
|
||||
__ movb(operand, value);
|
||||
}
|
||||
break;
|
||||
case kExternalByteArray:
|
||||
case kExternalUnsignedByteArray:
|
||||
__ movb(Operand(external_pointer, key, times_1, 0), value);
|
||||
__ movb(operand, value);
|
||||
break;
|
||||
case kExternalShortArray:
|
||||
case kExternalUnsignedShortArray:
|
||||
__ movw(Operand(external_pointer, key, times_2, 0), value);
|
||||
__ movw(operand, value);
|
||||
break;
|
||||
case kExternalIntArray:
|
||||
case kExternalUnsignedIntArray:
|
||||
__ movl(Operand(external_pointer, key, times_4, 0), value);
|
||||
__ movl(operand, value);
|
||||
break;
|
||||
case kExternalFloatArray:
|
||||
case kExternalDoubleArray:
|
||||
|
@ -214,6 +214,9 @@ class LCodeGen BASE_EMBEDDED {
|
||||
|
||||
Register ToRegister(int index) const;
|
||||
XMMRegister ToDoubleRegister(int index) const;
|
||||
Operand BuildExternalArrayOperand(LOperand* external_pointer,
|
||||
LOperand* key,
|
||||
ExternalArrayType array_type);
|
||||
|
||||
// Specific math operations - used from DoUnaryMathOperation.
|
||||
void EmitIntegerMathAbs(LUnaryMathOperation* instr);
|
||||
|
@ -1851,7 +1851,7 @@ LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
|
||||
array_type == kExternalDoubleArray)));
|
||||
ASSERT(instr->key()->representation().IsInteger32());
|
||||
LOperand* external_pointer = UseRegister(instr->external_pointer());
|
||||
LOperand* key = UseRegister(instr->key());
|
||||
LOperand* key = UseRegisterOrConstant(instr->key());
|
||||
LLoadKeyedSpecializedArrayElement* result =
|
||||
new LLoadKeyedSpecializedArrayElement(external_pointer, key);
|
||||
LInstruction* load_instr = DefineAsRegister(result);
|
||||
@ -1908,7 +1908,7 @@ LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
|
||||
LOperand* val = val_is_temp_register
|
||||
? UseTempRegister(instr->value())
|
||||
: UseRegister(instr->value());
|
||||
LOperand* key = UseRegister(instr->key());
|
||||
LOperand* key = UseRegisterOrConstant(instr->key());
|
||||
|
||||
return new LStoreKeyedSpecializedArrayElement(external_pointer,
|
||||
key,
|
||||
|
@ -11953,35 +11953,6 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
|
||||
CHECK_EQ(true, result->BooleanValue());
|
||||
}
|
||||
|
||||
// Test crankshaft external array loads
|
||||
for (int i = 0; i < kElementCount; i++) {
|
||||
array->set(i, static_cast<ElementType>(i));
|
||||
}
|
||||
result = CompileRun("function ee_load_test_func(sum) {"
|
||||
" for (var i = 0; i < 40; ++i)"
|
||||
" sum += ext_array[i];"
|
||||
" return sum;"
|
||||
"}"
|
||||
"sum=0;"
|
||||
"for (var i=0;i<10000;++i) {"
|
||||
" sum=ee_load_test_func(sum);"
|
||||
"}"
|
||||
"sum;");
|
||||
CHECK_EQ(7800000, result->Int32Value());
|
||||
|
||||
// Test crankshaft external array stores
|
||||
result = CompileRun("function ee_store_test_func(sum) {"
|
||||
" for (var i = 0; i < 40; ++i)"
|
||||
" sum += ext_array[i] = i;"
|
||||
" return sum;"
|
||||
"}"
|
||||
"sum=0;"
|
||||
"for (var i=0;i<10000;++i) {"
|
||||
" sum=ee_store_test_func(sum);"
|
||||
"}"
|
||||
"sum;");
|
||||
CHECK_EQ(7800000, result->Int32Value());
|
||||
|
||||
for (int i = 0; i < kElementCount; i++) {
|
||||
array->set(i, static_cast<ElementType>(i));
|
||||
}
|
||||
|
@ -25,7 +25,7 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Flags: --allow-natives-syntax
|
||||
// Flags: --allow-natives-syntax --expose-gc
|
||||
|
||||
// This is a regression test for overlapping key and value registers.
|
||||
function f(a) {
|
||||
@ -43,15 +43,6 @@ f(a);
|
||||
assertEquals(0, a[0]);
|
||||
assertEquals(0, a[1]);
|
||||
|
||||
// Test the correct behavior of the |length| property (which is read-only).
|
||||
a = new Int32Array(42);
|
||||
assertEquals(42, a.length);
|
||||
a.length = 2;
|
||||
assertEquals(42, a.length);
|
||||
assertTrue(delete a.length);
|
||||
a.length = 2
|
||||
assertEquals(2, a.length);
|
||||
|
||||
// Test the correct behavior of the |BYTES_PER_ELEMENT| property (which is
|
||||
// "constant", but not read-only).
|
||||
a = new Int32Array(2);
|
||||
@ -88,3 +79,72 @@ for (var i = 0; i < 5; i++) {
|
||||
%OptimizeFunctionOnNextCall(get);
|
||||
assertEquals(2.5, get(array, 0));
|
||||
assertEquals(3.5, get(array, 1));
|
||||
|
||||
// Test loads and stores.
|
||||
types = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array,
|
||||
Uint32Array, PixelArray, Float32Array, Float64Array];
|
||||
|
||||
const kElementCount = 40;
|
||||
|
||||
function test_load(array, sum) {
|
||||
for (var i = 0; i < kElementCount; i++) {
|
||||
sum += array[i];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
function test_load_const_key(array, sum) {
|
||||
sum += array[0];
|
||||
sum += array[1];
|
||||
sum += array[2];
|
||||
return sum;
|
||||
}
|
||||
|
||||
function test_store(array, sum) {
|
||||
for (var i = 0; i < kElementCount; i++) {
|
||||
sum += array[i] = i+1;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
function test_store_const_key(array, sum) {
|
||||
sum += array[0] = 1;
|
||||
sum += array[1] = 2;
|
||||
sum += array[2] = 3;
|
||||
return sum;
|
||||
}
|
||||
|
||||
function run_test(test_func, array, expected_sum_per_run) {
|
||||
for (var i = 0; i < 5; i++) test_func(array, 0);
|
||||
%OptimizeFunctionOnNextCall(test_func);
|
||||
const kRuns = 10;
|
||||
var sum = 0;
|
||||
for (var i = 0; i < kRuns; i++) {
|
||||
sum = test_func(array, sum);
|
||||
}
|
||||
assertEquals(sum, expected_sum_per_run * kRuns);
|
||||
%DeoptimizeFunction(test_func);
|
||||
gc(); // Makes V8 forget about type information for test_func.
|
||||
}
|
||||
|
||||
for (var t = 0; t < types.length; t++) {
|
||||
var type = types[t];
|
||||
var a = new type(kElementCount);
|
||||
for (var i = 0; i < kElementCount; i++) {
|
||||
a[i] = i;
|
||||
}
|
||||
|
||||
// Run test functions defined above.
|
||||
run_test(test_load, a, 780);
|
||||
run_test(test_load_const_key, a, 3);
|
||||
run_test(test_store, a, 820);
|
||||
run_test(test_store_const_key, a, 6);
|
||||
|
||||
// Test the correct behavior of the |length| property (which is read-only).
|
||||
assertEquals(kElementCount, a.length);
|
||||
a.length = 2;
|
||||
assertEquals(kElementCount, a.length);
|
||||
assertTrue(delete a.length);
|
||||
a.length = 2
|
||||
assertEquals(2, a.length);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user