diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index 6e368de036..f82c8b8603 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -2618,39 +2618,27 @@ void LCodeGen::EmitClassOfTest(Label* is_true, __ JumpIfSmi(input, is_false); + STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); + __ CompareObjectType(input, temp, temp2, FIRST_JS_RECEIVER_TYPE); + __ b(lt, is_false); + + // Objects with [[Call]] have class 'Function'. + __ ldrb(temp2, FieldMemOperand(temp, Map::kBitFieldOffset)); + __ tst(temp2, Operand(1 << Map::kIsCallable)); if (String::Equals(isolate()->factory()->Function_string(), class_name)) { - // 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); - __ CompareObjectType(input, temp, temp2, FIRST_SPEC_OBJECT_TYPE); - __ b(lt, is_false); - __ b(eq, is_true); - __ cmp(temp2, Operand(LAST_SPEC_OBJECT_TYPE)); - __ b(eq, is_true); + __ b(ne, is_true); } else { - // 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. - __ ldr(temp, FieldMemOperand(input, HeapObject::kMapOffset)); - __ ldrb(temp2, FieldMemOperand(temp, Map::kInstanceTypeOffset)); - __ sub(temp2, temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); - __ cmp(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE - - FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); - __ b(gt, is_false); + __ b(ne, is_false); } - // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range. + // Now we are in the FIRST-LAST_JS_RECEIVER_TYPE range. // Check if the constructor in the map is a function. Register instance_type = ip; __ GetMapConstructor(temp, temp, temp2, instance_type); // Objects with a non-function constructor have class 'Object'. __ cmp(instance_type, Operand(JS_FUNCTION_TYPE)); - if (class_name->IsOneByteEqualTo(STATIC_CHAR_VECTOR("Object"))) { + if (String::Equals(isolate()->factory()->Object_string(), class_name)) { __ b(ne, is_true); } else { __ b(ne, is_false); diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc index 3572e1cd30..057a59cf52 100644 --- a/src/arm/macro-assembler-arm.cc +++ b/src/arm/macro-assembler-arm.cc @@ -1390,26 +1390,6 @@ void MacroAssembler::InvokeFunction(Handle function, } -void MacroAssembler::IsObjectJSObjectType(Register heap_object, - Register map, - Register scratch, - Label* fail) { - ldr(map, FieldMemOperand(heap_object, HeapObject::kMapOffset)); - IsInstanceJSObjectType(map, scratch, fail); -} - - -void MacroAssembler::IsInstanceJSObjectType(Register map, - Register scratch, - Label* fail) { - ldrb(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); - cmp(scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); - b(lt, fail); - cmp(scratch, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); - b(gt, fail); -} - - void MacroAssembler::IsObjectJSStringType(Register object, Register scratch, Label* fail) { diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h index 702cedb57a..d418785740 100644 --- a/src/arm/macro-assembler-arm.h +++ b/src/arm/macro-assembler-arm.h @@ -662,15 +662,6 @@ class MacroAssembler: public Assembler { InvokeFlag flag, const CallWrapper& call_wrapper); - void IsObjectJSObjectType(Register heap_object, - Register map, - Register scratch, - Label* fail); - - void IsInstanceJSObjectType(Register map, - Register scratch, - Label* fail); - void IsObjectJSStringType(Register object, Register scratch, Label* fail); diff --git a/src/arm64/lithium-codegen-arm64.cc b/src/arm64/lithium-codegen-arm64.cc index 529352d77e..fc270c4618 100644 --- a/src/arm64/lithium-codegen-arm64.cc +++ b/src/arm64/lithium-codegen-arm64.cc @@ -2355,27 +2355,21 @@ void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { __ JumpIfSmi(input, false_label); Register map = scratch2; - if (String::Equals(isolate()->factory()->Function_string(), class_name)) { - // 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); + STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); + __ CompareObjectType(input, map, scratch1, FIRST_JS_RECEIVER_TYPE); + __ B(lt, false_label); - // We expect CompareObjectType to load the object instance type in scratch1. - __ CompareObjectType(input, map, scratch1, FIRST_SPEC_OBJECT_TYPE); - __ B(lt, false_label); - __ B(eq, true_label); - __ Cmp(scratch1, LAST_SPEC_OBJECT_TYPE); - __ B(eq, true_label); + // Objects with [[Call]] have class 'Function'. + Register bit_field = scratch1; + __ Ldrb(bit_field, FieldMemOperand(map, Map::kBitFieldOffset)); + __ Tst(bit_field, 1 << Map::kIsCallable); + if (String::Equals(isolate()->factory()->Function_string(), class_name)) { + __ B(ne, true_label); } else { - __ IsObjectJSObjectType(input, map, scratch1, false_label); + __ B(ne, false_label); } - // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range. + // Now we are in the FIRST-LAST_JS_RECEIVER_TYPE range. // Check if the constructor in the map is a function. { UseScratchRegisterScope temps(masm()); diff --git a/src/arm64/macro-assembler-arm64-inl.h b/src/arm64/macro-assembler-arm64-inl.h index 445513bf5a..a915058d31 100644 --- a/src/arm64/macro-assembler-arm64-inl.h +++ b/src/arm64/macro-assembler-arm64-inl.h @@ -1434,32 +1434,6 @@ void MacroAssembler::IsObjectNameType(Register object, } -void MacroAssembler::IsObjectJSObjectType(Register heap_object, - Register map, - Register scratch, - Label* fail) { - Ldr(map, FieldMemOperand(heap_object, HeapObject::kMapOffset)); - IsInstanceJSObjectType(map, scratch, fail); -} - - -void MacroAssembler::IsInstanceJSObjectType(Register map, - Register scratch, - Label* fail) { - Ldrb(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); - // If cmp result is lt, the following ccmp will clear all flags. - // Z == 0, N == V implies gt condition. - Cmp(scratch, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); - Ccmp(scratch, LAST_NONCALLABLE_SPEC_OBJECT_TYPE, NoFlag, ge); - - // If we didn't get a valid label object just fall through and leave the - // flags updated. - if (fail != NULL) { - B(gt, fail); - } -} - - void MacroAssembler::IsObjectJSStringType(Register object, Register type, Label* not_string, diff --git a/src/arm64/macro-assembler-arm64.h b/src/arm64/macro-assembler-arm64.h index a050a74fcb..9e81efe1b1 100644 --- a/src/arm64/macro-assembler-arm64.h +++ b/src/arm64/macro-assembler-arm64.h @@ -1490,20 +1490,6 @@ class MacroAssembler : public Assembler { // Fall-through if the object was a string and jump on fail otherwise. inline void IsObjectNameType(Register object, Register type, Label* fail); - inline void IsObjectJSObjectType(Register heap_object, - Register map, - Register scratch, - Label* fail); - - // Check the instance type in the given map to see if it corresponds to a - // JS object type. Jump to the fail label if this is not the case and fall - // through otherwise. However if fail label is NULL, no branch will be - // performed and the flag will be updated. You can test the flag for "le" - // condition to test if it is a valid JS object type. - inline void IsInstanceJSObjectType(Register map, - Register scratch, - Label* fail); - // Load and check the instance type of an object for being a string. // Loads the type into the second argument register. // The object and type arguments can be the same register; in that case it diff --git a/src/full-codegen/arm/full-codegen-arm.cc b/src/full-codegen/arm/full-codegen-arm.cc index 7d8181774c..988e9a7385 100644 --- a/src/full-codegen/arm/full-codegen-arm.cc +++ b/src/full-codegen/arm/full-codegen-arm.cc @@ -3663,7 +3663,7 @@ void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { ZoneList* args = expr->arguments(); - DCHECK(args->length() == 1); + DCHECK_EQ(1, args->length()); Label done, null, function, non_function_constructor; VisitForAccumulatorValue(args->at(0)); @@ -3671,24 +3671,17 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { // If the object is a smi, we return null. __ JumpIfSmi(r0, &null); - // Check that the object is a JS object but take special care of JS - // functions to make sure they have 'Function' as their class. - // Assume that there are only two callable types, and one of them is at - // either end of the type range for JS object types. Saves extra comparisons. - STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); - __ CompareObjectType(r0, r0, r1, FIRST_SPEC_OBJECT_TYPE); - // Map is now in r0. + // If the object is not a receiver, we return null. + STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); + __ CompareObjectType(r0, r0, r1, FIRST_JS_RECEIVER_TYPE); __ b(lt, &null); - STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == - FIRST_SPEC_OBJECT_TYPE + 1); - __ b(eq, &function); - __ cmp(r1, Operand(LAST_SPEC_OBJECT_TYPE)); - STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == - LAST_SPEC_OBJECT_TYPE - 1); - __ b(eq, &function); - // Assume that there is no larger type. - STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1); + // According to ES5 section 15 Standard Built-in ECMAScript Objects, the + // [[Class]] of builtin objects is "Function" if a [[Call]] internal + // method is present. + __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); + __ tst(r1, Operand(1 << Map::kIsCallable)); + __ b(ne, &function); // Check if the constructor in the map is a JS function. Register instance_type = r2; diff --git a/src/full-codegen/arm64/full-codegen-arm64.cc b/src/full-codegen/arm64/full-codegen-arm64.cc index 8b32fc9dca..cf238e5947 100644 --- a/src/full-codegen/arm64/full-codegen-arm64.cc +++ b/src/full-codegen/arm64/full-codegen-arm64.cc @@ -3390,7 +3390,7 @@ void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { ASM_LOCATION("FullCodeGenerator::EmitClassOf"); ZoneList* args = expr->arguments(); - DCHECK(args->length() == 1); + DCHECK_EQ(1, args->length()); Label done, null, function, non_function_constructor; VisitForAccumulatorValue(args->at(0)); @@ -3398,25 +3398,19 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { // If the object is a smi, we return null. __ JumpIfSmi(x0, &null); - // Check that the object is a JS object but take special care of JS - // functions to make sure they have 'Function' as their class. - // Assume that there are only two callable types, and one of them is at - // either end of the type range for JS object types. Saves extra comparisons. - STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); - __ CompareObjectType(x0, x10, x11, FIRST_SPEC_OBJECT_TYPE); + // If the object is not a receiver, we return null. + STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); + __ CompareObjectType(x0, x10, x11, FIRST_JS_RECEIVER_TYPE); // x10: object's map. // x11: object's type. __ B(lt, &null); - STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == - FIRST_SPEC_OBJECT_TYPE + 1); - __ B(eq, &function); - __ Cmp(x11, LAST_SPEC_OBJECT_TYPE); - STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == - LAST_SPEC_OBJECT_TYPE - 1); - __ B(eq, &function); - // Assume that there is no larger type. - STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1); + // According to ES5 section 15 Standard Built-in ECMAScript Objects, the + // [[Class]] of builtin objects is "Function" if a [[Call]] internal + // method is present. + __ Ldrb(x11, FieldMemOperand(x10, Map::kBitFieldOffset)); + __ Tst(x11, 1 << Map::kIsCallable); + __ B(ne, &function); // Check if the constructor in the map is a JS function. Register instance_type = x14; diff --git a/src/full-codegen/ia32/full-codegen-ia32.cc b/src/full-codegen/ia32/full-codegen-ia32.cc index df7ae9c5ec..6df2ce2778 100644 --- a/src/full-codegen/ia32/full-codegen-ia32.cc +++ b/src/full-codegen/ia32/full-codegen-ia32.cc @@ -3565,57 +3565,49 @@ void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { ZoneList* args = expr->arguments(); - DCHECK(args->length() == 1); - Label done, null, function, non_function_constructor; + DCHECK_EQ(1, args->length()); + Label done, null, function, function_constructor; VisitForAccumulatorValue(args->at(0)); // If the object is a smi, we return null. - __ JumpIfSmi(eax, &null); + __ JumpIfSmi(eax, &null, Label::kNear); - // Check that the object is a JS object but take special care of JS - // functions to make sure they have 'Function' as their class. - // Assume that there are only two callable types, and one of them is at - // either end of the type range for JS object types. Saves extra comparisons. - STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); - __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, eax); - // Map is now in eax. - __ j(below, &null); - STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == - FIRST_SPEC_OBJECT_TYPE + 1); - __ j(equal, &function); + // If the object is not a receiver, we return null. + STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); + __ CmpObjectType(eax, FIRST_JS_RECEIVER_TYPE, eax); + __ j(below, &null, Label::kNear); - __ CmpInstanceType(eax, LAST_SPEC_OBJECT_TYPE); - STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == - LAST_SPEC_OBJECT_TYPE - 1); - __ j(equal, &function); - // Assume that there is no larger type. - STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1); + // According to ES5 section 15 Standard Built-in ECMAScript Objects, the + // [[Class]] of builtin objects is "Function" if a [[Call]] internal + // method is present. + __ test_b(FieldOperand(eax, Map::kBitFieldOffset), 1 << Map::kIsCallable); + __ j(not_zero, &function, Label::kNear); // Check if the constructor in the map is a JS function. __ GetMapConstructor(eax, eax, ebx); __ CmpInstanceType(ebx, JS_FUNCTION_TYPE); - __ j(not_equal, &non_function_constructor); + __ j(equal, &function_constructor, Label::kNear); + // Objects with a non-function constructor have class 'Object'. + __ LoadRoot(eax, Heap::kObject_stringRootIndex); + __ jmp(&done, Label::kNear); + + // Non-JS objects have class null. + __ bind(&null); + __ LoadRoot(eax, Heap::kNullValueRootIndex); + __ jmp(&done, Label::kNear); + + // Functions have class 'Function'. + __ bind(&function); + __ LoadRoot(eax, Heap::kFunction_stringRootIndex); + __ jmp(&done, Label::kNear); + + __ bind(&function_constructor); // eax now contains the constructor function. Grab the // instance class name from there. __ mov(eax, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset)); __ mov(eax, FieldOperand(eax, SharedFunctionInfo::kInstanceClassNameOffset)); - __ jmp(&done); - - // Functions have class 'Function'. - __ bind(&function); - __ mov(eax, isolate()->factory()->Function_string()); - __ jmp(&done); - - // Objects with a non-function constructor have class 'Object'. - __ bind(&non_function_constructor); - __ mov(eax, isolate()->factory()->Object_string()); - __ jmp(&done); - - // Non-JS objects have class null. - __ bind(&null); - __ mov(eax, isolate()->factory()->null_value()); // All done. __ bind(&done); diff --git a/src/full-codegen/mips/full-codegen-mips.cc b/src/full-codegen/mips/full-codegen-mips.cc index e985f440c7..215d7ae032 100644 --- a/src/full-codegen/mips/full-codegen-mips.cc +++ b/src/full-codegen/mips/full-codegen-mips.cc @@ -3663,7 +3663,7 @@ void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { ZoneList* args = expr->arguments(); - DCHECK(args->length() == 1); + DCHECK_EQ(1, args->length()); Label done, null, function, non_function_constructor; VisitForAccumulatorValue(args->at(0)); @@ -3671,23 +3671,17 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { // If the object is a smi, we return null. __ JumpIfSmi(v0, &null); - // Check that the object is a JS object but take special care of JS - // functions to make sure they have 'Function' as their class. - // Assume that there are only two callable types, and one of them is at - // either end of the type range for JS object types. Saves extra comparisons. - STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); + // If the object is not a receiver, we return null. + STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); __ GetObjectType(v0, v0, a1); // Map is now in v0. - __ Branch(&null, lt, a1, Operand(FIRST_SPEC_OBJECT_TYPE)); + __ Branch(&null, lt, a1, Operand(FIRST_JS_RECEIVER_TYPE)); - STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == - FIRST_SPEC_OBJECT_TYPE + 1); - __ Branch(&function, eq, a1, Operand(FIRST_SPEC_OBJECT_TYPE)); - - STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == - LAST_SPEC_OBJECT_TYPE - 1); - __ Branch(&function, eq, a1, Operand(LAST_SPEC_OBJECT_TYPE)); - // Assume that there is no larger type. - STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1); + // According to ES5 section 15 Standard Built-in ECMAScript Objects, the + // [[Class]] of builtin objects is "Function" if a [[Call]] internal + // method is present. + __ lbu(a1, FieldMemOperand(v0, Map::kBitFieldOffset)); + __ And(a1, a1, Operand(1 << Map::kIsCallable)); + __ Branch(&function, ne, a1, Operand(zero_reg)); // Check if the constructor in the map is a JS function. Register instance_type = a2; diff --git a/src/full-codegen/mips64/full-codegen-mips64.cc b/src/full-codegen/mips64/full-codegen-mips64.cc index bd1fea27d5..fcaa99a0dd 100644 --- a/src/full-codegen/mips64/full-codegen-mips64.cc +++ b/src/full-codegen/mips64/full-codegen-mips64.cc @@ -3674,23 +3674,17 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { // If the object is a smi, we return null. __ JumpIfSmi(v0, &null); - // Check that the object is a JS object but take special care of JS - // functions to make sure they have 'Function' as their class. - // Assume that there are only two callable types, and one of them is at - // either end of the type range for JS object types. Saves extra comparisons. - STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); + // If the object is not a receiver, we return null. + STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); __ GetObjectType(v0, v0, a1); // Map is now in v0. - __ Branch(&null, lt, a1, Operand(FIRST_SPEC_OBJECT_TYPE)); + __ Branch(&null, lt, a1, Operand(FIRST_JS_RECEIVER_TYPE)); - STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == - FIRST_SPEC_OBJECT_TYPE + 1); - __ Branch(&function, eq, a1, Operand(FIRST_SPEC_OBJECT_TYPE)); - - STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == - LAST_SPEC_OBJECT_TYPE - 1); - __ Branch(&function, eq, a1, Operand(LAST_SPEC_OBJECT_TYPE)); - // Assume that there is no larger type. - STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1); + // According to ES5 section 15 Standard Built-in ECMAScript Objects, the + // [[Class]] of builtin objects is "Function" if a [[Call]] internal + // method is present. + __ lbu(a1, FieldMemOperand(v0, Map::kBitFieldOffset)); + __ And(a1, a1, Operand(1 << Map::kIsCallable)); + __ Branch(&function, ne, a1, Operand(zero_reg)); // Check if the constructor in the map is a JS function. Register instance_type = a2; diff --git a/src/full-codegen/x64/full-codegen-x64.cc b/src/full-codegen/x64/full-codegen-x64.cc index 2010590a04..a7710072ba 100644 --- a/src/full-codegen/x64/full-codegen-x64.cc +++ b/src/full-codegen/x64/full-codegen-x64.cc @@ -3548,57 +3548,50 @@ void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { ZoneList* args = expr->arguments(); - DCHECK(args->length() == 1); - Label done, null, function, non_function_constructor; + DCHECK_EQ(1, args->length()); + Label done, null, function, function_constructor; VisitForAccumulatorValue(args->at(0)); // If the object is a smi, we return null. - __ JumpIfSmi(rax, &null); + __ JumpIfSmi(rax, &null, Label::kNear); - // Check that the object is a JS object but take special care of JS - // functions to make sure they have 'Function' as their class. - // Assume that there are only two callable types, and one of them is at - // either end of the type range for JS object types. Saves extra comparisons. - STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); - __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rax); - // Map is now in rax. - __ j(below, &null); - STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == - FIRST_SPEC_OBJECT_TYPE + 1); - __ j(equal, &function); + // If the object is not a receiver, we return null. + STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); + __ CmpObjectType(rax, FIRST_JS_RECEIVER_TYPE, rax); + __ j(below, &null, Label::kNear); - __ CmpInstanceType(rax, LAST_SPEC_OBJECT_TYPE); - STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == - LAST_SPEC_OBJECT_TYPE - 1); - __ j(equal, &function); - // Assume that there is no larger type. - STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1); + // According to ES5 section 15 Standard Built-in ECMAScript Objects, the + // [[Class]] of builtin objects is "Function" if a [[Call]] internal + // method is present. + __ testb(FieldOperand(rax, Map::kBitFieldOffset), + Immediate(1 << Map::kIsCallable)); + __ j(not_zero, &function, Label::kNear); // Check if the constructor in the map is a JS function. __ GetMapConstructor(rax, rax, rbx); __ CmpInstanceType(rbx, JS_FUNCTION_TYPE); - __ j(not_equal, &non_function_constructor); - - // rax now contains the constructor function. Grab the - // instance class name from there. - __ movp(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset)); - __ movp(rax, FieldOperand(rax, SharedFunctionInfo::kInstanceClassNameOffset)); - __ jmp(&done); - - // Functions have class 'Function'. - __ bind(&function); - __ Move(rax, isolate()->factory()->Function_string()); - __ jmp(&done); + __ j(equal, &function_constructor, Label::kNear); // Objects with a non-function constructor have class 'Object'. - __ bind(&non_function_constructor); - __ Move(rax, isolate()->factory()->Object_string()); - __ jmp(&done); + __ LoadRoot(rax, Heap::kObject_stringRootIndex); + __ jmp(&done, Label::kNear); // Non-JS objects have class null. __ bind(&null); __ LoadRoot(rax, Heap::kNullValueRootIndex); + __ jmp(&done, Label::kNear); + + // Functions have class 'Function'. + __ bind(&function); + __ LoadRoot(rax, Heap::kFunction_stringRootIndex); + __ jmp(&done, Label::kNear); + + __ bind(&function_constructor); + // rax now contains the constructor function. Grab the + // instance class name from there. + __ movp(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset)); + __ movp(rax, FieldOperand(rax, SharedFunctionInfo::kInstanceClassNameOffset)); // All done. __ bind(&done); diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index 7f44b9e77e..aa0ab58ff9 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -2521,32 +2521,19 @@ void LCodeGen::EmitClassOfTest(Label* is_true, DCHECK(!temp.is(temp2)); __ JumpIfSmi(input, is_false); + STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); + __ CmpObjectType(input, FIRST_JS_RECEIVER_TYPE, temp); + __ j(below, is_false); + + // Objects with [[Call]] have class 'Function'. + __ test_b(FieldOperand(temp, Map::kBitFieldOffset), 1 << Map::kIsCallable); if (String::Equals(isolate()->factory()->Function_string(), class_name)) { - // 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); + __ j(not_zero, is_true); } else { - // 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)); - __ movzx_b(temp2, FieldOperand(temp, Map::kInstanceTypeOffset)); - __ sub(Operand(temp2), Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); - __ cmp(Operand(temp2), Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE - - FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); - __ j(above, is_false); + __ j(not_zero, is_false); } - // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range. + // Now we are in the FIRST-LAST_JS_RECEIVER_TYPE range. // Check if the constructor in the map is a function. __ GetMapConstructor(temp, temp, temp2); // Objects with a non-function constructor have class 'Object'. diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc index a6b130b5a2..b05384d052 100644 --- a/src/ia32/macro-assembler-ia32.cc +++ b/src/ia32/macro-assembler-ia32.cc @@ -752,26 +752,6 @@ Condition MacroAssembler::IsObjectNameType(Register heap_object, } -void MacroAssembler::IsObjectJSObjectType(Register heap_object, - Register map, - Register scratch, - Label* fail) { - mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); - IsInstanceJSObjectType(map, scratch, fail); -} - - -void MacroAssembler::IsInstanceJSObjectType(Register map, - Register scratch, - Label* fail) { - movzx_b(scratch, FieldOperand(map, Map::kInstanceTypeOffset)); - sub(scratch, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); - cmp(scratch, - LAST_NONCALLABLE_SPEC_OBJECT_TYPE - FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); - j(above, fail); -} - - void MacroAssembler::FCmp() { fucomip(); fstp(0); @@ -1784,9 +1764,9 @@ void MacroAssembler::GetMapConstructor(Register result, Register map, Label done, loop; mov(result, FieldOperand(map, Map::kConstructorOrBackPointerOffset)); bind(&loop); - JumpIfSmi(result, &done); + JumpIfSmi(result, &done, Label::kNear); CmpObjectType(result, MAP_TYPE, temp); - j(not_equal, &done); + j(not_equal, &done, Label::kNear); mov(result, FieldOperand(result, Map::kConstructorOrBackPointerOffset)); jmp(&loop); bind(&done); diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h index 8f7cae92b5..dd90650f6d 100644 --- a/src/ia32/macro-assembler-ia32.h +++ b/src/ia32/macro-assembler-ia32.h @@ -452,18 +452,6 @@ class MacroAssembler: public Assembler { Register map, Register instance_type); - // Check if a heap object's type is in the JSObject range, not including - // JSFunction. The object's map will be loaded in the map register. - // Any or all of the three registers may be the same. - // The contents of the scratch register will always be overwritten. - void IsObjectJSObjectType(Register heap_object, - Register map, - Register scratch, - Label* fail); - - // The contents of the scratch register will be overwritten. - void IsInstanceJSObjectType(Register map, Register scratch, Label* fail); - // FCmp is similar to integer cmp, but requires unsigned // jcc instructions (je, ja, jae, jb, jbe, je, and jz). void FCmp(); diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc index 5586ed1ab2..c98da62947 100644 --- a/src/mips/lithium-codegen-mips.cc +++ b/src/mips/lithium-codegen-mips.cc @@ -2544,30 +2544,20 @@ void LCodeGen::EmitClassOfTest(Label* is_true, __ JumpIfSmi(input, is_false); - if (String::Equals(isolate()->factory()->Function_string(), class_name)) { - // 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); + STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); + __ GetObjectType(input, temp, temp2); + __ Branch(is_false, lt, temp2, Operand(FIRST_JS_RECEIVER_TYPE)); - __ GetObjectType(input, temp, temp2); - __ Branch(is_false, lt, temp2, Operand(FIRST_SPEC_OBJECT_TYPE)); - __ Branch(is_true, eq, temp2, Operand(FIRST_SPEC_OBJECT_TYPE)); - __ Branch(is_true, eq, temp2, Operand(LAST_SPEC_OBJECT_TYPE)); + // Objects with [[Call]] have class 'Function'. + __ lbu(temp2, FieldMemOperand(temp, Map::kBitFieldOffset)); + __ And(temp2, temp2, Operand(1 << Map::kIsCallable)); + if (String::Equals(isolate()->factory()->Function_string(), class_name)) { + __ Branch(is_true, ne, temp2, Operand(zero_reg)); } else { - // 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. - __ GetObjectType(input, temp, temp2); - __ Subu(temp2, temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); - __ Branch(is_false, gt, temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE - - FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); + __ Branch(is_false, ne, temp2, Operand(zero_reg)); } - // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range. + // Now we are in the FIRST-LAST_JS_RECEIVER_TYPE range. // Check if the constructor in the map is a function. Register instance_type = scratch1(); DCHECK(!instance_type.is(temp)); diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc index 8a75ae934f..9ba814ae2f 100644 --- a/src/mips/macro-assembler-mips.cc +++ b/src/mips/macro-assembler-mips.cc @@ -4214,24 +4214,6 @@ void MacroAssembler::InvokeFunction(Handle function, } -void MacroAssembler::IsObjectJSObjectType(Register heap_object, - Register map, - Register scratch, - Label* fail) { - lw(map, FieldMemOperand(heap_object, HeapObject::kMapOffset)); - IsInstanceJSObjectType(map, scratch, fail); -} - - -void MacroAssembler::IsInstanceJSObjectType(Register map, - Register scratch, - Label* fail) { - lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); - Branch(fail, lt, scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); - Branch(fail, gt, scratch, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); -} - - void MacroAssembler::IsObjectJSStringType(Register object, Register scratch, Label* fail) { diff --git a/src/mips/macro-assembler-mips.h b/src/mips/macro-assembler-mips.h index a126e55ac6..5e1d2c6253 100644 --- a/src/mips/macro-assembler-mips.h +++ b/src/mips/macro-assembler-mips.h @@ -977,16 +977,6 @@ class MacroAssembler: public Assembler { InvokeFlag flag, const CallWrapper& call_wrapper); - - void IsObjectJSObjectType(Register heap_object, - Register map, - Register scratch, - Label* fail); - - void IsInstanceJSObjectType(Register map, - Register scratch, - Label* fail); - void IsObjectJSStringType(Register object, Register scratch, Label* fail); diff --git a/src/mips64/lithium-codegen-mips64.cc b/src/mips64/lithium-codegen-mips64.cc index a612681c5b..80befa531d 100644 --- a/src/mips64/lithium-codegen-mips64.cc +++ b/src/mips64/lithium-codegen-mips64.cc @@ -2648,30 +2648,20 @@ void LCodeGen::EmitClassOfTest(Label* is_true, __ JumpIfSmi(input, is_false); - if (String::Equals(isolate()->factory()->Function_string(), class_name)) { - // 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); + STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); + __ GetObjectType(input, temp, temp2); + __ Branch(is_false, lt, temp2, Operand(FIRST_JS_RECEIVER_TYPE)); - __ GetObjectType(input, temp, temp2); - __ Branch(is_false, lt, temp2, Operand(FIRST_SPEC_OBJECT_TYPE)); - __ Branch(is_true, eq, temp2, Operand(FIRST_SPEC_OBJECT_TYPE)); - __ Branch(is_true, eq, temp2, Operand(LAST_SPEC_OBJECT_TYPE)); + // Objects with [[Call]] have class 'Function'. + __ lbu(temp2, FieldMemOperand(temp, Map::kBitFieldOffset)); + __ And(temp2, temp2, Operand(1 << Map::kIsCallable)); + if (String::Equals(isolate()->factory()->Function_string(), class_name)) { + __ Branch(is_true, ne, temp2, Operand(zero_reg)); } else { - // 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. - __ GetObjectType(input, temp, temp2); - __ Dsubu(temp2, temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); - __ Branch(is_false, gt, temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE - - FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); + __ Branch(is_false, ne, temp2, Operand(zero_reg)); } - // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range. + // Now we are in the FIRST-LAST_JS_RECEIVER_TYPE range. // Check if the constructor in the map is a function. Register instance_type = scratch1(); DCHECK(!instance_type.is(temp)); diff --git a/src/mips64/macro-assembler-mips64.cc b/src/mips64/macro-assembler-mips64.cc index 1e9aebd9a5..a379d847ae 100644 --- a/src/mips64/macro-assembler-mips64.cc +++ b/src/mips64/macro-assembler-mips64.cc @@ -4217,24 +4217,6 @@ void MacroAssembler::InvokeFunction(Handle function, } -void MacroAssembler::IsObjectJSObjectType(Register heap_object, - Register map, - Register scratch, - Label* fail) { - ld(map, FieldMemOperand(heap_object, HeapObject::kMapOffset)); - IsInstanceJSObjectType(map, scratch, fail); -} - - -void MacroAssembler::IsInstanceJSObjectType(Register map, - Register scratch, - Label* fail) { - lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); - Branch(fail, lt, scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); - Branch(fail, gt, scratch, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); -} - - void MacroAssembler::IsObjectJSStringType(Register object, Register scratch, Label* fail) { diff --git a/src/mips64/macro-assembler-mips64.h b/src/mips64/macro-assembler-mips64.h index 7691ba4d89..17e0857ba5 100644 --- a/src/mips64/macro-assembler-mips64.h +++ b/src/mips64/macro-assembler-mips64.h @@ -1008,15 +1008,6 @@ class MacroAssembler: public Assembler { const CallWrapper& call_wrapper); - void IsObjectJSObjectType(Register heap_object, - Register map, - Register scratch, - Label* fail); - - void IsInstanceJSObjectType(Register map, - Register scratch, - Label* fail); - void IsObjectJSStringType(Register object, Register scratch, Label* fail); diff --git a/src/objects.cc b/src/objects.cc index c0539c493f..60f1e5bdc9 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -58,9 +58,9 @@ Handle Object::OptimalType(Isolate* isolate, if (representation.IsHeapObject() && IsHeapObject()) { // We can track only JavaScript objects with stable maps. Handle map(HeapObject::cast(this)->map(), isolate); - if (map->is_stable() && - map->instance_type() >= FIRST_NONCALLABLE_SPEC_OBJECT_TYPE && - map->instance_type() <= LAST_NONCALLABLE_SPEC_OBJECT_TYPE) { + if (map->is_stable() && !map->is_callable() && + map->instance_type() >= FIRST_JS_RECEIVER_TYPE && + map->instance_type() <= LAST_JS_RECEIVER_TYPE) { return HeapType::Class(map, isolate); } } @@ -1650,7 +1650,10 @@ void Simd128Value::CopyBits(void* destination) const { String* JSReceiver::class_name() { - if (IsJSFunction() || IsJSFunctionProxy()) { + // According to ES5 section 15 Standard Built-in ECMAScript Objects, the + // [[Class]] of builtin objects is "Function" if a [[Call]] internal + // method is present. + if (IsCallable()) { return GetHeap()->Function_string(); } Object* maybe_constructor = map()->GetConstructor(); diff --git a/src/objects.h b/src/objects.h index 4ece658d38..a07ab50e3a 100644 --- a/src/objects.h +++ b/src/objects.h @@ -708,8 +708,7 @@ enum InstanceType { // All the following types are subtypes of JSReceiver, which corresponds to // objects in the JS sense. The first and the last type in this range are // the two forms of function. This organization enables using the same - // compares for checking the JS_RECEIVER/SPEC_OBJECT range and the - // NONCALLABLE_JS_OBJECT range. + // compares for checking the JS_RECEIVER/SPEC_OBJECT range. JS_FUNCTION_PROXY_TYPE, // FIRST_JS_RECEIVER_TYPE, FIRST_JS_PROXY_TYPE JS_PROXY_TYPE, // LAST_JS_PROXY_TYPE JS_VALUE_TYPE, // FIRST_JS_OBJECT_TYPE @@ -766,13 +765,7 @@ enum InstanceType { LAST_JS_PROXY_TYPE = JS_PROXY_TYPE, // Boundaries for testing whether the type is a JavaScript object. FIRST_SPEC_OBJECT_TYPE = FIRST_JS_RECEIVER_TYPE, - LAST_SPEC_OBJECT_TYPE = LAST_JS_RECEIVER_TYPE, - // Boundaries for testing the types for which typeof is "object". - FIRST_NONCALLABLE_SPEC_OBJECT_TYPE = JS_PROXY_TYPE, - LAST_NONCALLABLE_SPEC_OBJECT_TYPE = JS_REGEXP_TYPE, - // Note that the types for which typeof is "function" are not continuous. - // Define this so that we can put assertions on discrete checks. - NUM_OF_CALLABLE_SPEC_OBJECT_TYPES = 2 + LAST_SPEC_OBJECT_TYPE = LAST_JS_RECEIVER_TYPE }; STATIC_ASSERT(JS_OBJECT_TYPE == Internals::kJSObjectType); diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index 2505890974..322de11f5d 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -2572,32 +2572,20 @@ void LCodeGen::EmitClassOfTest(Label* is_true, __ JumpIfSmi(input, is_false); + STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); + __ CmpObjectType(input, FIRST_JS_RECEIVER_TYPE, temp); + __ j(below, is_false); + + // Objects with [[Call]] have class 'Function'. + __ testb(FieldOperand(temp, Map::kBitFieldOffset), + Immediate(1 << Map::kIsCallable)); if (String::Equals(isolate()->factory()->Function_string(), class_name)) { - // 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); + __ j(not_zero, is_true); } else { - // 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. - __ movp(temp, FieldOperand(input, HeapObject::kMapOffset)); - __ movzxbl(temp2, FieldOperand(temp, Map::kInstanceTypeOffset)); - __ subp(temp2, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); - __ cmpp(temp2, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE - - FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); - __ j(above, is_false); + __ j(not_zero, is_false); } - // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range. + // Now we are in the FIRST-LAST_JS_RECEIVER_TYPE range. // Check if the constructor in the map is a function. __ GetMapConstructor(temp, temp, kScratchRegister); diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc index 8898f7bae0..c67d955a89 100644 --- a/src/x64/macro-assembler-x64.cc +++ b/src/x64/macro-assembler-x64.cc @@ -3446,9 +3446,9 @@ void MacroAssembler::GetMapConstructor(Register result, Register map, Label done, loop; movp(result, FieldOperand(map, Map::kConstructorOrBackPointerOffset)); bind(&loop); - JumpIfSmi(result, &done); + JumpIfSmi(result, &done, Label::kNear); CmpObjectType(result, MAP_TYPE, temp); - j(not_equal, &done); + j(not_equal, &done, Label::kNear); movp(result, FieldOperand(result, Map::kConstructorOrBackPointerOffset)); jmp(&loop); bind(&done);