Add missing type feedback collection to ia32 BinaryOpStubs for bitwise operations

Review URL: https://codereview.chromium.org/12223039

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13624 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent b09cc0be
...@@ -747,25 +747,14 @@ class FloatingPointHelper : public AllStatic { ...@@ -747,25 +747,14 @@ class FloatingPointHelper : public AllStatic {
Label* non_float, Label* non_float,
Register scratch); Register scratch);
// Checks that the two floating point numbers on top of the FPU stack
// have int32 values.
static void CheckFloatOperandsAreInt32(MacroAssembler* masm,
Label* non_int32);
// Takes the operands in edx and eax and loads them as integers in eax // Takes the operands in edx and eax and loads them as integers in eax
// and ecx. // and ecx.
static void LoadUnknownsAsIntegers(MacroAssembler* masm, static void LoadUnknownsAsIntegers(MacroAssembler* masm,
bool use_sse3, bool use_sse3,
BinaryOpIC::TypeInfo left_type,
BinaryOpIC::TypeInfo right_type,
Label* operand_conversion_failure); Label* operand_conversion_failure);
// Must only be called after LoadUnknownsAsIntegers. Assumes that the
// operands are pushed on the stack, and that their conversions to int32
// are in eax and ecx. Checks that the original numbers were in the int32
// range.
static void CheckLoadedIntegersWereInt32(MacroAssembler* masm,
bool use_sse3,
Label* not_int32);
// Assumes that operands are smis or heap numbers and loads them // Assumes that operands are smis or heap numbers and loads them
// into xmm0 and xmm1. Operands are in edx and eax. // into xmm0 and xmm1. Operands are in edx and eax.
// Leaves operands unchanged. // Leaves operands unchanged.
...@@ -787,9 +776,12 @@ class FloatingPointHelper : public AllStatic { ...@@ -787,9 +776,12 @@ class FloatingPointHelper : public AllStatic {
Label* non_int32, Label* non_int32,
Register scratch); Register scratch);
// Checks that |operand| has an int32 value. If |int32_result| is different
// from |scratch|, it will contain that int32 value.
static void CheckSSE2OperandIsInt32(MacroAssembler* masm, static void CheckSSE2OperandIsInt32(MacroAssembler* masm,
Label* non_int32, Label* non_int32,
XMMRegister operand, XMMRegister operand,
Register int32_result,
Register scratch, Register scratch,
XMMRegister xmm_scratch); XMMRegister xmm_scratch);
}; };
...@@ -923,6 +915,18 @@ static void IntegerConvert(MacroAssembler* masm, ...@@ -923,6 +915,18 @@ static void IntegerConvert(MacroAssembler* masm,
} }
// Uses SSE2 to convert the heap number in |source| to an integer. Jumps to
// |conversion_failure| if the heap number did not contain an int32 value.
// Result is in ecx. Trashes ebx, xmm0, and xmm1.
static void ConvertHeapNumberToInt32(MacroAssembler* masm,
Register source,
Label* conversion_failure) {
__ movdbl(xmm0, FieldOperand(source, HeapNumber::kValueOffset));
FloatingPointHelper::CheckSSE2OperandIsInt32(
masm, conversion_failure, xmm0, ecx, ebx, xmm1);
}
void UnaryOpStub::PrintName(StringStream* stream) { void UnaryOpStub::PrintName(StringStream* stream) {
const char* op_name = Token::Name(op_); const char* op_name = Token::Name(op_);
const char* overwrite_name = NULL; // Make g++ happy. const char* overwrite_name = NULL; // Make g++ happy.
...@@ -1797,7 +1801,7 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { ...@@ -1797,7 +1801,7 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
// Check result type if it is currently Int32. // Check result type if it is currently Int32.
if (result_type_ <= BinaryOpIC::INT32) { if (result_type_ <= BinaryOpIC::INT32) {
FloatingPointHelper::CheckSSE2OperandIsInt32( FloatingPointHelper::CheckSSE2OperandIsInt32(
masm, &not_int32, xmm0, ecx, xmm2); masm, &not_int32, xmm0, ecx, ecx, xmm2);
} }
BinaryOpStub_GenerateHeapResultAllocation(masm, &call_runtime, mode_); BinaryOpStub_GenerateHeapResultAllocation(masm, &call_runtime, mode_);
__ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
...@@ -1809,7 +1813,6 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { ...@@ -1809,7 +1813,6 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
masm, masm,
ecx, ecx,
FloatingPointHelper::ARGS_IN_REGISTERS); FloatingPointHelper::ARGS_IN_REGISTERS);
FloatingPointHelper::CheckFloatOperandsAreInt32(masm, &not_int32);
if (op_ == Token::MOD) { if (op_ == Token::MOD) {
// The operands are now on the FPU stack, but we don't need them. // The operands are now on the FPU stack, but we don't need them.
__ fstp(0); __ fstp(0);
...@@ -1851,15 +1854,9 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { ...@@ -1851,15 +1854,9 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
Label not_floats; Label not_floats;
Label not_int32; Label not_int32;
Label non_smi_result; Label non_smi_result;
// We do not check the input arguments here, as any value is
// unconditionally truncated to an int32 anyway. To get the
// right optimized code, int32 type feedback is just right.
bool use_sse3 = platform_specific_bit_; bool use_sse3 = platform_specific_bit_;
FloatingPointHelper::LoadUnknownsAsIntegers(masm, FloatingPointHelper::LoadUnknownsAsIntegers(
use_sse3, masm, use_sse3, left_type_, right_type_, &not_floats);
&not_floats);
FloatingPointHelper::CheckLoadedIntegersWereInt32(masm, use_sse3,
&not_int32);
switch (op_) { switch (op_) {
case Token::BIT_OR: __ or_(eax, ecx); break; case Token::BIT_OR: __ or_(eax, ecx); break;
case Token::BIT_AND: __ and_(eax, ecx); break; case Token::BIT_AND: __ and_(eax, ecx); break;
...@@ -2013,11 +2010,11 @@ void BinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { ...@@ -2013,11 +2010,11 @@ void BinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
FloatingPointHelper::LoadSSE2Operands(masm, &not_floats); FloatingPointHelper::LoadSSE2Operands(masm, &not_floats);
if (left_type_ == BinaryOpIC::INT32) { if (left_type_ == BinaryOpIC::INT32) {
FloatingPointHelper::CheckSSE2OperandIsInt32( FloatingPointHelper::CheckSSE2OperandIsInt32(
masm, &not_floats, xmm0, ecx, xmm2); masm, &not_floats, xmm0, ecx, ecx, xmm2);
} }
if (right_type_ == BinaryOpIC::INT32) { if (right_type_ == BinaryOpIC::INT32) {
FloatingPointHelper::CheckSSE2OperandIsInt32( FloatingPointHelper::CheckSSE2OperandIsInt32(
masm, &not_floats, xmm1, ecx, xmm2); masm, &not_floats, xmm1, ecx, ecx, xmm2);
} }
switch (op_) { switch (op_) {
...@@ -2075,9 +2072,8 @@ void BinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { ...@@ -2075,9 +2072,8 @@ void BinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
// unconditionally truncated to an int32 anyway. To get the // unconditionally truncated to an int32 anyway. To get the
// right optimized code, int32 type feedback is just right. // right optimized code, int32 type feedback is just right.
bool use_sse3 = platform_specific_bit_; bool use_sse3 = platform_specific_bit_;
FloatingPointHelper::LoadUnknownsAsIntegers(masm, FloatingPointHelper::LoadUnknownsAsIntegers(
use_sse3, masm, use_sse3, left_type_, right_type_, &not_floats);
&not_floats);
switch (op_) { switch (op_) {
case Token::BIT_OR: __ or_(eax, ecx); break; case Token::BIT_OR: __ or_(eax, ecx); break;
case Token::BIT_AND: __ and_(eax, ecx); break; case Token::BIT_AND: __ and_(eax, ecx); break;
...@@ -2256,6 +2252,8 @@ void BinaryOpStub::GenerateGeneric(MacroAssembler* masm) { ...@@ -2256,6 +2252,8 @@ void BinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
bool use_sse3 = platform_specific_bit_; bool use_sse3 = platform_specific_bit_;
FloatingPointHelper::LoadUnknownsAsIntegers(masm, FloatingPointHelper::LoadUnknownsAsIntegers(masm,
use_sse3, use_sse3,
BinaryOpIC::GENERIC,
BinaryOpIC::GENERIC,
&call_runtime); &call_runtime);
switch (op_) { switch (op_) {
case Token::BIT_OR: __ or_(eax, ecx); break; case Token::BIT_OR: __ or_(eax, ecx); break;
...@@ -2736,16 +2734,24 @@ void TranscendentalCacheStub::GenerateOperation( ...@@ -2736,16 +2734,24 @@ void TranscendentalCacheStub::GenerateOperation(
// Input: edx, eax are the left and right objects of a bit op. // Input: edx, eax are the left and right objects of a bit op.
// Output: eax, ecx are left and right integers for a bit op. // Output: eax, ecx are left and right integers for a bit op.
void FloatingPointHelper::LoadUnknownsAsIntegers(MacroAssembler* masm, // Warning: can clobber inputs even when it jumps to |conversion_failure|!
bool use_sse3, void FloatingPointHelper::LoadUnknownsAsIntegers(
Label* conversion_failure) { MacroAssembler* masm,
bool use_sse3,
BinaryOpIC::TypeInfo left_type,
BinaryOpIC::TypeInfo right_type,
Label* conversion_failure) {
// Check float operands. // Check float operands.
Label arg1_is_object, check_undefined_arg1; Label arg1_is_object, check_undefined_arg1;
Label arg2_is_object, check_undefined_arg2; Label arg2_is_object, check_undefined_arg2;
Label load_arg2, done; Label load_arg2, done;
// Test if arg1 is a Smi. // Test if arg1 is a Smi.
__ JumpIfNotSmi(edx, &arg1_is_object, Label::kNear); if (left_type == BinaryOpIC::SMI) {
__ JumpIfNotSmi(edx, conversion_failure);
} else {
__ JumpIfNotSmi(edx, &arg1_is_object, Label::kNear);
}
__ SmiUntag(edx); __ SmiUntag(edx);
__ jmp(&load_arg2); __ jmp(&load_arg2);
...@@ -2761,17 +2767,27 @@ void FloatingPointHelper::LoadUnknownsAsIntegers(MacroAssembler* masm, ...@@ -2761,17 +2767,27 @@ void FloatingPointHelper::LoadUnknownsAsIntegers(MacroAssembler* masm,
__ bind(&arg1_is_object); __ bind(&arg1_is_object);
__ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
__ cmp(ebx, factory->heap_number_map()); __ cmp(ebx, factory->heap_number_map());
__ j(not_equal, &check_undefined_arg1); if (left_type == BinaryOpIC::INT32 && CpuFeatures::IsSupported(SSE2)) {
CpuFeatures::Scope use_sse2(SSE2);
// Get the untagged integer version of the edx heap number in ecx. __ j(not_equal, conversion_failure);
IntegerConvert(masm, edx, use_sse3, conversion_failure); // Get the untagged integer version of the edx heap number in ecx.
ConvertHeapNumberToInt32(masm, edx, conversion_failure);
} else {
__ j(not_equal, &check_undefined_arg1);
// Get the untagged integer version of the edx heap number in ecx.
IntegerConvert(masm, edx, use_sse3, conversion_failure);
}
__ mov(edx, ecx); __ mov(edx, ecx);
// Here edx has the untagged integer, eax has a Smi or a heap number. // Here edx has the untagged integer, eax has a Smi or a heap number.
__ bind(&load_arg2); __ bind(&load_arg2);
// Test if arg2 is a Smi. // Test if arg2 is a Smi.
__ JumpIfNotSmi(eax, &arg2_is_object, Label::kNear); if (right_type == BinaryOpIC::SMI) {
__ JumpIfNotSmi(eax, conversion_failure);
} else {
__ JumpIfNotSmi(eax, &arg2_is_object, Label::kNear);
}
__ SmiUntag(eax); __ SmiUntag(eax);
__ mov(ecx, eax); __ mov(ecx, eax);
...@@ -2787,22 +2803,22 @@ void FloatingPointHelper::LoadUnknownsAsIntegers(MacroAssembler* masm, ...@@ -2787,22 +2803,22 @@ void FloatingPointHelper::LoadUnknownsAsIntegers(MacroAssembler* masm,
__ bind(&arg2_is_object); __ bind(&arg2_is_object);
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
__ cmp(ebx, factory->heap_number_map()); __ cmp(ebx, factory->heap_number_map());
__ j(not_equal, &check_undefined_arg2); if (right_type == BinaryOpIC::INT32 && CpuFeatures::IsSupported(SSE2)) {
CpuFeatures::Scope use_sse2(SSE2);
__ j(not_equal, conversion_failure);
// Get the untagged integer version of the eax heap number in ecx.
ConvertHeapNumberToInt32(masm, eax, conversion_failure);
} else {
__ j(not_equal, &check_undefined_arg2);
// Get the untagged integer version of the eax heap number in ecx.
IntegerConvert(masm, eax, use_sse3, conversion_failure);
}
// Get the untagged integer version of the eax heap number in ecx.
IntegerConvert(masm, eax, use_sse3, conversion_failure);
__ bind(&done); __ bind(&done);
__ mov(eax, edx); __ mov(eax, edx);
} }
void FloatingPointHelper::CheckLoadedIntegersWereInt32(MacroAssembler* masm,
bool use_sse3,
Label* not_int32) {
return;
}
void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm,
Register number) { Register number) {
Label load_smi, done; Label load_smi, done;
...@@ -2897,18 +2913,19 @@ void FloatingPointHelper::LoadSSE2Smis(MacroAssembler* masm, ...@@ -2897,18 +2913,19 @@ void FloatingPointHelper::LoadSSE2Smis(MacroAssembler* masm,
void FloatingPointHelper::CheckSSE2OperandsAreInt32(MacroAssembler* masm, void FloatingPointHelper::CheckSSE2OperandsAreInt32(MacroAssembler* masm,
Label* non_int32, Label* non_int32,
Register scratch) { Register scratch) {
CheckSSE2OperandIsInt32(masm, non_int32, xmm0, scratch, xmm2); CheckSSE2OperandIsInt32(masm, non_int32, xmm0, scratch, scratch, xmm2);
CheckSSE2OperandIsInt32(masm, non_int32, xmm1, scratch, xmm2); CheckSSE2OperandIsInt32(masm, non_int32, xmm1, scratch, scratch, xmm2);
} }
void FloatingPointHelper::CheckSSE2OperandIsInt32(MacroAssembler* masm, void FloatingPointHelper::CheckSSE2OperandIsInt32(MacroAssembler* masm,
Label* non_int32, Label* non_int32,
XMMRegister operand, XMMRegister operand,
Register int32_result,
Register scratch, Register scratch,
XMMRegister xmm_scratch) { XMMRegister xmm_scratch) {
__ cvttsd2si(scratch, Operand(operand)); __ cvttsd2si(int32_result, Operand(operand));
__ cvtsi2sd(xmm_scratch, scratch); __ cvtsi2sd(xmm_scratch, int32_result);
__ pcmpeqd(xmm_scratch, operand); __ pcmpeqd(xmm_scratch, operand);
__ movmskps(scratch, xmm_scratch); __ movmskps(scratch, xmm_scratch);
// Two least significant bits should be both set. // Two least significant bits should be both set.
...@@ -2998,12 +3015,6 @@ void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm, ...@@ -2998,12 +3015,6 @@ void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm,
} }
void FloatingPointHelper::CheckFloatOperandsAreInt32(MacroAssembler* masm,
Label* non_int32) {
return;
}
void MathPowStub::Generate(MacroAssembler* masm) { void MathPowStub::Generate(MacroAssembler* masm) {
CpuFeatures::Scope use_sse2(SSE2); CpuFeatures::Scope use_sse2(SSE2);
Factory* factory = masm->isolate()->factory(); Factory* factory = masm->isolate()->factory();
......
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