[runtime] Drop FIRST/LAST_NONCALLABLE_SPEC_OBJECT instance type range.

The FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range was accidentially used
in field type tracking, where we should check for JSReceiver instead
(there's no need to exclude JSProxy or JSFunction from tracking).

And the use in %_ClassOf was actually wrong and didn't match the C++
implementation in JSReceiver::class_name() anymore. Now it's consistent
again.

R=yangguo@chromium.org
BUG=chromium:535408
LOG=n

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

Cr-Commit-Position: refs/heads/master@{#32926}
This commit is contained in:
Benedikt Meurer 2015-12-17 07:19:10 +01:00
parent d0cfc9bfb8
commit aafc3e5484
18 changed files with 82 additions and 259 deletions

View File

@ -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_JS_RECEIVER_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,

View File

@ -1466,20 +1466,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

View File

@ -2538,36 +2538,20 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
__ JumpIfSmi(input, is_false);
__ CompareObjectType(input, temp, temp2, JS_FUNCTION_TYPE);
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(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
LAST_JS_RECEIVER_TYPE - 1);
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
__ CompareObjectType(input, temp, temp2, FIRST_JS_RECEIVER_TYPE);
__ b(lt, is_false);
__ cmp(temp2, Operand(LAST_JS_RECEIVER_TYPE));
__ b(eq, 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_JS_RECEIVER_TYPE));
__ cmp(temp2,
Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE - FIRST_JS_RECEIVER_TYPE));
__ b(gt, is_false);
__ b(eq, is_false);
}
// Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_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);

View File

@ -2259,24 +2259,13 @@ void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
__ JumpIfSmi(input, false_label);
Register map = scratch2;
__ CompareObjectType(input, map, scratch1, JS_FUNCTION_TYPE);
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(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
LAST_JS_RECEIVER_TYPE - 1);
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
// We expect CompareObjectType to load the object instance type in scratch1.
__ CompareObjectType(input, map, scratch1, FIRST_JS_RECEIVER_TYPE);
__ B(lt, false_label);
__ Cmp(scratch1, LAST_JS_RECEIVER_TYPE);
__ B(eq, true_label);
} else {
__ IsObjectJSObjectType(input, map, scratch1, false_label);
__ B(eq, false_label);
}
// Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range.
// Check if the constructor in the map is a function.
{
UseScratchRegisterScope temps(masm());

View File

@ -2441,26 +2441,11 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
DCHECK(!temp.is(temp2));
__ JumpIfSmi(input, is_false);
__ CmpObjectType(input, JS_FUNCTION_TYPE, temp);
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(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
LAST_JS_RECEIVER_TYPE - 1);
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
__ CmpObjectType(input, FIRST_JS_RECEIVER_TYPE, temp);
__ j(below, is_false);
__ CmpInstanceType(temp, LAST_JS_RECEIVER_TYPE);
__ j(equal, 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_JS_RECEIVER_TYPE));
__ cmp(Operand(temp2), Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
FIRST_JS_RECEIVER_TYPE));
__ j(above, is_false);
__ j(equal, is_false);
}
// Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range.

View File

@ -2448,28 +2448,13 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
DCHECK(!temp.is(temp2));
__ JumpIfSmi(input, is_false);
__ GetObjectType(input, temp, temp2);
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(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
LAST_JS_RECEIVER_TYPE - 1);
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
__ GetObjectType(input, temp, temp2);
__ Branch(is_false, lt, temp2, Operand(FIRST_JS_RECEIVER_TYPE));
__ Branch(is_true, eq, temp2, Operand(LAST_JS_RECEIVER_TYPE));
__ Branch(is_true, eq, temp2, Operand(JS_FUNCTION_TYPE));
} 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_JS_RECEIVER_TYPE));
__ Branch(is_false, gt, temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
FIRST_JS_RECEIVER_TYPE));
__ Branch(is_false, eq, temp2, Operand(JS_FUNCTION_TYPE));
}
// Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range.
// Check if the constructor in the map is a function.
Register instance_type = scratch1();
DCHECK(!instance_type.is(temp));

View File

@ -2570,24 +2570,11 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
__ JumpIfSmi(input, is_false);
__ GetObjectType(input, temp, temp2);
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(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
LAST_JS_RECEIVER_TYPE - 1);
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
__ GetObjectType(input, temp, temp2);
__ Branch(is_false, lt, temp2, Operand(FIRST_JS_RECEIVER_TYPE));
__ Branch(is_true, eq, temp2, Operand(LAST_JS_RECEIVER_TYPE));
__ Branch(is_true, eq, temp2, Operand(JS_FUNCTION_TYPE));
} 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_JS_RECEIVER_TYPE));
__ Branch(is_false, gt, temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
FIRST_JS_RECEIVER_TYPE));
__ Branch(is_false, eq, temp2, Operand(JS_FUNCTION_TYPE));
}
// Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range.

