Commit 465aadc8 authored by ager@chromium.org's avatar ager@chromium.org

Port %ClassOf() optimization to X64 and ARM.

Review URL: http://codereview.chromium.org/150226

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2339 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 89b77643
......@@ -3176,9 +3176,60 @@ void CodeGenerator::VisitCallNew(CallNew* node) {
void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) {
VirtualFrame::SpilledScope spilled_scope;
ASSERT(args->length() == 1);
LoadAndSpill(args->at(0)); // Load the object.
frame_->CallRuntime(Runtime::kClassOf, 1);
JumpTarget leave, null, function, non_function_constructor;
// Load the object into r0.
LoadAndSpill(args->at(0));
frame_->EmitPop(r0);
// If the object is a smi, we return null.
__ tst(r0, Operand(kSmiTagMask));
null.Branch(eq);
// Check that the object is a JS object but take special care of JS
// functions to make sure they have 'Function' as their class.
__ CompareObjectType(r0, r0, r1, FIRST_JS_OBJECT_TYPE);
null.Branch(lt);
// 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(r1, Operand(JS_FUNCTION_TYPE));
function.Branch(eq);
// Check if the constructor in the map is a function.
__ ldr(r0, FieldMemOperand(r0, Map::kConstructorOffset));
__ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE);
non_function_constructor.Branch(ne);
// The r0 register now contains the constructor function. Grab the
// instance class name from there.
__ ldr(r0, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset));
__ ldr(r0, FieldMemOperand(r0, SharedFunctionInfo::kInstanceClassNameOffset));
frame_->EmitPush(r0);
leave.Jump();
// Functions have class 'Function'.
function.Bind();
__ mov(r0, Operand(Factory::function_class_symbol()));
frame_->EmitPush(r0);
leave.Jump();
// Objects with a non-function constructor have class 'Object'.
non_function_constructor.Bind();
__ mov(r0, Operand(Factory::Object_symbol()));
frame_->EmitPush(r0);
leave.Jump();
// Non-JS objects have class null.
null.Bind();
__ mov(r0, Operand(Factory::null_value()));
frame_->EmitPush(r0);
// All done.
leave.Bind();
}
......
......@@ -3367,11 +3367,67 @@ void CodeGenerator::GenerateFastMathOp(MathOp op, ZoneList<Expression*>* args) {
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));
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));
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());
non_function_constructor.Branch(not_equal);
}
// The obj 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();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment