| Index: src/ia32/codegen-ia32.cc
|
| ===================================================================
|
| --- src/ia32/codegen-ia32.cc (revision 4792)
|
| +++ src/ia32/codegen-ia32.cc (working copy)
|
| @@ -2624,9 +2624,8 @@
|
| ASSERT(temp.is_valid());
|
| __ mov(temp.reg(),
|
| FieldOperand(operand.reg(), HeapObject::kMapOffset));
|
| - __ movzx_b(temp.reg(),
|
| - FieldOperand(temp.reg(), Map::kBitFieldOffset));
|
| - __ test(temp.reg(), Immediate(1 << Map::kIsUndetectable));
|
| + __ test_b(FieldOperand(temp.reg(), Map::kBitFieldOffset),
|
| + 1 << Map::kIsUndetectable);
|
| temp.Unuse();
|
| operand.Unuse();
|
| dest->Split(not_zero);
|
| @@ -2720,11 +2719,9 @@
|
| // left_side is a sequential ASCII string.
|
| left_side = Result(left_reg);
|
| right_side = Result(right_val);
|
| - Result temp2 = allocator_->Allocate();
|
| - ASSERT(temp2.is_valid());
|
| // Test string equality and comparison.
|
| + Label comparison_done;
|
| if (cc == equal) {
|
| - Label comparison_done;
|
| __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset),
|
| Immediate(Smi::FromInt(1)));
|
| __ j(not_equal, &comparison_done);
|
| @@ -2732,34 +2729,25 @@
|
| static_cast<uint8_t>(String::cast(*right_val)->Get(0));
|
| __ cmpb(FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize),
|
| char_value);
|
| - __ bind(&comparison_done);
|
| } else {
|
| - __ mov(temp2.reg(),
|
| - FieldOperand(left_side.reg(), String::kLengthOffset));
|
| - __ SmiUntag(temp2.reg());
|
| - __ sub(Operand(temp2.reg()), Immediate(1));
|
| - Label comparison;
|
| - // If the length is 0 then the subtraction gave -1 which compares less
|
| - // than any character.
|
| - __ j(negative, &comparison);
|
| - // Otherwise load the first character.
|
| - __ movzx_b(temp2.reg(),
|
| - FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize));
|
| - __ bind(&comparison);
|
| + __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset),
|
| + Immediate(Smi::FromInt(1)));
|
| + // If the length is 0 then the jump is taken and the flags
|
| + // correctly represent being less than the one-character string.
|
| + __ j(below, &comparison_done);
|
| // Compare the first character of the string with the
|
| // constant 1-character string.
|
| uint8_t char_value =
|
| static_cast<uint8_t>(String::cast(*right_val)->Get(0));
|
| - __ cmp(Operand(temp2.reg()), Immediate(char_value));
|
| - Label characters_were_different;
|
| - __ j(not_equal, &characters_were_different);
|
| + __ cmpb(FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize),
|
| + char_value);
|
| + __ j(not_equal, &comparison_done);
|
| // If the first character is the same then the long string sorts after
|
| // the short one.
|
| __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset),
|
| Immediate(Smi::FromInt(1)));
|
| - __ bind(&characters_were_different);
|
| }
|
| - temp2.Unuse();
|
| + __ bind(&comparison_done);
|
| left_side.Unuse();
|
| right_side.Unuse();
|
| dest->Split(cc);
|
| @@ -4148,9 +4136,7 @@
|
| // eax: value to be iterated over
|
| __ test(eax, Immediate(kSmiTagMask));
|
| primitive.Branch(zero);
|
| - __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
|
| - __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
|
| - __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
|
| + __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx);
|
| jsobject.Branch(above_equal);
|
|
|
| primitive.Bind();
|
| @@ -6317,14 +6303,15 @@
|
| ASSERT(map.is_valid());
|
| __ mov(map.reg(), FieldOperand(obj.reg(), HeapObject::kMapOffset));
|
| // Undetectable objects behave like undefined when tested with typeof.
|
| - __ movzx_b(map.reg(), FieldOperand(map.reg(), Map::kBitFieldOffset));
|
| - __ test(map.reg(), Immediate(1 << Map::kIsUndetectable));
|
| + __ test_b(FieldOperand(map.reg(), Map::kBitFieldOffset),
|
| + 1 << Map::kIsUndetectable);
|
| destination()->false_target()->Branch(not_zero);
|
| - __ mov(map.reg(), FieldOperand(obj.reg(), HeapObject::kMapOffset));
|
| + // Do a range test for JSObject type. We can't use
|
| + // MacroAssembler::IsInstanceJSObjectType, because we are using a
|
| + // ControlDestination, so we copy its implementation here.
|
| __ movzx_b(map.reg(), FieldOperand(map.reg(), Map::kInstanceTypeOffset));
|
| - __ cmp(map.reg(), FIRST_JS_OBJECT_TYPE);
|
| - destination()->false_target()->Branch(below);
|
| - __ cmp(map.reg(), LAST_JS_OBJECT_TYPE);
|
| + __ sub(Operand(map.reg()), Immediate(FIRST_JS_OBJECT_TYPE));
|
| + __ cmp(map.reg(), LAST_JS_OBJECT_TYPE - FIRST_JS_OBJECT_TYPE);
|
| obj.Unuse();
|
| map.Unuse();
|
| destination()->Split(below_equal);
|
| @@ -6360,9 +6347,8 @@
|
| ASSERT(temp.is_valid());
|
| __ mov(temp.reg(),
|
| FieldOperand(obj.reg(), HeapObject::kMapOffset));
|
| - __ movzx_b(temp.reg(),
|
| - FieldOperand(temp.reg(), Map::kBitFieldOffset));
|
| - __ test(temp.reg(), Immediate(1 << Map::kIsUndetectable));
|
| + __ test_b(FieldOperand(temp.reg(), Map::kBitFieldOffset),
|
| + 1 << Map::kIsUndetectable);
|
| obj.Unuse();
|
| temp.Unuse();
|
| destination()->Split(not_zero);
|
| @@ -6436,20 +6422,16 @@
|
|
|
| // Check that the object is a JS object but take special care of JS
|
| // functions to make sure they have 'Function' as their class.
|
| - { Result tmp = allocator()->Allocate();
|
| - __ mov(obj.reg(), FieldOperand(obj.reg(), HeapObject::kMapOffset));
|
| - __ movzx_b(tmp.reg(), FieldOperand(obj.reg(), Map::kInstanceTypeOffset));
|
| - __ cmp(tmp.reg(), FIRST_JS_OBJECT_TYPE);
|
| - null.Branch(below);
|
| + __ CmpObjectType(obj.reg(), FIRST_JS_OBJECT_TYPE, obj.reg());
|
| + null.Branch(below);
|
|
|
| - // As long as JS_FUNCTION_TYPE is the last instance type and it is
|
| - // right after LAST_JS_OBJECT_TYPE, we can avoid checking for
|
| - // LAST_JS_OBJECT_TYPE.
|
| - ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
|
| - ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1);
|
| - __ cmp(tmp.reg(), JS_FUNCTION_TYPE);
|
| - function.Branch(equal);
|
| - }
|
| + // As long as JS_FUNCTION_TYPE is the last instance type and it is
|
| + // right after LAST_JS_OBJECT_TYPE, we can avoid checking for
|
| + // LAST_JS_OBJECT_TYPE.
|
| + ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
|
| + ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1);
|
| + __ CmpInstanceType(obj.reg(), JS_FUNCTION_TYPE);
|
| + function.Branch(equal);
|
|
|
| // Check if the constructor in the map is a function.
|
| { Result tmp = allocator()->Allocate();
|
| @@ -7030,8 +7012,8 @@
|
| // has no indexed interceptor.
|
| __ CmpObjectType(object.reg(), FIRST_JS_OBJECT_TYPE, tmp1.reg());
|
| deferred->Branch(below);
|
| - __ movzx_b(tmp1.reg(), FieldOperand(tmp1.reg(), Map::kBitFieldOffset));
|
| - __ test(tmp1.reg(), Immediate(KeyedLoadIC::kSlowCaseBitFieldMask));
|
| + __ test_b(FieldOperand(tmp1.reg(), Map::kBitFieldOffset),
|
| + KeyedLoadIC::kSlowCaseBitFieldMask);
|
| deferred->Branch(not_zero);
|
|
|
| // Check the object's elements are in fast case.
|
| @@ -8285,10 +8267,10 @@
|
| Result temp = allocator()->Allocate();
|
| ASSERT(temp.is_valid());
|
| __ mov(temp.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset));
|
| - __ movzx_b(temp.reg(), FieldOperand(temp.reg(), Map::kBitFieldOffset));
|
| - __ test(temp.reg(), Immediate(1 << Map::kIsUndetectable));
|
| + __ test_b(FieldOperand(temp.reg(), Map::kBitFieldOffset),
|
| + 1 << Map::kIsUndetectable);
|
| destination()->false_target()->Branch(not_zero);
|
| - __ CmpObjectType(answer.reg(), FIRST_NONSTRING_TYPE, temp.reg());
|
| + __ CmpInstanceType(temp.reg(), FIRST_NONSTRING_TYPE);
|
| temp.Unuse();
|
| answer.Unuse();
|
| destination()->Split(below);
|
| @@ -8310,9 +8292,8 @@
|
| // It can be an undetectable object.
|
| frame_->Spill(answer.reg());
|
| __ mov(answer.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset));
|
| - __ movzx_b(answer.reg(),
|
| - FieldOperand(answer.reg(), Map::kBitFieldOffset));
|
| - __ test(answer.reg(), Immediate(1 << Map::kIsUndetectable));
|
| + __ test_b(FieldOperand(answer.reg(), Map::kBitFieldOffset),
|
| + 1 << Map::kIsUndetectable);
|
| answer.Unuse();
|
| destination()->Split(not_zero);
|
|
|
| @@ -8339,14 +8320,15 @@
|
| destination()->false_target()->Branch(equal);
|
|
|
| // It can be an undetectable object.
|
| - __ movzx_b(map.reg(), FieldOperand(map.reg(), Map::kBitFieldOffset));
|
| - __ test(map.reg(), Immediate(1 << Map::kIsUndetectable));
|
| + __ test_b(FieldOperand(map.reg(), Map::kBitFieldOffset),
|
| + 1 << Map::kIsUndetectable);
|
| destination()->false_target()->Branch(not_zero);
|
| - __ mov(map.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset));
|
| + // Do a range test for JSObject type. We can't use
|
| + // MacroAssembler::IsInstanceJSObjectType, because we are using a
|
| + // ControlDestination, so we copy its implementation here.
|
| __ movzx_b(map.reg(), FieldOperand(map.reg(), Map::kInstanceTypeOffset));
|
| - __ cmp(map.reg(), FIRST_JS_OBJECT_TYPE);
|
| - destination()->false_target()->Branch(below);
|
| - __ cmp(map.reg(), LAST_JS_OBJECT_TYPE);
|
| + __ sub(Operand(map.reg()), Immediate(FIRST_JS_OBJECT_TYPE));
|
| + __ cmp(map.reg(), LAST_JS_OBJECT_TYPE - FIRST_JS_OBJECT_TYPE);
|
| answer.Unuse();
|
| map.Unuse();
|
| destination()->Split(below_equal);
|
| @@ -9273,20 +9255,19 @@
|
| __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset));
|
|
|
| // Undetectable => false.
|
| - __ movzx_b(ebx, FieldOperand(edx, Map::kBitFieldOffset));
|
| - __ and_(ebx, 1 << Map::kIsUndetectable);
|
| + __ test_b(FieldOperand(edx, Map::kBitFieldOffset),
|
| + 1 << Map::kIsUndetectable);
|
| __ j(not_zero, &false_result);
|
|
|
| // JavaScript object => true.
|
| - __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
|
| + __ CmpInstanceType(edx, FIRST_JS_OBJECT_TYPE);
|
| __ j(above_equal, &true_result);
|
|
|
| // String value => false iff empty.
|
| - __ cmp(ecx, FIRST_NONSTRING_TYPE);
|
| + __ CmpInstanceType(edx, FIRST_NONSTRING_TYPE);
|
| __ j(above_equal, ¬_string);
|
| - __ mov(edx, FieldOperand(eax, String::kLengthOffset));
|
| ASSERT(kSmiTag == 0);
|
| - __ test(edx, Operand(edx));
|
| + __ cmp(FieldOperand(eax, String::kLengthOffset), Immediate(0));
|
| __ j(zero, &false_result);
|
| __ jmp(&true_result);
|
|
|
| @@ -11742,13 +11723,10 @@
|
| // There is no test for undetectability in strict equality.
|
|
|
| // Get the type of the first operand.
|
| - __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
|
| - __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
|
| -
|
| // If the first object is a JS object, we have done pointer comparison.
|
| - ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
|
| Label first_non_object;
|
| - __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
|
| + ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
|
| + __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx);
|
| __ j(below, &first_non_object);
|
|
|
| // Return non-zero (eax is not zero)
|
| @@ -11759,17 +11737,14 @@
|
|
|
| __ bind(&first_non_object);
|
| // Check for oddballs: true, false, null, undefined.
|
| - __ cmp(ecx, ODDBALL_TYPE);
|
| + __ CmpInstanceType(ecx, ODDBALL_TYPE);
|
| __ j(equal, &return_not_equal);
|
|
|
| - __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
|
| - __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
|
| -
|
| - __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
|
| + __ CmpObjectType(edx, FIRST_JS_OBJECT_TYPE, ecx);
|
| __ j(above_equal, &return_not_equal);
|
|
|
| // Check for oddballs: true, false, null, undefined.
|
| - __ cmp(ecx, ODDBALL_TYPE);
|
| + __ CmpInstanceType(ecx, ODDBALL_TYPE);
|
| __ j(equal, &return_not_equal);
|
|
|
| // Fall through to the general case.
|
| @@ -12411,12 +12386,7 @@
|
| __ j(zero, &slow, not_taken);
|
|
|
| // Check that the left hand is a JS object.
|
| - __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); // eax - object map
|
| - __ movzx_b(ecx, FieldOperand(eax, Map::kInstanceTypeOffset)); // ecx - type
|
| - __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
|
| - __ j(below, &slow, not_taken);
|
| - __ cmp(ecx, LAST_JS_OBJECT_TYPE);
|
| - __ j(above, &slow, not_taken);
|
| + __ IsObjectJSObjectType(eax, eax, edx, &slow);
|
|
|
| // Get the prototype of the function.
|
| __ mov(edx, Operand(esp, 1 * kPointerSize)); // 1 ~ return address
|
| @@ -12441,12 +12411,7 @@
|
| // Check that the function prototype is a JS object.
|
| __ test(ebx, Immediate(kSmiTagMask));
|
| __ j(zero, &slow, not_taken);
|
| - __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset));
|
| - __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
|
| - __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
|
| - __ j(below, &slow, not_taken);
|
| - __ cmp(ecx, LAST_JS_OBJECT_TYPE);
|
| - __ j(above, &slow, not_taken);
|
| + __ IsObjectJSObjectType(ebx, ecx, ecx, &slow);
|
|
|
| // Register mapping:
|
| // eax is object map.
|
| @@ -12881,14 +12846,12 @@
|
| // ebx: length of resulting flat string as a smi
|
| // edx: second string
|
| Label non_ascii_string_add_flat_result;
|
| - __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
|
| - __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
|
| ASSERT(kStringEncodingMask == kAsciiStringTag);
|
| - __ test(ecx, Immediate(kAsciiStringTag));
|
| + __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
|
| + __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag);
|
| __ j(zero, &non_ascii_string_add_flat_result);
|
| __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
|
| - __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
|
| - __ test(ecx, Immediate(kAsciiStringTag));
|
| + __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag);
|
| __ j(zero, &string_add_runtime);
|
|
|
| __ bind(&make_flat_ascii_string);
|
| @@ -12929,8 +12892,7 @@
|
| // edx: second string
|
| __ bind(&non_ascii_string_add_flat_result);
|
| __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
|
| - __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
|
| - __ and_(ecx, kAsciiStringTag);
|
| + __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag);
|
| __ j(not_zero, &string_add_runtime);
|
| // Both strings are two byte strings. As they are short they are both
|
| // flat.
|
|
|