Chromium Code Reviews| Index: src/x64/codegen-x64.cc |
| =================================================================== |
| --- src/x64/codegen-x64.cc (revision 2324) |
| +++ src/x64/codegen-x64.cc (working copy) |
| @@ -3367,11 +3367,67 @@ |
| void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { |
| - // TODO(X64): Optimize this like it's done on IA-32. |
| ASSERT(args->length() == 1); |
| + JumpTarget leave, null, function, non_function_constructor; |
| Load(args->at(0)); // Load the object. |
| - Result result = frame_->CallRuntime(Runtime::kClassOf, 1); |
| - frame_->Push(&result); |
| + Result obj = frame_->Pop(); |
| + obj.ToRegister(); |
| + frame_->Spill(obj.reg()); |
| + |
| + // If the object is a smi, we return null. |
| + __ testl(obj.reg(), Immediate(kSmiTagMask)); |
|
Erik Corry
2009/07/02 13:48:31
Do we need an l here? Will that preclude an 8 bit
Mads Ager (chromium)
2009/07/02 14:14:08
I'm using testl for consistency with the rest of t
William Hesse
2009/07/02 14:44:25
testl does not preclude an 8-bit encoding of the i
|
| + 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(); |
| + __ movq(obj.reg(), FieldOperand(obj.reg(), HeapObject::kMapOffset)); |
| + __ movb(tmp.reg(), FieldOperand(obj.reg(), Map::kInstanceTypeOffset)); |
| + __ cmpb(tmp.reg(), Immediate(FIRST_JS_OBJECT_TYPE)); |
|
Erik Corry
2009/07/02 13:48:31
CmpObjectType?
Mads Ager (chromium)
2009/07/02 14:14:08
Can't on x64/ia32 because the map register is clob
William Hesse
2009/07/02 14:44:25
On x64 and ia32, the map register isn't clobbered
|
| + 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); |
| + __ cmpb(tmp.reg(), Immediate(JS_FUNCTION_TYPE)); |
| + function.Branch(equal); |
| + } |
| + |
| + // Check if the constructor in the map is a function. |
| + { Result tmp = allocator()->Allocate(); |
| + __ movq(obj.reg(), FieldOperand(obj.reg(), Map::kConstructorOffset)); |
| + __ CmpObjectType(obj.reg(), JS_FUNCTION_TYPE, tmp.reg()); |
|
William Hesse
2009/07/02 14:44:25
kScratchRegister, rather than tmp, can be used her
|
| + non_function_constructor.Branch(not_equal); |
| + } |
| + |
| + // The map register now contains the constructor function. Grab the |
| + // instance class name from there. |
| + __ movq(obj.reg(), |
| + FieldOperand(obj.reg(), JSFunction::kSharedFunctionInfoOffset)); |
| + __ movq(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(); |
| } |