View File

@ -2498,29 +2498,13 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
__ JumpIfSmi(input, is_false);
__ CmpObjectType(input, JS_FUNCTION_TYPE, temp);
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(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
LAST_JS_RECEIVER_TYPE - 1);
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
__ CmpObjectType(input, FIRST_JS_RECEIVER_TYPE, temp);
__ j(below, is_false);
__ CmpInstanceType(temp, LAST_JS_RECEIVER_TYPE);
__ j(equal, 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_JS_RECEIVER_TYPE));
__ cmpp(temp2, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
FIRST_JS_RECEIVER_TYPE));
__ j(above, is_false);
__ j(equal, is_false);
}
// Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range.
// Check if the constructor in the map is a function.
__ GetMapConstructor(temp, temp, kScratchRegister);

View File

@ -3322,24 +3322,16 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
VisitForAccumulatorValue(args->at(0));
// If the object is a smi, we return null.
// If the object is not a JSReceiver, 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);
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
__ CompareObjectType(r0, r0, r1, FIRST_JS_RECEIVER_TYPE);
// Map is now in r0.
__ b(lt, &null);
__ cmp(r1, Operand(LAST_JS_RECEIVER_TYPE));
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
LAST_JS_RECEIVER_TYPE - 1);
// Return 'Function' for JSFunction objects.
__ cmp(r1, Operand(JS_FUNCTION_TYPE));
__ b(eq, &function);
// Assume that there is no larger type.
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1);
// Check if the constructor in the map is a JS function.
Register instance_type = r2;

View File

@ -3034,25 +3034,17 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
VisitForAccumulatorValue(args->at(0));
// If the object is a smi, we return null.
// If the object is not a JSReceiver, 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);
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);
__ Cmp(x11, LAST_JS_RECEIVER_TYPE);
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
LAST_JS_RECEIVER_TYPE - 1);
// Return 'Function' for JSFunction objects.
__ Cmp(x11, JS_FUNCTION_TYPE);
__ B(eq, &function);
// Assume that there is no larger type.
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1);
// Check if the constructor in the map is a JS function.
Register instance_type = x14;

View File

@ -3203,49 +3203,40 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
VisitForAccumulatorValue(args->at(0));
// If the object is a smi, we return null.
__ JumpIfSmi(eax, &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 JSReceiver, we return null.
__ JumpIfSmi(eax, &null, Label::kNear);
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
__ CmpObjectType(eax, FIRST_JS_RECEIVER_TYPE, eax);
// Map is now in eax.
__ j(below, &null);
__ j(below, &null, Label::kNear);
__ CmpInstanceType(eax, LAST_JS_RECEIVER_TYPE);
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
LAST_JS_RECEIVER_TYPE - 1);
__ j(equal, &function);
// Assume that there is no larger type.
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1);
// Return 'Function' for JSFunction objects.
__ CmpInstanceType(eax, JS_FUNCTION_TYPE);
__ j(equal, &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(not_equal, &non_function_constructor, Label::kNear);
// 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);
__ jmp(&done, Label::kNear);
// Non-JS objects have class null.
__ bind(&null);
__ mov(eax, isolate()->factory()->null_value());
__ jmp(&done, Label::kNear);
// Functions have class 'Function'.
__ bind(&function);
__ mov(eax, isolate()->factory()->Function_string());
__ jmp(&done, Label::kNear);
// Objects with a non-function constructor have class 'Object'.
__ bind(&non_function_constructor);
__ mov(eax, isolate()->factory()->Object_string());
// All done.
__ bind(&done);

View File

@ -3316,22 +3316,14 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
VisitForAccumulatorValue(args->at(0));
// If the object is a smi, we return null.
// If the object is not a JSReceiver, 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);
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
__ GetObjectType(v0, v0, a1); // Map is now in v0.
__ Branch(&null, lt, a1, Operand(FIRST_JS_RECEIVER_TYPE));
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
LAST_JS_RECEIVER_TYPE - 1);
__ Branch(&function, eq, a1, Operand(LAST_JS_RECEIVER_TYPE));
// Assume that there is no larger type.
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1);
// Return 'Function' for JSFunction objects.
__ Branch(&function, eq, a1, Operand(JS_FUNCTION_TYPE));
// Check if the constructor in the map is a JS function.
Register instance_type = a2;

View File

@ -3322,22 +3322,14 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
VisitForAccumulatorValue(args->at(0));
// If the object is a smi, we return null.
// If the object is not a JSReceiver, 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);
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
__ GetObjectType(v0, v0, a1); // Map is now in v0.
__ Branch(&null, lt, a1, Operand(FIRST_JS_RECEIVER_TYPE));
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
LAST_JS_RECEIVER_TYPE - 1);
__ Branch(&function, eq, a1, Operand(LAST_JS_RECEIVER_TYPE));
// Assume that there is no larger type.
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1);
// Return 'Function' for JSFunction objects.
__ Branch(&function, eq, a1, Operand(JS_FUNCTION_TYPE));
// Check if the constructor in the map is a JS function.
Register instance_type = a2;

