Index: src/ia32/code-stubs-ia32.cc |
=================================================================== |
--- src/ia32/code-stubs-ia32.cc (revision 8868) |
+++ src/ia32/code-stubs-ia32.cc (working copy) |
@@ -249,20 +249,20 @@ |
} |
// undefined -> false |
- CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false, &patch); |
+ CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false); |
// Boolean -> its value |
- CheckOddball(masm, BOOLEAN, Heap::kFalseValueRootIndex, false, &patch); |
- CheckOddball(masm, BOOLEAN, Heap::kTrueValueRootIndex, true, &patch); |
+ CheckOddball(masm, BOOLEAN, Heap::kFalseValueRootIndex, false); |
+ CheckOddball(masm, BOOLEAN, Heap::kTrueValueRootIndex, true); |
// 'null' -> false. |
- CheckOddball(masm, NULL_TYPE, Heap::kNullValueRootIndex, false, &patch); |
+ CheckOddball(masm, NULL_TYPE, Heap::kNullValueRootIndex, false); |
if (types_.Contains(SMI)) { |
// Smis: 0 -> false, all other -> true |
Label not_smi; |
__ JumpIfNotSmi(argument, ¬_smi, Label::kNear); |
- // argument contains the correct return value already |
+ // argument contains the correct return value already. |
if (!tos_.is(argument)) { |
__ mov(tos_, argument); |
} |
@@ -276,15 +276,16 @@ |
if (types_.NeedsMap()) { |
__ mov(map, FieldOperand(argument, HeapObject::kMapOffset)); |
- // Everything with a map could be undetectable, so check this now. |
- __ test_b(FieldOperand(map, Map::kBitFieldOffset), |
- 1 << Map::kIsUndetectable); |
- // Undetectable -> false. |
- Label not_undetectable; |
- __ j(zero, ¬_undetectable, Label::kNear); |
- __ Set(tos_, Immediate(0)); |
- __ ret(1 * kPointerSize); |
- __ bind(¬_undetectable); |
+ if (types_.CanBeUndetectable()) { |
+ __ test_b(FieldOperand(map, Map::kBitFieldOffset), |
+ 1 << Map::kIsUndetectable); |
+ // Undetectable -> false. |
+ Label not_undetectable; |
+ __ j(zero, ¬_undetectable, Label::kNear); |
+ __ Set(tos_, Immediate(0)); |
+ __ ret(1 * kPointerSize); |
+ __ bind(¬_undetectable); |
+ } |
} |
if (types_.Contains(SPEC_OBJECT)) { |
@@ -292,13 +293,12 @@ |
Label not_js_object; |
__ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); |
__ j(below, ¬_js_object, Label::kNear); |
- __ Set(tos_, Immediate(1)); |
+ // argument contains the correct return value already. |
+ if (!tos_.is(argument)) { |
+ __ Set(tos_, Immediate(1)); |
+ } |
__ ret(1 * kPointerSize); |
__ bind(¬_js_object); |
- } else if (types_.Contains(INTERNAL_OBJECT)) { |
- // We've seen a spec object for the first time -> patch. |
- __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); |
- __ j(above_equal, &patch, Label::kNear); |
} |
if (types_.Contains(STRING)) { |
@@ -309,10 +309,6 @@ |
__ mov(tos_, FieldOperand(argument, String::kLengthOffset)); |
__ ret(1 * kPointerSize); // the string length is OK as the return value |
__ bind(¬_string); |
- } else if (types_.Contains(INTERNAL_OBJECT)) { |
- // We've seen a string for the first time -> patch |
- __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); |
- __ j(below, &patch, Label::kNear); |
} |
if (types_.Contains(HEAP_NUMBER)) { |
@@ -324,50 +320,42 @@ |
__ fld_d(FieldOperand(argument, HeapNumber::kValueOffset)); |
__ FCmp(); |
__ j(zero, &false_result, Label::kNear); |
- __ Set(tos_, Immediate(1)); |
+ // argument contains the correct return value already. |
+ if (!tos_.is(argument)) { |
+ __ Set(tos_, Immediate(1)); |
+ } |
__ ret(1 * kPointerSize); |
__ bind(&false_result); |
__ Set(tos_, Immediate(0)); |
__ ret(1 * kPointerSize); |
__ bind(¬_heap_number); |
- } else if (types_.Contains(INTERNAL_OBJECT)) { |
- // We've seen a heap number for the first time -> patch |
- __ cmp(map, factory->heap_number_map()); |
- __ j(equal, &patch, Label::kNear); |
} |
- if (types_.Contains(INTERNAL_OBJECT)) { |
- // internal objects -> true |
- __ Set(tos_, Immediate(1)); |
- __ ret(1 * kPointerSize); |
- } |
- |
- if (!types_.IsAll()) { |
- __ bind(&patch); |
- GenerateTypeTransition(masm); |
- } |
+ __ bind(&patch); |
+ GenerateTypeTransition(masm); |
} |
void ToBooleanStub::CheckOddball(MacroAssembler* masm, |
Type type, |
Heap::RootListIndex value, |
- bool result, |
- Label* patch) { |
+ bool result) { |
const Register argument = eax; |
if (types_.Contains(type)) { |
// If we see an expected oddball, return its ToBoolean value tos_. |
Label different_value; |
__ CompareRoot(argument, value); |
__ j(not_equal, &different_value, Label::kNear); |
- __ Set(tos_, Immediate(result ? 1 : 0)); |
+ if (!result) { |
+ // If we have to return zero, there is no way around clearing tos_. |
+ __ Set(tos_, Immediate(0)); |
+ } else if (!tos_.is(argument)) { |
+ // If we have to return non-zero, we can re-use the argument if it is the |
+ // same register as the result, because we never see Smi-zero here. |
+ __ Set(tos_, Immediate(1)); |
+ } |
__ ret(1 * kPointerSize); |
__ bind(&different_value); |
- } else if (types_.Contains(INTERNAL_OBJECT)) { |
- // If we see an unexpected oddball and handle internal objects, we must |
- // patch because the code for internal objects doesn't handle it explictly. |
- __ CompareRoot(argument, value); |
- __ j(equal, patch); |
} |
} |