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