View File

@ -3190,49 +3190,40 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
VisitForAccumulatorValue(args->at(0));
// If the object is a smi, we return null.
__ JumpIfSmi(rax, &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 JSReceiver, we return null.
__ JumpIfSmi(rax, &null, Label::kNear);
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
__ CmpObjectType(rax, FIRST_JS_RECEIVER_TYPE, rax);
// Map is now in rax.
__ j(below, &null);
__ j(below, &null, Label::kNear);
__ CmpInstanceType(rax, LAST_JS_RECEIVER_TYPE);
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
LAST_JS_RECEIVER_TYPE - 1);
__ j(equal, &function);
// Assume that there is no larger type.
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1);
// Return 'Function' for JSFunction objects.
__ CmpInstanceType(rax, JS_FUNCTION_TYPE);
__ j(equal, &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);
__ j(not_equal, &non_function_constructor, Label::kNear);
// 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);
// Objects with a non-function constructor have class 'Object'.
__ bind(&non_function_constructor);
__ Move(rax, isolate()->factory()->Object_string());
__ jmp(&done);
__ 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);
// Objects with a non-function constructor have class 'Object'.
__ bind(&non_function_constructor);
__ LoadRoot(rax, Heap::kObject_stringRootIndex);
// All done.
__ bind(&done);

View File

@ -4813,6 +4813,10 @@ bool Map::IsPrimitiveMap() {
STATIC_ASSERT(FIRST_PRIMITIVE_TYPE == FIRST_TYPE);
return instance_type() <= LAST_PRIMITIVE_TYPE;
}
bool Map::IsJSReceiverMap() {
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
return instance_type() >= FIRST_JS_RECEIVER_TYPE;
}
bool Map::IsJSObjectMap() {
STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
return instance_type() >= FIRST_JS_OBJECT_TYPE;

View File

@ -77,9 +77,7 @@ Handle<HeapType> Object::OptimalType(Isolate* isolate,
if (representation.IsHeapObject() && IsHeapObject()) {
// We can track only JavaScript objects with stable maps.
Handle<Map> 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->IsJSReceiverMap()) {
return HeapType::Class(map, isolate);
}
}

View File

@ -759,12 +759,6 @@ enum InstanceType {
// Boundaries for testing the types represented as JSObject
FIRST_JS_OBJECT_TYPE = JS_VALUE_TYPE,
LAST_JS_OBJECT_TYPE = LAST_TYPE,
//
FIRST_NONCALLABLE_SPEC_OBJECT_TYPE = JS_VALUE_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
};
STATIC_ASSERT(JS_OBJECT_TYPE == Internals::kJSObjectType);
@ -5928,6 +5922,7 @@ class Map: public HeapObject {
inline bool IsBooleanMap();
inline bool IsPrimitiveMap();
inline bool IsJSReceiverMap();
inline bool IsJSObjectMap();
inline bool IsJSArrayMap();
inline bool IsJSFunctionMap();

View File

@ -1380,9 +1380,10 @@ TEST(ReconfigureDataFieldAttribute_DataConstantToDataFieldAfterTargetMap) {
void UpdateExpectations(int property_index, Expectations& expectations) {
Isolate* isolate = CcTest::i_isolate();
Handle<HeapType> any_type = HeapType::Any(isolate);
Handle<HeapType> function_type =
HeapType::Class(isolate->sloppy_function_map(), isolate);
expectations.SetDataField(property_index, Representation::HeapObject(),
any_type);
function_type);
}
};
@ -2136,7 +2137,8 @@ TEST(TransitionDataConstantToAnotherDataConstant) {
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
Handle<HeapType> any_type = HeapType::Any(isolate);
Handle<HeapType> function_type =
HeapType::Class(isolate->sloppy_function_map(), isolate);
Handle<JSFunction> js_func1 = factory->NewFunction(factory->empty_string());
TransitionToDataConstantOperator transition_op1(js_func1);
@ -2144,8 +2146,8 @@ TEST(TransitionDataConstantToAnotherDataConstant) {
Handle<JSFunction> js_func2 = factory->NewFunction(factory->empty_string());
TransitionToDataConstantOperator transition_op2(js_func2);
FieldGeneralizationChecker checker(kPropCount - 1,
Representation::HeapObject(), any_type);
FieldGeneralizationChecker checker(
kPropCount - 1, Representation::HeapObject(), function_type);
TestTransitionTo(transition_op1, transition_op2, checker);
}