Revision: 6027
Author: [email protected]
Date: Wed Dec 15 04:32:19 2010
Log: Support %_IsObject in Crankshaft.
Review URL: http://codereview.chromium.org/5806001
http://code.google.com/p/v8/source/detail?r=6027

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/arm/lithium-codegen-arm.h
 /branches/bleeding_edge/src/hydrogen-instructions.h
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.h
 /branches/bleeding_edge/src/ia32/lithium-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-ia32.h

=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc      Tue Dec 14 10:53:48 2010
+++ /branches/bleeding_edge/src/arm/lithium-arm.cc      Wed Dec 15 04:32:19 2010
@@ -204,6 +204,13 @@
   stream->Add(is_strict() ? " === null" : " == null");
   stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
 }
+
+
+void LIsObjectAndBranch::PrintDataTo(StringStream* stream) const {
+  stream->Add("if is_object(");
+  input()->PrintTo(stream);
+  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
+}


 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) const {
@@ -1238,6 +1245,17 @@
                                   temp,
                                   first_id,
                                   second_id);
+    } else if (v->IsIsObject()) {
+      HIsObject* compare = HIsObject::cast(v);
+      ASSERT(compare->value()->representation().IsTagged());
+
+      LOperand* temp1 = TempRegister();
+      LOperand* temp2 = TempRegister();
+      return new LIsObjectAndBranch(UseRegisterAtStart(compare->value()),
+                                    temp1,
+                                    temp2,
+                                    first_id,
+                                    second_id);
     } else if (v->IsCompareJSObjectEq()) {
       HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v);
return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()),
@@ -1598,6 +1616,14 @@
   return DefineAsRegister(new LIsNull(value,
                                       instr->is_strict()));
 }
+
+
+LInstruction* LChunkBuilder::DoIsObject(HIsObject* instr) {
+  ASSERT(instr->value()->representation().IsTagged());
+  LOperand* value = UseRegisterAtStart(instr->value());
+
+  return DefineAsRegister(new LIsObject(value, TempRegister()));
+}


 LInstruction* LChunkBuilder::DoIsSmi(HIsSmi* instr) {
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.h       Tue Dec 14 10:53:48 2010
+++ /branches/bleeding_edge/src/arm/lithium-arm.h       Wed Dec 15 04:32:19 2010
@@ -121,6 +121,8 @@
 //     LInteger32ToDouble
 //     LIsNull
 //     LIsNullAndBranch
+//     LIsObject
+//     LIsObjectAndBranch
 //     LIsSmi
 //     LIsSmiAndBranch
 //     LLoadNamedField
@@ -203,6 +205,8 @@
   V(Integer32ToDouble)                          \
   V(IsNull)                                     \
   V(IsNullAndBranch)                            \
+  V(IsObject)                                   \
+  V(IsObjectAndBranch)                          \
   V(IsSmi)                                      \
   V(IsSmiAndBranch)                             \
   V(HasInstanceType)                            \
@@ -742,6 +746,48 @@
 };


+class LIsObject: public LUnaryOperation {
+ public:
+  LIsObject(LOperand* value, LOperand* temp)
+      : LUnaryOperation(value), temp_(temp) {}
+
+  DECLARE_CONCRETE_INSTRUCTION(IsObject, "is-object")
+
+  LOperand* temp() const { return temp_; }
+
+ private:
+  LOperand* temp_;
+};
+
+
+class LIsObjectAndBranch: public LIsObject {
+ public:
+  LIsObjectAndBranch(LOperand* value,
+                     LOperand* temp,
+                     LOperand* temp2,
+                     int true_block_id,
+                     int false_block_id)
+      : LIsObject(value, temp),
+        temp2_(temp2),
+        true_block_id_(true_block_id),
+        false_block_id_(false_block_id) { }
+
+  DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch, "is-object-and-branch")
+  virtual void PrintDataTo(StringStream* stream) const;
+  virtual bool IsControl() const { return true; }
+
+  int true_block_id() const { return true_block_id_; }
+  int false_block_id() const { return false_block_id_; }
+
+  LOperand* temp2() const { return temp2_; }
+
+ private:
+  LOperand* temp2_;
+  int true_block_id_;
+  int false_block_id_;
+};
+
+
 class LIsSmi: public LUnaryOperation {
  public:
   explicit LIsSmi(LOperand* value) : LUnaryOperation(value) {}
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Fri Dec 10 06:10:54 2010 +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Wed Dec 15 04:32:19 2010
@@ -1211,6 +1211,26 @@
     EmitBranch(true_block, false_block, ne);
   }
 }
