Author: [email protected]
Date: Thu Jul  2 07:17:10 2009
New Revision: 2339

Modified:
    branches/bleeding_edge/src/arm/codegen-arm.cc
    branches/bleeding_edge/src/x64/codegen-x64.cc

Log:
Port %ClassOf() optimization to X64 and ARM.
Review URL: http://codereview.chromium.org/150226

Modified: branches/bleeding_edge/src/arm/codegen-arm.cc
==============================================================================
--- branches/bleeding_edge/src/arm/codegen-arm.cc       (original)
+++ branches/bleeding_edge/src/arm/codegen-arm.cc       Thu Jul  2 07:17:10 2009
@@ -3176,9 +3176,60 @@
  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();
  }



Modified: branches/bleeding_edge/src/x64/codegen-x64.cc
==============================================================================
--- branches/bleeding_edge/src/x64/codegen-x64.cc       (original)
+++ branches/bleeding_edge/src/x64/codegen-x64.cc       Thu Jul  2 07:17:10 2009
@@ -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));
+  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();
  }



--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to