Revision: 6271
Author: [email protected]
Date: Tue Jan 11 06:01:53 2011
Log: ARM: Implement ClassOf in the lithium arm backend.

Review URL: http://codereview.chromium.org/6201004
http://code.google.com/p/v8/source/detail?r=6271

Modified:
 /branches/bleeding_edge/src/arm/lithium-arm.cc
 /branches/bleeding_edge/src/arm/lithium-arm.h
 /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
 /branches/bleeding_edge/src/ia32/lithium-ia32.h

=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc      Tue Jan 11 04:10:11 2011
+++ /branches/bleeding_edge/src/arm/lithium-arm.cc      Tue Jan 11 06:01:53 2011
@@ -998,7 +998,6 @@

       return new LClassOfTestAndBranch(UseTempRegister(compare->value()),
                                        TempRegister(),
-                                       TempRegister(),
                                        first_id,
                                        second_id);
     } else if (v->IsCompare()) {
@@ -1485,8 +1484,7 @@
 LInstruction* LChunkBuilder::DoClassOfTest(HClassOfTest* instr) {
   ASSERT(instr->value()->representation().IsTagged());
   LOperand* value = UseTempRegister(instr->value());
-
-  return DefineSameAsFirst(new LClassOfTest(value, TempRegister()));
+  return DefineSameAsFirst(new LClassOfTest(value));
 }


=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.h       Tue Jan 11 04:10:11 2011
+++ /branches/bleeding_edge/src/arm/lithium-arm.h       Tue Jan 11 06:01:53 2011
@@ -848,18 +848,12 @@

 class LClassOfTest: public LUnaryOperation {
  public:
-  LClassOfTest(LOperand* value, LOperand* temp)
-      : LUnaryOperation(value), temporary_(temp) {}
+  explicit LClassOfTest(LOperand* value) : LUnaryOperation(value) {}

   DECLARE_CONCRETE_INSTRUCTION(ClassOfTest, "class-of-test")
   DECLARE_HYDROGEN_ACCESSOR(ClassOfTest)

   virtual void PrintDataTo(StringStream* stream) const;
-
-  LOperand* temporary() { return temporary_; }
-
- private:
-  LOperand *temporary_;
 };


@@ -867,11 +861,10 @@
  public:
   LClassOfTestAndBranch(LOperand* value,
                         LOperand* temporary,
-                        LOperand* temporary2,
                         int true_block_id,
                         int false_block_id)
-      : LClassOfTest(value, temporary),
-        temporary2_(temporary2),
+      : LClassOfTest(value),
+        temporary_(temporary),
         true_block_id_(true_block_id),
         false_block_id_(false_block_id) { }

@@ -882,10 +875,10 @@

   int true_block_id() const { return true_block_id_; }
   int false_block_id() const { return false_block_id_; }
-  LOperand* temporary2() { return temporary2_; }
+  LOperand* temporary() { return temporary_; }

  private:
-  LOperand* temporary2_;
+  LOperand* temporary_;
   int true_block_id_;
   int false_block_id_;
 };
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Tue Jan 11 05:50:12 2011 +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Tue Jan 11 06:01:53 2011
@@ -958,12 +958,26 @@
   Register result = ToRegister(instr->result());
   Register array = ToRegister(instr->input());
   __ ldr(result, FieldMemOperand(array, FixedArray::kLengthOffset));
-  Abort("DoFixedArrayLength untested.");
 }


 void LCodeGen::DoValueOf(LValueOf* instr) {
-  Abort("DoValueOf unimplemented.");
+  Register input = ToRegister(instr->input());
+  Register result = ToRegister(instr->result());
+  Register map = ToRegister(instr->temporary());
+  ASSERT(input.is(result));
+  Label done;
+
+  // If the object is a smi return the object.
+  __ tst(input, Operand(kSmiTagMask));
+  __ b(eq, &done);
+
+  // If the object is not a value type, return the object.
+  __ CompareObjectType(input, map, map, JS_VALUE_TYPE);
+  __ b(ne, &done);
+  __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset));
+
+  __ bind(&done);
 }


@@ -971,7 +985,6 @@
   LOperand* input = instr->input();
   ASSERT(input->Equals(instr->result()));
   __ mvn(ToRegister(input), Operand(ToRegister(input)));
-  Abort("DoBitNotI untested.");
 }