+
+
+Condition LCodeGen::EmitIsObject(Register input,
+                                 Register temp1,
+                                 Register temp2,
+                                 Label* is_not_object,
+                                 Label* is_object) {
+  Abort("EmitIsObject unimplemented.");
+  return ne;
+}
+
+
+void LCodeGen::DoIsObject(LIsObject* instr) {
+  Abort("DoIsObject unimplemented.");
+}
+
+
+void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
+  Abort("DoIsObjectAndBranch unimplemented.");
+}


 void LCodeGen::DoIsSmi(LIsSmi* instr) {
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.h Tue Dec 7 03:31:57 2010 +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.h Wed Dec 15 04:32:19 2010
@@ -208,6 +208,15 @@
   Condition EmitTypeofIs(Label* true_label, Label* false_label,
                          Register input, Handle<String> type_name);

+  // Emits optimized code for %_IsObject(x).  Preserves input register.
+  // Returns the condition on which a final split to
+  // true and false label should be made, to optimize fallthrough.
+  Condition EmitIsObject(Register input,
+                         Register temp1,
+                         Register temp2,
+                         Label* is_not_object,
+                         Label* is_object);
+
   LChunk* const chunk_;
   MacroAssembler* const masm_;
   CompilationInfo* const info_;
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Tue Dec 14 10:53:48 2010 +++ /branches/bleeding_edge/src/hydrogen-instructions.h Wed Dec 15 04:32:19 2010
@@ -140,6 +140,7 @@
 //         HHasCachedArrayIndex
 //         HHasInstanceType
 //         HIsNull
+//         HIsObject
 //         HIsSmi
 //       HValueOf
 //     HUnknownOSRValue
@@ -208,6 +209,7 @@
   V(Goto)                                      \
   V(InstanceOf)                                \
   V(IsNull)                                    \
+  V(IsObject)                                  \
   V(IsSmi)                                     \
   V(HasInstanceType)                           \
   V(HasCachedArrayIndex)                       \
@@ -2100,6 +2102,14 @@
 };


+class HIsObject: public HUnaryPredicate {
+ public:
+  explicit HIsObject(HValue* value) : HUnaryPredicate(value) { }
+
+  DECLARE_CONCRETE_INSTRUCTION(IsObject, "is_object")
+};
+
+
 class HIsSmi: public HUnaryPredicate {
  public:
   explicit HIsSmi(HValue* value) : HUnaryPredicate(value) { }
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Wed Dec 15 03:47:05 2010
+++ /branches/bleeding_edge/src/hydrogen.cc     Wed Dec 15 04:32:19 2010
@@ -4950,14 +4950,18 @@
 }


-void HGraphBuilder::GenerateIsNonNegativeSmi(int argument_count,
-                                             int ast_id) {
-  BAILOUT("inlined runtime function: IsNonNegativeSmi");
+void HGraphBuilder::GenerateIsObject(int argument_count, int ast_id) {
+  ASSERT(argument_count == 1);
+
+  HValue* value = Pop();
+  HIsObject* test = new HIsObject(value);
+  ast_context()->ReturnInstruction(test, ast_id);
 }


-void HGraphBuilder::GenerateIsObject(int argument_count, int ast_id) {
-  BAILOUT("inlined runtime function: IsObject");
+void HGraphBuilder::GenerateIsNonNegativeSmi(int argument_count,
+                                             int ast_id) {
+  BAILOUT("inlined runtime function: IsNonNegativeSmi");
 }


=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Tue Dec 14 05:21:29 2010 +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Wed Dec 15 04:32:19 2010
@@ -1401,6 +1401,71 @@
     EmitBranch(true_block, false_block, not_zero);
   }
 }
+
+
+Condition LCodeGen::EmitIsObject(Register input,
+                                 Register temp1,
+                                 Register temp2,
+                                 Label* is_not_object,
+                                 Label* is_object) {
+  ASSERT(!input.is(temp1));
+  ASSERT(!input.is(temp2));
+  ASSERT(!temp1.is(temp2));
+
+  __ test(input, Immediate(kSmiTagMask));
+  __ j(equal, is_not_object);
+
+  __ cmp(input, Factory::null_value());
+  __ j(equal, is_object);
+
+  __ mov(temp1, FieldOperand(input, HeapObject::kMapOffset));
+  // Undetectable objects behave like undefined.
+  __ movzx_b(temp2, FieldOperand(temp1, Map::kBitFieldOffset));
+  __ test(temp2, Immediate(1 << Map::kIsUndetectable));
+  __ j(not_zero, is_not_object);
+
+  __ movzx_b(temp2, FieldOperand(temp1, Map::kInstanceTypeOffset));
+  __ cmp(temp2, FIRST_JS_OBJECT_TYPE);
+  __ j(below, is_not_object);
+  __ cmp(temp2, LAST_JS_OBJECT_TYPE);
+  return below_equal;
+}
+
+
+void LCodeGen::DoIsObject(LIsObject* instr) {
+  Register reg = ToRegister(instr->input());
+  Register result = ToRegister(instr->result());
+  Register temp = ToRegister(instr->temp());
+  Label is_false, is_true, done;
+
+ Condition true_cond = EmitIsObject(reg, result, temp, &is_false, &is_true);
+  __ j(true_cond, &is_true);
+
+  __ bind(&is_false);
+  __ mov(result, Handle<Object>(Heap::false_value()));
+  __ jmp(&done);
+
+  __ bind(&is_true);
+  __ mov(result, Handle<Object>(Heap::true_value()));
+
+  __ bind(&done);
+}
+
+
+void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
+  Register reg = ToRegister(instr->input());
+  Register temp = ToRegister(instr->temp());
+  Register temp2 = ToRegister(instr->temp2());
+
+  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);
+
+ Condition true_cond = EmitIsObject(reg, temp, temp2, false_label, true_label);
+
+  EmitBranch(true_block, false_block, true_cond);
+}


 void LCodeGen::DoIsSmi(LIsSmi* instr) {
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.h Tue Dec 14 05:21:29 2010 +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.h Wed Dec 15 04:32:19 2010
@@ -197,6 +197,15 @@
   Condition EmitTypeofIs(Label* true_label, Label* false_label,
                          Register input, Handle<String> type_name);

+  // Emits optimized code for %_IsObject(x).  Preserves input register.
+  // Returns the condition on which a final split to
+  // true and false label should be made, to optimize fallthrough.
+  Condition EmitIsObject(Register input,
+                         Register temp1,
+                         Register temp2,
+                         Label* is_not_object,
+                         Label* is_object);
+
   LChunk* const chunk_;
   MacroAssembler* const masm_;
   CompilationInfo* const info_;
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.cc Tue Dec 14 10:53:48 2010 +++ /branches/bleeding_edge/src/ia32/lithium-ia32.cc Wed Dec 15 04:32:19 2010
@@ -204,6 +204,13 @@
   stream->Add(is_strict() ? " === null" : " == null");
   stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
 }
