Revision: 14886
Author: [email protected]
Date: Wed May 29 07:49:28 2013
Log: Convert ToBooleanStub to a HydrogenStub. Currently just using the
existing HBranch instruction, which is still fully implemented in Lithium.
Will refactor HBranch in a next CL.
[
CL breaks mips, since the deoptimizer in
Deoptimizer::DoTranslateCommand(...) does not convert smis passed to the
stub via a0.
]
BUG=
[email protected]
Review URL: https://codereview.chromium.org/15302004
http://code.google.com/p/v8/source/detail?r=14886
Modified:
/branches/bleeding_edge/src/arm/code-stubs-arm.cc
/branches/bleeding_edge/src/arm/full-codegen-arm.cc
/branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
/branches/bleeding_edge/src/code-stubs-hydrogen.cc
/branches/bleeding_edge/src/code-stubs.cc
/branches/bleeding_edge/src/code-stubs.h
/branches/bleeding_edge/src/hydrogen-instructions.h
/branches/bleeding_edge/src/ia32/code-stubs-ia32.cc
/branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
/branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
/branches/bleeding_edge/src/ic.cc
/branches/bleeding_edge/src/ic.h
/branches/bleeding_edge/src/isolate.cc
/branches/bleeding_edge/src/mips/lithium-codegen-mips.cc
/branches/bleeding_edge/src/objects-inl.h
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/src/x64/code-stubs-x64.cc
/branches/bleeding_edge/src/x64/full-codegen-x64.cc
/branches/bleeding_edge/src/x64/lithium-codegen-x64.cc
=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.cc Fri May 24 04:44:55
2013
+++ /branches/bleeding_edge/src/arm/code-stubs-arm.cc Wed May 29 07:49:28
2013
@@ -173,6 +173,19 @@
CodeStubInterfaceDescriptor* descriptor) {
InitializeArrayConstructorDescriptor(isolate, descriptor, -1);
}
+
+
+void ToBooleanStub::InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor) {
+ static Register registers[] = { r0 };
+ descriptor->register_param_count_ = 1;
+ descriptor->register_params_ = registers;
+ descriptor->deoptimization_handler_ =
+ FUNCTION_ADDR(ToBooleanIC_Miss);
+ descriptor->SetMissHandler(
+ ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate));
+}
#define __ ACCESS_MASM(masm)
@@ -1205,116 +1218,6 @@
__ bind(&miss);
GenerateMiss(masm);
}
-
-
-// The stub expects its argument in the tos_ register and returns its
result in
-// it, too: zero for false, and a non-zero value for true.
-void ToBooleanStub::Generate(MacroAssembler* masm) {
- // This stub overrides SometimesSetsUpAFrame() to return false. That
means
- // we cannot call anything that could cause a GC from this stub.
- Label patch;
- const Register map = r9.is(tos_) ? r7 : r9;
-
- // undefined -> false.
- CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false);
-
- // Boolean -> its value.
- CheckOddball(masm, BOOLEAN, Heap::kFalseValueRootIndex, false);
- CheckOddball(masm, BOOLEAN, Heap::kTrueValueRootIndex, true);
-
- // 'null' -> false.
- CheckOddball(masm, NULL_TYPE, Heap::kNullValueRootIndex, false);
-
- if (types_.Contains(SMI)) {
- // Smis: 0 -> false, all other -> true
- __ SmiTst(tos_);
- // tos_ contains the correct return value already
- __ Ret(eq);
- } else if (types_.NeedsMap()) {
- // If we need a map later and have a Smi -> patch.
- __ JumpIfSmi(tos_, &patch);
- }
-
- if (types_.NeedsMap()) {
- __ ldr(map, FieldMemOperand(tos_, HeapObject::kMapOffset));
-
- if (types_.CanBeUndetectable()) {
- __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset));
- __ tst(ip, Operand(1 << Map::kIsUndetectable));
- // Undetectable -> false.
- __ mov(tos_, Operand::Zero(), LeaveCC, ne);
- __ Ret(ne);
- }
- }
-
- if (types_.Contains(SPEC_OBJECT)) {
- // Spec object -> true.
- __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE);
- // tos_ contains the correct non-zero return value already.
- __ Ret(ge);
- }
-
- if (types_.Contains(STRING)) {
- // String value -> false iff empty.
- __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE);
- __ ldr(tos_, FieldMemOperand(tos_, String::kLengthOffset), lt);
- __ Ret(lt); // the string length is OK as the return value
- }
-
- if (types_.Contains(HEAP_NUMBER)) {
- // Heap number -> false iff +0, -0, or NaN.
- Label not_heap_number;
- __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
- __ b(ne, ¬_heap_number);
-
- __ vldr(d1, FieldMemOperand(tos_, HeapNumber::kValueOffset));
- __ VFPCompareAndSetFlags(d1, 0.0);
- // "tos_" is a register, and contains a non zero value by default.
- // Hence we only need to overwrite "tos_" with zero to return false for
- // FP_ZERO or FP_NAN cases. Otherwise, by default it returns true.
- __ mov(tos_, Operand::Zero(), LeaveCC, eq); // for FP_ZERO
- __ mov(tos_, Operand::Zero(), LeaveCC, vs); // for FP_NAN
- __ Ret();
- __ bind(¬_heap_number);
- }
-
- __ bind(&patch);
- GenerateTypeTransition(masm);
-}
-
-
-void ToBooleanStub::CheckOddball(MacroAssembler* masm,
- Type type,
- Heap::RootListIndex value,
- bool result) {
- if (types_.Contains(type)) {
- // If we see an expected oddball, return its ToBoolean value tos_.
- __ LoadRoot(ip, value);
- __ cmp(tos_, ip);
- // The value of a root is never NULL, so we can avoid loading a
non-null
- // value into tos_ when we want to return 'true'.
- if (!result) {
- __ mov(tos_, Operand::Zero(), LeaveCC, eq);
- }
- __ Ret(eq);
- }
-}
-
-
-void ToBooleanStub::GenerateTypeTransition(MacroAssembler* masm) {
- if (!tos_.is(r3)) {
- __ mov(r3, Operand(tos_));
- }
- __ mov(r2, Operand(Smi::FromInt(tos_.code())));
- __ mov(r1, Operand(Smi::FromInt(types_.ToByte())));
- __ Push(r3, r2, r1);
- // Patch the caller to an appropriate specialized stub and return the
- // operation result to the caller of the stub.
- __ TailCallExternalReference(
- ExternalReference(IC_Utility(IC::kToBoolean_Patch), masm->isolate()),
- 3,
- 1);
-}
void StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Thu May 23 02:51:06
2013
+++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Wed May 29 07:49:28
2013
@@ -678,8 +678,8 @@
Label* if_true,
Label* if_false,
Label* fall_through) {
- ToBooleanStub stub(result_register());
- __ CallStub(&stub, condition->test_id());
+ Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
+ CallIC(ic, RelocInfo::CODE_TARGET, condition->test_id());
__ tst(result_register(), result_register());
Split(ne, if_true, if_false, fall_through);
}
@@ -2050,8 +2050,8 @@
Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize();
CallIC(done_ic); // result.done in
r0
__ add(sp, sp, Operand(kPointerSize)); // drop LoadIC
state
- ToBooleanStub stub(r0);
- __ CallStub(&stub);
+ Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
+ CallIC(bool_ic);
__ cmp(r0, Operand(0));
__ b(eq, &l_try);
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Wed May 29
05:09:03 2013
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Wed May 29
07:49:28 2013
@@ -2247,10 +2247,12 @@
Representation r = instr->hydrogen()->value()->representation();
if (r.IsInteger32() || r.IsSmi()) {
+ ASSERT(!info()->IsStub());
Register reg = ToRegister(instr->value());
__ cmp(reg, Operand::Zero());
EmitBranch(true_block, false_block, ne);
} else if (r.IsDouble()) {
+ ASSERT(!info()->IsStub());
DwVfpRegister reg = ToDoubleRegister(instr->value());
// Test the double value. Zero and NaN are false.
__ VFPCompareAndSetFlags(reg, 0.0);
@@ -2261,9 +2263,11 @@
Register reg = ToRegister(instr->value());
HType type = instr->hydrogen()->value()->type();
if (type.IsBoolean()) {
+ ASSERT(!info()->IsStub());
__ CompareRoot(reg, Heap::kTrueValueRootIndex);
EmitBranch(true_block, false_block, eq);
} else if (type.IsSmi()) {
+ ASSERT(!info()->IsStub());
__ cmp(reg, Operand::Zero());
EmitBranch(true_block, false_block, ne);
} else {
=======================================
--- /branches/bleeding_edge/src/code-stubs-hydrogen.cc Wed May 29 05:36:41
2013
+++ /branches/bleeding_edge/src/code-stubs-hydrogen.cc Wed May 29 07:49:28
2013
@@ -673,5 +673,25 @@
Handle<Code> CompareNilICStub::GenerateCode() {
return DoGenerateCode(this);
}
+
+
+template <>
+HValue* CodeStubGraphBuilder<ToBooleanStub>::BuildCodeInitializedStub() {
+ ToBooleanStub* stub = casted_stub();
+
+ IfBuilder if_true(this);
+ if_true.If<HBranch>(GetParameter(0), stub->GetTypes());
+ if_true.Then();
+ if_true.Return(graph()->GetConstant1());
+ if_true.Else();
+ if_true.End();
+ return graph()->GetConstant0();
+}
+
+
+Handle<Code> ToBooleanStub::GenerateCode() {
+ return DoGenerateCode(this);
+}
+
} } // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/code-stubs.cc Fri May 24 08:20:48 2013
+++ /branches/bleeding_edge/src/code-stubs.cc Wed May 29 07:49:28 2013
@@ -570,6 +570,14 @@
stream->Add("CallConstructStub");
if (RecordCallTarget()) stream->Add("_Recording");
}
+
+
+bool ToBooleanStub::Record(Handle<Object> object) {
+ Types old_types(types_);
+ bool to_boolean_value = types_.Record(object);
+ old_types.TraceTransition(types_);
+ return to_boolean_value;
+}
void ToBooleanStub::PrintName(StringStream* stream) {
=======================================
--- /branches/bleeding_edge/src/code-stubs.h Mon May 27 06:59:20 2013
+++ /branches/bleeding_edge/src/code-stubs.h Wed May 29 07:49:28 2013
@@ -1816,7 +1816,7 @@
};
-class ToBooleanStub: public PlatformCodeStub {
+class ToBooleanStub: public HydrogenCodeStub {
public:
enum Type {
UNDEFINED,
@@ -1850,31 +1850,47 @@
static Types no_types() { return Types(); }
static Types all_types() { return Types((1 << NUMBER_OF_TYPES) - 1); }
- explicit ToBooleanStub(Register tos, Types types = Types())
- : tos_(tos), types_(types) { }
+ explicit ToBooleanStub(Types types = Types())
+ : types_(types) { }
+ explicit ToBooleanStub(Code::ExtraICState state)
+ : types_(static_cast<byte>(state)) { }
- void Generate(MacroAssembler* masm);
+ bool Record(Handle<Object> object);
+ Types GetTypes() { return types_; }
+
+ virtual Handle<Code> GenerateCode();
+ virtual void InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor);
+
virtual Code::Kind GetCodeKind() const { return Code::TO_BOOLEAN_IC; }
virtual void PrintName(StringStream* stream);
virtual bool SometimesSetsUpAFrame() { return false; }
- private:
- Major MajorKey() { return ToBoolean; }
- int MinorKey() { return (tos_.code() << NUMBER_OF_TYPES) |
- types_.ToByte(); }
+ static void InitializeForIsolate(Isolate* isolate) {
+ ToBooleanStub stub;
+ stub.InitializeInterfaceDescriptor(
+ isolate,
+ isolate->code_stub_interface_descriptor(CodeStub::ToBoolean));
+ }
+
+ static Handle<Code> GetUninitialized(Isolate* isolate) {
+ return ToBooleanStub(UNINITIALIZED).GetCode(isolate);
+ }
- virtual void FinishCode(Handle<Code> code) {
- code->set_to_boolean_state(types_.ToByte());
+ virtual Code::ExtraICState GetExtraICState() {
+ return types_.ToIntegral();
}
- void CheckOddball(MacroAssembler* masm,
- Type type,
- Heap::RootListIndex value,
- bool result);
- void GenerateTypeTransition(MacroAssembler* masm);
+
+ private:
+ Major MajorKey() { return ToBoolean; }
+ int NotMissMinorKey() { return GetExtraICState(); }
+
+ explicit ToBooleanStub(InitializationState init_state) :
+ HydrogenCodeStub(init_state) {}
- Register tos_;
Types types_;
};
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Wed May 29 05:42:04
2013
+++ /branches/bleeding_edge/src/hydrogen-instructions.h Wed May 29 07:49:28
2013
@@ -1562,6 +1562,9 @@
}
explicit HBranch(HValue* value)
: HUnaryControlInstruction(value, NULL, NULL) { }
+ HBranch(HValue* value, ToBooleanStub::Types expected_input_types)
+ : HUnaryControlInstruction(value, NULL, NULL),
+ expected_input_types_(expected_input_types) { }
virtual Representation RequiredInputRepresentation(int index) {
=======================================
--- /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Fri May 24 04:44:55
2013
+++ /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Wed May 29 07:49:28
2013
@@ -180,6 +180,18 @@
ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate));
}
+void ToBooleanStub::InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor) {
+ static Register registers[] = { eax };
+ descriptor->register_param_count_ = 1;
+ descriptor->register_params_ = registers;
+ descriptor->deoptimization_handler_ =
+ FUNCTION_ADDR(ToBooleanIC_Miss);
+ descriptor->SetMissHandler(
+ ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate));
+}
+
#define __ ACCESS_MASM(masm)
@@ -467,116 +479,6 @@
__ bind(&gc);
__ TailCallRuntime(Runtime::kPushBlockContext, 2, 1);
}
-
-
-// The stub expects its argument on the stack and returns its result in
tos_:
-// zero for false, and a non-zero value for true.
-void ToBooleanStub::Generate(MacroAssembler* masm) {
- // This stub overrides SometimesSetsUpAFrame() to return false. That
means
- // we cannot call anything that could cause a GC from this stub.
- Label patch;
- Factory* factory = masm->isolate()->factory();
- const Register argument = eax;
- const Register map = edx;
-
- if (!types_.IsEmpty()) {
- __ mov(argument, Operand(esp, 1 * kPointerSize));
- }
-
- // undefined -> false
- CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false);
-
- // Boolean -> its value
- CheckOddball(masm, BOOLEAN, Heap::kFalseValueRootIndex, false);
- CheckOddball(masm, BOOLEAN, Heap::kTrueValueRootIndex, true);
-
- // 'null' -> false.
- CheckOddball(masm, NULL_TYPE, Heap::kNullValueRootIndex, false);
-
- if (types_.Contains(SMI)) {
- // Smis: 0 -> false, all other -> true
- Label not_smi;
- __ JumpIfNotSmi(argument, ¬_smi, Label::kNear);
- // argument contains the correct return value already.
- if (!tos_.is(argument)) {
- __ mov(tos_, argument);
- }
- __ ret(1 * kPointerSize);
- __ bind(¬_smi);
- } else if (types_.NeedsMap()) {
- // If we need a map later and have a Smi -> patch.
- __ JumpIfSmi(argument, &patch, Label::kNear);
- }
-
- if (types_.NeedsMap()) {
- __ mov(map, FieldOperand(argument, HeapObject::kMapOffset));
-
- if (types_.CanBeUndetectable()) {
- __ test_b(FieldOperand(map, Map::kBitFieldOffset),
- 1 << Map::kIsUndetectable);
- // Undetectable -> false.
- Label not_undetectable;
- __ j(zero, ¬_undetectable, Label::kNear);
- __ Set(tos_, Immediate(0));
- __ ret(1 * kPointerSize);
- __ bind(¬_undetectable);
- }
- }
-
- if (types_.Contains(SPEC_OBJECT)) {
- // spec object -> true.
- Label not_js_object;
- __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
- __ j(below, ¬_js_object, Label::kNear);
- // argument contains the correct return value already.
- if (!tos_.is(argument)) {
- __ Set(tos_, Immediate(1));
- }
- __ ret(1 * kPointerSize);
- __ bind(¬_js_object);
- }
-
- if (types_.Contains(STRING)) {
- // String value -> false iff empty.
- Label not_string;
- __ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
- __ j(above_equal, ¬_string, Label::kNear);
- __ mov(tos_, FieldOperand(argument, String::kLengthOffset));
- __ ret(1 * kPointerSize); // the string length is OK as the return
value
- __ bind(¬_string);
- }
-
- if (types_.Contains(SYMBOL)) {
- // Symbol value -> true.
- Label not_symbol;
- __ CmpInstanceType(map, SYMBOL_TYPE);
- __ j(not_equal, ¬_symbol, Label::kNear);
- __ bind(¬_symbol);
- }
-
- if (types_.Contains(HEAP_NUMBER)) {
- // heap number -> false iff +0, -0, or NaN.
- Label not_heap_number, false_result;
- __ cmp(map, factory->heap_number_map());
- __ j(not_equal, ¬_heap_number, Label::kNear);
- __ fldz();
- __ fld_d(FieldOperand(argument, HeapNumber::kValueOffset));
- __ FCmp();
- __ j(zero, &false_result, Label::kNear);
- // argument contains the correct return value already.
- if (!tos_.is(argument)) {
- __ Set(tos_, Immediate(1));
- }
- __ ret(1 * kPointerSize);
- __ bind(&false_result);
- __ Set(tos_, Immediate(0));
- __ ret(1 * kPointerSize);
- __ bind(¬_heap_number);
- }
-
- __ bind(&patch);
- GenerateTypeTransition(masm);
-}
void StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
@@ -612,44 +514,6 @@
__ popad();
__ ret(0);
}
-
-
-void ToBooleanStub::CheckOddball(MacroAssembler* masm,
- Type type,
- Heap::RootListIndex value,
- bool result) {
- const Register argument = eax;
- if (types_.Contains(type)) {
- // If we see an expected oddball, return its ToBoolean value tos_.
- Label different_value;
- __ CompareRoot(argument, value);
- __ j(not_equal, &different_value, Label::kNear);
- if (!result) {
- // If we have to return zero, there is no way around clearing tos_.
- __ Set(tos_, Immediate(0));
- } else if (!tos_.is(argument)) {
- // If we have to return non-zero, we can re-use the argument if it
is the
- // same register as the result, because we never see Smi-zero here.
- __ Set(tos_, Immediate(1));
- }
- __ ret(1 * kPointerSize);
- __ bind(&different_value);
- }
-}
-
-
-void ToBooleanStub::GenerateTypeTransition(MacroAssembler* masm) {
- __ pop(ecx); // Get return address, operand is now on top of stack.
- __ push(Immediate(Smi::FromInt(tos_.code())));
- __ push(Immediate(Smi::FromInt(types_.ToByte())));
- __ push(ecx); // Push return address.
- // Patch the caller to an appropriate specialized stub and return the
- // operation result to the caller of the stub.
- __ TailCallExternalReference(
- ExternalReference(IC_Utility(IC::kToBoolean_Patch), masm->isolate()),
- 3,
- 1);
-}
class FloatingPointHelper : public AllStatic {
=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Thu May 23
02:51:06 2013
+++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Wed May 29
07:49:28 2013
@@ -641,9 +641,8 @@
Label* if_true,
Label* if_false,
Label* fall_through) {
- ToBooleanStub stub(result_register());
- __ push(result_register());
- __ CallStub(&stub, condition->test_id());
+ Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
+ CallIC(ic, RelocInfo::CODE_TARGET, condition->test_id());
__ test(result_register(), result_register());
// The stub returns nonzero for true.
Split(not_zero, if_true, if_false, fall_through);
@@ -2003,9 +2002,8 @@
__ mov(ecx, isolate()->factory()->done_string()); // "done"
Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize();
CallIC(done_ic); // result.done in
eax
- ToBooleanStub stub(eax);
- __ push(eax);
- __ CallStub(&stub);
+ Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
+ CallIC(bool_ic);
__ test(eax, eax);
__ j(zero, &l_try);
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Wed May 29
03:47:55 2013
+++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Wed May 29
07:49:28 2013
@@ -2128,14 +2128,16 @@
void LCodeGen::DoBranch(LBranch* instr) {
int true_block = chunk_->LookupDestination(instr->true_block_id());
int false_block = chunk_->LookupDestination(instr->false_block_id());
- CpuFeatureScope scope(masm(), SSE2);
Representation r = instr->hydrogen()->value()->representation();
if (r.IsSmiOrInteger32()) {
+ ASSERT(!info()->IsStub());
Register reg = ToRegister(instr->value());
__ test(reg, Operand(reg));
EmitBranch(true_block, false_block, not_zero);
} else if (r.IsDouble()) {
+ ASSERT(!info()->IsStub());
+ CpuFeatureScope scope(masm(), SSE2);
XMMRegister reg = ToDoubleRegister(instr->value());
__ xorps(xmm0, xmm0);
__ ucomisd(reg, xmm0);
@@ -2145,9 +2147,11 @@
Register reg = ToRegister(instr->value());
HType type = instr->hydrogen()->value()->type();
if (type.IsBoolean()) {
+ ASSERT(!info()->IsStub());
__ cmp(reg, factory()->true_value());
EmitBranch(true_block, false_block, equal);
} else if (type.IsSmi()) {
+ ASSERT(!info()->IsStub());
__ test(reg, Operand(reg));
EmitBranch(true_block, false_block, not_equal);
} else {
@@ -2231,8 +2235,15 @@
__ cmp(FieldOperand(reg, HeapObject::kMapOffset),
factory()->heap_number_map());
__ j(not_equal, ¬_heap_number, Label::kNear);
- __ xorps(xmm0, xmm0);
- __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset));
+ if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
+ CpuFeatureScope scope(masm(), SSE2);
+ __ xorps(xmm0, xmm0);
+ __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset));
+ } else {
+ __ fldz();
+ __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset));
+ __ FCmp();
+ }
__ j(zero, false_label);
__ jmp(true_label);
__ bind(¬_heap_number);
=======================================
--- /branches/bleeding_edge/src/ic.cc Fri May 24 08:20:48 2013
+++ /branches/bleeding_edge/src/ic.cc Wed May 29 07:49:28 2013
@@ -2945,16 +2945,9 @@
} else {
code = stub.GetCode(isolate());
}
-
- patch(*code);
-
+ set_target(*code);
return DoCompareNilSlow(kind, nil, object);
}
-
-
-void CompareNilIC::patch(Code* code) {
- set_target(code);
-}
RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_Miss) {
@@ -2972,28 +2965,23 @@
}
-RUNTIME_FUNCTION(MaybeObject*, ToBoolean_Patch) {
- ASSERT(args.length() == 3);
-
- HandleScope scope(isolate);
- Handle<Object> object = args.at<Object>(0);
- Register tos = Register::from_code(args.smi_at(1));
- ToBooleanStub::Types old_types(args.smi_at(2));
-
- ToBooleanStub::Types new_types(old_types);
- bool to_boolean_value = new_types.Record(object);
- old_types.TraceTransition(new_types);
-
- ToBooleanStub stub(tos, new_types);
- Handle<Code> code = stub.GetCode(isolate);
- ToBooleanIC ic(isolate);
- ic.patch(*code);
+MaybeObject* ToBooleanIC::ToBoolean(Handle<Object> object,
+ Code::ExtraICState extra_ic_state) {
+ ToBooleanStub stub(extra_ic_state);
+ bool to_boolean_value = stub.Record(object);
+ Handle<Code> code = stub.GetCode(isolate());
+ set_target(*code);
return Smi::FromInt(to_boolean_value ? 1 : 0);
}
-void ToBooleanIC::patch(Code* code) {
- set_target(code);
+RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss) {
+ ASSERT(args.length() == 1);
+ HandleScope scope(isolate);
+ Handle<Object> object = args.at<Object>(0);
+ ToBooleanIC ic(isolate);
+ Code::ExtraICState ic_state = ic.target()->extended_extra_ic_state();
+ return ic.ToBoolean(object, ic_state);
}
=======================================
--- /branches/bleeding_edge/src/ic.h Fri May 24 04:44:55 2013
+++ /branches/bleeding_edge/src/ic.h Wed May 29 07:49:28 2013
@@ -62,7 +62,7 @@
ICU(CompareIC_Miss) \
ICU(CompareNilIC_Miss) \
ICU(Unreachable) \
- ICU(ToBoolean_Patch)
+ ICU(ToBooleanIC_Miss)
//
// IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC,
// and KeyedStoreIC.
@@ -789,8 +789,6 @@
static void Clear(Address address, Code* target);
- void patch(Code* code);
-
static MUST_USE_RESULT MaybeObject* DoCompareNilSlow(EqualityKind kind,
NilValue nil,
Handle<Object>
object);
@@ -799,9 +797,9 @@
class ToBooleanIC: public IC {
public:
- explicit ToBooleanIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
+ explicit ToBooleanIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) {
}
- void patch(Code* code);
+ MaybeObject* ToBoolean(Handle<Object> object, Code::ExtraICState state);
};
@@ -811,8 +809,8 @@
DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure);
DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure);
-DECLARE_RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_MissLight);
DECLARE_RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_Miss);
+DECLARE_RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss);
} } // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/isolate.cc Tue May 21 02:25:57 2013
+++ /branches/bleeding_edge/src/isolate.cc Wed May 29 07:49:28 2013
@@ -2245,6 +2245,7 @@
stub.InitializeInterfaceDescriptor(
this,
code_stub_interface_descriptor(CodeStub::FastCloneShallowArray));
CompareNilICStub::InitializeForIsolate(this);
+ ToBooleanStub::InitializeForIsolate(this);
ArrayConstructorStubBase::InstallDescriptors(this);
}
=======================================
--- /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc Wed May 29
05:09:03 2013
+++ /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc Wed May 29
07:49:28 2013
@@ -1873,9 +1873,11 @@
Representation r = instr->hydrogen()->value()->representation();
if (r.IsInteger32() || r.IsSmi()) {
+ ASSERT(!info()->IsStub());
Register reg = ToRegister(instr->value());
EmitBranch(true_block, false_block, ne, reg, Operand(zero_reg));
} else if (r.IsDouble()) {
+ ASSERT(!info()->IsStub());
DoubleRegister reg = ToDoubleRegister(instr->value());
// Test the double value. Zero and NaN are false.
EmitBranchF(true_block, false_block, nue, reg, kDoubleRegZero);
@@ -1884,9 +1886,11 @@
Register reg = ToRegister(instr->value());
HType type = instr->hydrogen()->value()->type();
if (type.IsBoolean()) {
+ ASSERT(!info()->IsStub());
__ LoadRoot(at, Heap::kTrueValueRootIndex);
EmitBranch(true_block, false_block, eq, reg, Operand(at));
} else if (type.IsSmi()) {
+ ASSERT(!info()->IsStub());
EmitBranch(true_block, false_block, ne, reg, Operand(zero_reg));
} else {
Label* true_label = chunk_->GetAssemblyLabel(true_block);
=======================================
--- /branches/bleeding_edge/src/objects-inl.h Thu May 23 04:30:24 2013
+++ /branches/bleeding_edge/src/objects-inl.h Wed May 29 07:49:28 2013
@@ -3729,6 +3729,7 @@
Code::ExtraICState Code::extended_extra_ic_state() {
ASSERT(is_inline_cache_stub() || ic_state() == DEBUG_STUB);
+ ASSERT(needs_extended_extra_ic_state(kind()));
return ExtractExtendedExtraICStateFromFlags(flags());
}
@@ -3979,17 +3980,7 @@
byte Code::to_boolean_state() {
- ASSERT(is_to_boolean_ic_stub());
- return ToBooleanStateField::decode(
- READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
-}
-
-
-void Code::set_to_boolean_state(byte value) {
- ASSERT(is_to_boolean_ic_stub());
- int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
- int updated = ToBooleanStateField::update(previous, value);
- WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
+ return extended_extra_ic_state();
}
@@ -4052,10 +4043,7 @@
| TypeField::encode(type)
| ExtendedExtraICStateField::encode(extra_ic_state)
| CacheHolderField::encode(holder);
- // TODO(danno): This is a bit of a hack right now since there are still
- // clients of this API that pass "extra" values in for argc. These
clients
- // should be retrofitted to used ExtendedExtraICState.
- if (kind != Code::COMPARE_NIL_IC) {
+ if (!Code::needs_extended_extra_ic_state(kind)) {
bits |= (argc << kArgumentsCountShift);
}
return static_cast<Flags>(bits);
=======================================
--- /branches/bleeding_edge/src/objects.h Thu May 23 04:30:24 2013
+++ /branches/bleeding_edge/src/objects.h Wed May 29 07:49:28 2013
@@ -4534,8 +4534,16 @@
inline Kind kind();
inline InlineCacheState ic_state(); // Only valid for IC stubs.
inline ExtraICState extra_ic_state(); // Only valid for IC stubs.
+
inline ExtraICState extended_extra_ic_state(); // Only valid for
// non-call IC stubs.
+ static bool needs_extended_extra_ic_state(Kind kind) {
+ // TODO(danno): This is a bit of a hack right now since there are still
+ // clients of this API that pass "extra" values in for argc. These
clients
+ // should be retrofitted to used ExtendedExtraICState.
+ return kind == COMPARE_NIL_IC || kind == TO_BOOLEAN_IC;
+ }
+
inline StubType type(); // Only valid for monomorphic IC stubs.
inline int arguments_count(); // Only valid for call IC stubs.
@@ -4628,7 +4636,6 @@
// [to_boolean_foo]: For kind TO_BOOLEAN_IC tells what state the stub is
in.
inline byte to_boolean_state();
- inline void set_to_boolean_state(byte value);
// [compare_nil]: For kind COMPARE_NIL_IC tells what state the stub is
in.
byte compare_nil_types();
@@ -4860,9 +4867,6 @@
static const int kUnaryOpTypeFirstBit =
kStackSlotsFirstBit + kStackSlotsBitCount;
static const int kUnaryOpTypeBitCount = 3;
- static const int kToBooleanStateFirstBit =
- kStackSlotsFirstBit + kStackSlotsBitCount;
- static const int kToBooleanStateBitCount = 8;
static const int kHasFunctionCacheFirstBit =
kStackSlotsFirstBit + kStackSlotsBitCount;
static const int kHasFunctionCacheBitCount = 1;
@@ -4872,7 +4876,6 @@
STATIC_ASSERT(kStackSlotsFirstBit + kStackSlotsBitCount <= 32);
STATIC_ASSERT(kUnaryOpTypeFirstBit + kUnaryOpTypeBitCount <= 32);
- STATIC_ASSERT(kToBooleanStateFirstBit + kToBooleanStateBitCount <= 32);
STATIC_ASSERT(kHasFunctionCacheFirstBit + kHasFunctionCacheBitCount <=
32);
STATIC_ASSERT(kMarkedForDeoptimizationFirstBit +
kMarkedForDeoptimizationBitCount <= 32);
@@ -4881,8 +4884,6 @@
kStackSlotsFirstBit, kStackSlotsBitCount> {}; // NOLINT
class UnaryOpTypeField: public BitField<int,
kUnaryOpTypeFirstBit, kUnaryOpTypeBitCount> {}; // NOLINT
- class ToBooleanStateField: public BitField<int,
- kToBooleanStateFirstBit, kToBooleanStateBitCount> {}; // NOLINT
class HasFunctionCacheField: public BitField<bool,
kHasFunctionCacheFirstBit, kHasFunctionCacheBitCount> {}; // NOLINT
class MarkedForDeoptimizationField: public BitField<bool,
=======================================
--- /branches/bleeding_edge/src/x64/code-stubs-x64.cc Fri May 24 04:44:55
2013
+++ /branches/bleeding_edge/src/x64/code-stubs-x64.cc Wed May 29 07:49:28
2013
@@ -173,6 +173,19 @@
descriptor->SetMissHandler(
ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate));
}
+
+
+void ToBooleanStub::InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor) {
+ static Register registers[] = { rax };
+ descriptor->register_param_count_ = 1;
+ descriptor->register_params_ = registers;
+ descriptor->deoptimization_handler_ =
+ FUNCTION_ADDR(ToBooleanIC_Miss);
+ descriptor->SetMissHandler(
+ ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate));
+}
#define __ ACCESS_MASM(masm)
@@ -460,106 +473,6 @@
__ bind(&gc);
__ TailCallRuntime(Runtime::kPushBlockContext, 2, 1);
}
-
-
-// The stub expects its argument on the stack and returns its result in
tos_:
-// zero for false, and a non-zero value for true.
-void ToBooleanStub::Generate(MacroAssembler* masm) {
- // This stub overrides SometimesSetsUpAFrame() to return false. That
means
- // we cannot call anything that could cause a GC from this stub.
- Label patch;
- const Register argument = rax;
- const Register map = rdx;
-
- if (!types_.IsEmpty()) {
- __ movq(argument, Operand(rsp, 1 * kPointerSize));
- }
-
- // undefined -> false
- CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false);
-
- // Boolean -> its value
- CheckOddball(masm, BOOLEAN, Heap::kFalseValueRootIndex, false);
- CheckOddball(masm, BOOLEAN, Heap::kTrueValueRootIndex, true);
-
- // 'null' -> false.
- CheckOddball(masm, NULL_TYPE, Heap::kNullValueRootIndex, false);
-
- if (types_.Contains(SMI)) {
- // Smis: 0 -> false, all other -> true
- Label not_smi;
- __ JumpIfNotSmi(argument, ¬_smi, Label::kNear);
- // argument contains the correct return value already
- if (!tos_.is(argument)) {
- __ movq(tos_, argument);
- }
- __ ret(1 * kPointerSize);
- __ bind(¬_smi);
- } else if (types_.NeedsMap()) {
- // If we need a map later and have a Smi -> patch.
- __ JumpIfSmi(argument, &patch, Label::kNear);
- }
-
- if (types_.NeedsMap()) {
- __ movq(map, FieldOperand(argument, HeapObject::kMapOffset));
-
- if (types_.CanBeUndetectable()) {
- __ testb(FieldOperand(map, Map::kBitFieldOffset),
- Immediate(1 << Map::kIsUndetectable));
- // Undetectable -> false.
- Label not_undetectable;
- __ j(zero, ¬_undetectable, Label::kNear);
- __ Set(tos_, 0);
- __ ret(1 * kPointerSize);
- __ bind(¬_undetectable);
- }
- }
-
- if (types_.Contains(SPEC_OBJECT)) {
- // spec object -> true.
- Label not_js_object;
- __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
- __ j(below, ¬_js_object, Label::kNear);
- // argument contains the correct return value already.
- if (!tos_.is(argument)) {
- __ Set(tos_, 1);
- }
- __ ret(1 * kPointerSize);
- __ bind(¬_js_object);
- }
-
- if (types_.Contains(STRING)) {
- // String value -> false iff empty.
- Label not_string;
- __ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
- __ j(above_equal, ¬_string, Label::kNear);
- __ movq(tos_, FieldOperand(argument, String::kLengthOffset));
- __ ret(1 * kPointerSize); // the string length is OK as the return
value
- __ bind(¬_string);
- }
-
- if (types_.Contains(HEAP_NUMBER)) {
- // heap number -> false iff +0, -0, or NaN.
- Label not_heap_number, false_result;
- __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
- __ j(not_equal, ¬_heap_number, Label::kNear);
- __ xorps(xmm0, xmm0);
- __ ucomisd(xmm0, FieldOperand(argument, HeapNumber::kValueOffset));
- __ j(zero, &false_result, Label::kNear);
- // argument contains the correct return value already.
- if (!tos_.is(argument)) {
- __ Set(tos_, 1);
- }
- __ ret(1 * kPointerSize);
- __ bind(&false_result);
- __ Set(tos_, 0);
- __ ret(1 * kPointerSize);
- __ bind(¬_heap_number);
- }
-
- __ bind(&patch);
- GenerateTypeTransition(masm);
-}
void StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
@@ -576,44 +489,6 @@
__ PopCallerSaved(save_doubles_);
__ ret(0);
}
-
-
-void ToBooleanStub::CheckOddball(MacroAssembler* masm,
- Type type,
- Heap::RootListIndex value,
- bool result) {
- const Register argument = rax;
- if (types_.Contains(type)) {
- // If we see an expected oddball, return its ToBoolean value tos_.
- Label different_value;
- __ CompareRoot(argument, value);
- __ j(not_equal, &different_value, Label::kNear);
- if (!result) {
- // If we have to return zero, there is no way around clearing tos_.
- __ Set(tos_, 0);
- } else if (!tos_.is(argument)) {
- // If we have to return non-zero, we can re-use the argument if it
is the
- // same register as the result, because we never see Smi-zero here.
- __ Set(tos_, 1);
- }
- __ ret(1 * kPointerSize);
- __ bind(&different_value);
- }
-}
-
-
-void ToBooleanStub::GenerateTypeTransition(MacroAssembler* masm) {
- __ pop(rcx); // Get return address, operand is now on top of stack.
- __ Push(Smi::FromInt(tos_.code()));
- __ Push(Smi::FromInt(types_.ToByte()));
- __ push(rcx); // Push return address.
- // Patch the caller to an appropriate specialized stub and return the
- // operation result to the caller of the stub.
- __ TailCallExternalReference(
- ExternalReference(IC_Utility(IC::kToBoolean_Patch), masm->isolate()),
- 3,
- 1);
-}
class FloatingPointHelper : public AllStatic {
=======================================
--- /branches/bleeding_edge/src/x64/full-codegen-x64.cc Thu May 23 02:51:06
2013
+++ /branches/bleeding_edge/src/x64/full-codegen-x64.cc Wed May 29 07:49:28
2013
@@ -652,9 +652,8 @@
Label* if_true,
Label* if_false,
Label* fall_through) {
- ToBooleanStub stub(result_register());
- __ push(result_register());
- __ CallStub(&stub, condition->test_id());
+ Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
+ CallIC(ic, RelocInfo::CODE_TARGET, condition->test_id());
__ testq(result_register(), result_register());
// The stub returns nonzero for true.
Split(not_zero, if_true, if_false, fall_through);
@@ -2028,10 +2027,9 @@
__ LoadRoot(rcx, Heap::kdone_stringRootIndex); // "done"
Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize();
CallIC(done_ic); // result.done in
rax
- ToBooleanStub stub(rax);
- __ push(rax);
- __ CallStub(&stub);
- __ testq(rax, rax);
+ Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
+ CallIC(bool_ic);
+ __ testq(result_register(), result_register());
__ j(zero, &l_try);
// result.value
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Wed May 29
03:47:55 2013
+++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Wed May 29
07:49:28 2013
@@ -1911,14 +1911,17 @@
Representation r = instr->hydrogen()->value()->representation();
if (r.IsInteger32()) {
+ ASSERT(!info()->IsStub());
Register reg = ToRegister(instr->value());
__ testl(reg, reg);
EmitBranch(true_block, false_block, not_zero);
} else if (r.IsSmi()) {
+ ASSERT(!info()->IsStub());
Register reg = ToRegister(instr->value());
__ testq(reg, reg);
EmitBranch(true_block, false_block, not_zero);
} else if (r.IsDouble()) {
+ ASSERT(!info()->IsStub());
XMMRegister reg = ToDoubleRegister(instr->value());
__ xorps(xmm0, xmm0);
__ ucomisd(reg, xmm0);
@@ -1928,9 +1931,11 @@
Register reg = ToRegister(instr->value());
HType type = instr->hydrogen()->value()->type();
if (type.IsBoolean()) {
+ ASSERT(!info()->IsStub());
__ CompareRoot(reg, Heap::kTrueValueRootIndex);
EmitBranch(true_block, false_block, equal);
} else if (type.IsSmi()) {
+ ASSERT(!info()->IsStub());
__ SmiCompare(reg, Smi::FromInt(0));
EmitBranch(true_block, false_block, not_equal);
} else {
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.