@@ -1408,7 +1421,7 @@
 }


-// Branches to a label or falls through with the answer in the z flag. Trashes
+// Branches to a label or falls through with the answer in flags.  Trashes
 // the temp registers, but not the input.  Only input and temp2 may alias.
 void LCodeGen::EmitClassOfTest(Label* is_true,
                                Label* is_false,
@@ -1416,17 +1429,91 @@
                                Register input,
                                Register temp,
                                Register temp2) {
-  Abort("EmitClassOfTest unimplemented.");
+  ASSERT(!input.is(temp));
+ ASSERT(!temp.is(temp2)); // But input and temp2 may be the same register.
+  __ tst(input, Operand(kSmiTagMask));
+  __ b(eq, is_false);
+  __ CompareObjectType(input, temp, temp2, FIRST_JS_OBJECT_TYPE);
+  __ b(lt, is_false);
+
+  // Map is now in temp.
+  // Functions have class 'Function'.
+  __ CompareInstanceType(temp, temp2, JS_FUNCTION_TYPE);
+  if (class_name->IsEqualTo(CStrVector("Function"))) {
+    __ b(eq, is_true);
+  } else {
+    __ b(eq, is_false);
+  }
+
+  // Check if the constructor in the map is a function.
+  __ ldr(temp, FieldMemOperand(temp, Map::kConstructorOffset));
+
+  // 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);
+
+  // Objects with a non-function constructor have class 'Object'.
+  __ CompareObjectType(temp, temp2, temp2, JS_FUNCTION_TYPE);
+  if (class_name->IsEqualTo(CStrVector("Object"))) {
+    __ b(ne, is_true);
+  } else {
+    __ b(ne, is_false);
+  }
+
+  // temp now contains the constructor function. Grab the
+  // instance class name from there.
+ __ ldr(temp, FieldMemOperand(temp, JSFunction::kSharedFunctionInfoOffset));
+  __ ldr(temp, FieldMemOperand(temp,
+ SharedFunctionInfo::kInstanceClassNameOffset)); + // The class name we are testing against is a symbol because it's a literal. + // The name in the constructor is a symbol because of the way the context is
+  // booted.  This routine isn't expected to work for random API-created
+ // classes and it doesn't have to because you can't access it with natives + // syntax. Since both sides are symbols it is sufficient to use an identity
+  // comparison.
+  __ cmp(temp, Operand(class_name));
+  // End with the answer in flags.
 }


 void LCodeGen::DoClassOfTest(LClassOfTest* instr) {
-  Abort("DoClassOfTest unimplemented.");
+  Register input = ToRegister(instr->input());
+  Register result = ToRegister(instr->result());
+  ASSERT(input.is(result));
+  Handle<String> class_name = instr->hydrogen()->class_name();
+
+  Label done, is_true, is_false;
+
+ EmitClassOfTest(&is_true, &is_false, class_name, input, scratch0(), input);
+  __ b(ne, &is_false);
+
+  __ bind(&is_true);
+  __ LoadRoot(result, Heap::kTrueValueRootIndex);
+  __ jmp(&done);
+
+  __ bind(&is_false);
+  __ LoadRoot(result, Heap::kFalseValueRootIndex);
+  __ bind(&done);
 }


 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
-  Abort("DoClassOfTestAndBranch unimplemented.");
+  Register input = ToRegister(instr->input());
+  Register temp = scratch0();
+  Register temp2 = ToRegister(instr->temporary());
+  Handle<String> class_name = instr->hydrogen()->class_name();
+
+  int true_block = chunk_->LookupDestination(instr->true_block_id());
+  int false_block = chunk_->LookupDestination(instr->false_block_id());
+
+  Label* true_label = chunk_->GetAssemblyLabel(true_block);
+  Label* false_label = chunk_->GetAssemblyLabel(false_block);
+
+  EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2);
+
+  EmitBranch(true_block, false_block, eq);
 }


=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.h     Tue Jan 11 05:48:49 2011
+++ /branches/bleeding_edge/src/ia32/lithium-ia32.h     Tue Jan 11 06:01:53 2011
@@ -898,7 +898,7 @@
   LOperand* temporary() { return temporary_; }

  private:
-  LOperand *temporary_;
+  LOperand* temporary_;
 };


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

Reply via email to