Index: src/ia32/codegen-ia32.cc |
=================================================================== |
--- src/ia32/codegen-ia32.cc (revision 2290) |
+++ src/ia32/codegen-ia32.cc (working copy) |
@@ -5022,6 +5022,70 @@ |
} |
+void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { |
+ ASSERT(args->length() == 1); |
+ JumpTarget leave, null, function, non_function_constructor; |
+ Load(args->at(0)); // Load the object. |
+ Result obj = frame_->Pop(); |
+ obj.ToRegister(); |
+ frame_->Spill(obj.reg()); |
+ |
+ // If the object is a smi, we return null. |
+ __ test(obj.reg(), Immediate(kSmiTagMask)); |
+ null.Branch(zero); |
+ |
+ // 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(less); |
+ |
+ // 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); |
+ } |
+ |
+ // Check if the constructor in the map is a function. |
+ { Result tmp = allocator()->Allocate(); |
+ __ mov(obj.reg(), FieldOperand(obj.reg(), Map::kConstructorOffset)); |
+ __ CmpObjectType(obj.reg(), JS_FUNCTION_TYPE, tmp.reg()); |
+ non_function_constructor.Branch(not_equal); |
+ } |
+ |
+ // The map register now contains the constructor function. Grab the |
+ // instance class name from there. |
+ __ mov(obj.reg(), |
+ FieldOperand(obj.reg(), JSFunction::kSharedFunctionInfoOffset)); |
+ __ mov(obj.reg(), |
+ FieldOperand(obj.reg(), SharedFunctionInfo::kInstanceClassNameOffset)); |
+ frame_->Push(&obj); |
+ leave.Jump(); |
+ |
+ // Functions have class 'Function'. |
+ function.Bind(); |
+ frame_->Push(Factory::function_class_symbol()); |
+ leave.Jump(); |
+ |
+ // Objects with a non-function constructor have class 'Object'. |
+ non_function_constructor.Bind(); |
+ frame_->Push(Factory::Object_symbol()); |
+ leave.Jump(); |
+ |
+ // Non-JS objects have class null. |
+ null.Bind(); |
+ frame_->Push(Factory::null_value()); |
+ |
+ // All done. |
+ leave.Bind(); |
+} |
+ |
+ |
void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { |
ASSERT(args->length() == 1); |
JumpTarget leave; |