| Index: src/ia32/lithium-codegen-ia32.cc
 | 
| diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
 | 
| index 4e3ea98161dd278f177ecf10918fb3262bac2cb2..07709b608a304b6a5ed2bd19fbc0e5acf4203651 100644
 | 
| --- a/src/ia32/lithium-codegen-ia32.cc
 | 
| +++ b/src/ia32/lithium-codegen-ia32.cc
 | 
| @@ -1745,28 +1745,36 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
 | 
|    ASSERT(!input.is(temp));
 | 
|    ASSERT(!temp.is(temp2));  // But input and temp2 may be the same register.
 | 
|    __ JumpIfSmi(input, is_false);
 | 
| -  __ CmpObjectType(input, FIRST_SPEC_OBJECT_TYPE, temp);
 | 
| -  __ j(below, is_false);
 | 
|  
 | 
| -  // Map is now in temp.
 | 
| -  // Functions have class 'Function'.
 | 
| -  __ CmpInstanceType(temp, FIRST_CALLABLE_SPEC_OBJECT_TYPE);
 | 
|    if (class_name->IsEqualTo(CStrVector("Function"))) {
 | 
| -    __ j(above_equal, is_true);
 | 
| +    // Assuming the following assertions, we can use the same compares to test
 | 
| +    // for both being a function type and being in the object type range.
 | 
| +    STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
 | 
| +    STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
 | 
| +                  FIRST_SPEC_OBJECT_TYPE + 1);
 | 
| +    STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
 | 
| +                  LAST_SPEC_OBJECT_TYPE - 1);
 | 
| +    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
 | 
| +    __ CmpObjectType(input, FIRST_SPEC_OBJECT_TYPE, temp);
 | 
| +    __ j(below, is_false);
 | 
| +    __ j(equal, is_true);
 | 
| +    __ CmpInstanceType(temp, LAST_SPEC_OBJECT_TYPE);
 | 
| +    __ j(equal, is_true);
 | 
|    } else {
 | 
| -    __ j(above_equal, is_false);
 | 
| +    // Faster code path to avoid two compares: subtract lower bound from the
 | 
| +    // actual type and do a signed compare with the width of the type range.
 | 
| +    __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
 | 
| +    __ mov(temp2, FieldOperand(temp, Map::kInstanceTypeOffset));
 | 
| +    __ sub(Operand(temp2), Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
 | 
| +    __ cmpb(Operand(temp2),
 | 
| +            static_cast<int8_t>(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
 | 
| +                                FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
 | 
| +    __ j(above, is_false);
 | 
|    }
 | 
|  
 | 
| +  // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range.
 | 
|    // Check if the constructor in the map is a function.
 | 
|    __ mov(temp, FieldOperand(temp, Map::kConstructorOffset));
 | 
| -
 | 
| -  // As long as LAST_CALLABLE_SPEC_OBJECT_TYPE is the last instance type, and
 | 
| -  // FIRST_CALLABLE_SPEC_OBJECT_TYPE comes right after
 | 
| -  // LAST_NONCALLABLE_SPEC_OBJECT_TYPE, we can avoid checking for the latter.
 | 
| -  STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE);
 | 
| -  STATIC_ASSERT(FIRST_CALLABLE_SPEC_OBJECT_TYPE ==
 | 
| -                LAST_NONCALLABLE_SPEC_OBJECT_TYPE + 1);
 | 
| -
 | 
|    // Objects with a non-function constructor have class 'Object'.
 | 
|    __ CmpObjectType(temp, JS_FUNCTION_TYPE, temp2);
 | 
|    if (class_name->IsEqualTo(CStrVector("Object"))) {
 | 
| @@ -4188,10 +4196,12 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
 | 
|      final_branch_condition = not_zero;
 | 
|  
 | 
|    } else if (type_name->Equals(heap()->function_symbol())) {
 | 
| -    STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE);
 | 
| +    STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
 | 
|      __ JumpIfSmi(input, false_label);
 | 
| -    __ CmpObjectType(input, FIRST_CALLABLE_SPEC_OBJECT_TYPE, input);
 | 
| -    final_branch_condition = above_equal;
 | 
| +    __ CmpObjectType(input, JS_FUNCTION_TYPE, input);
 | 
| +    __ j(equal, true_label);
 | 
| +    __ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE);
 | 
| +    final_branch_condition = equal;
 | 
|  
 | 
|    } else if (type_name->Equals(heap()->object_symbol())) {
 | 
|      __ JumpIfSmi(input, false_label);
 | 
| 
 |