+
+
+void LIsObjectAndBranch::PrintDataTo(StringStream* stream) const {
+  stream->Add("if is_object(");
+  input()->PrintTo(stream);
+  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
+}


 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) const {
@@ -1251,6 +1258,17 @@
                                   temp,
                                   first_id,
                                   second_id);
+    } else if (v->IsIsObject()) {
+      HIsObject* compare = HIsObject::cast(v);
+      ASSERT(compare->value()->representation().IsTagged());
+
+      LOperand* temp1 = TempRegister();
+      LOperand* temp2 = TempRegister();
+      return new LIsObjectAndBranch(UseRegisterAtStart(compare->value()),
+                                    temp1,
+                                    temp2,
+                                    first_id,
+                                    second_id);
     } else if (v->IsCompareJSObjectEq()) {
       HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v);
return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()),
@@ -1628,6 +1646,14 @@
   return DefineAsRegister(new LIsNull(value,
                                       instr->is_strict()));
 }
+
+
+LInstruction* LChunkBuilder::DoIsObject(HIsObject* instr) {
+  ASSERT(instr->value()->representation().IsTagged());
+  LOperand* value = UseRegisterAtStart(instr->value());
+
+  return DefineAsRegister(new LIsObject(value, TempRegister()));
+}


 LInstruction* LChunkBuilder::DoIsSmi(HIsSmi* instr) {
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.h     Tue Dec 14 10:53:48 2010
+++ /branches/bleeding_edge/src/ia32/lithium-ia32.h     Wed Dec 15 04:32:19 2010
@@ -124,6 +124,8 @@
 //     LInteger32ToDouble
 //     LIsNull
 //     LIsNullAndBranch
+//     LIsObject
+//     LIsObjectAndBranch
 //     LIsSmi
 //     LIsSmiAndBranch
 //     LLoadNamedField
@@ -206,6 +208,8 @@
   V(Integer32ToDouble)                          \
   V(IsNull)                                     \
   V(IsNullAndBranch)                            \
+  V(IsObject)                                   \
+  V(IsObjectAndBranch)                          \
   V(IsSmi)                                      \
   V(IsSmiAndBranch)                             \
   V(HasInstanceType)                            \
@@ -747,6 +751,48 @@
 };


+class LIsObject: public LUnaryOperation {
+ public:
+  LIsObject(LOperand* value, LOperand* temp)
+      : LUnaryOperation(value), temp_(temp) {}
+
+  DECLARE_CONCRETE_INSTRUCTION(IsObject, "is-object")
+
+  LOperand* temp() const { return temp_; }
+
+ private:
+  LOperand* temp_;
+};
+
+
+class LIsObjectAndBranch: public LIsObject {
+ public:
+  LIsObjectAndBranch(LOperand* value,
+                     LOperand* temp,
+                     LOperand* temp2,
+                     int true_block_id,
+                     int false_block_id)
+      : LIsObject(value, temp),
+        temp2_(temp2),
+        true_block_id_(true_block_id),
+        false_block_id_(false_block_id) { }
+
+  DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch, "is-object-and-branch")
+  virtual void PrintDataTo(StringStream* stream) const;
+  virtual bool IsControl() const { return true; }
+
+  int true_block_id() const { return true_block_id_; }
+  int false_block_id() const { return false_block_id_; }
+
+  LOperand* temp2() const { return temp2_; }
+
+ private:
+  LOperand* temp2_;
+  int true_block_id_;
+  int false_block_id_;
+};
+
+
 class LIsSmi: public LUnaryOperation {
  public:
   explicit LIsSmi(LOperand* value) : LUnaryOperation(value) {}

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

Reply via email to