Index: src/code-stubs.cc |
diff --git a/src/code-stubs.cc b/src/code-stubs.cc |
index 346ef7517239f5650e30ed06e79a44f3d5f96641..2c4445f59ddf22316137d67c95693bdd3bb1e411 100644 |
--- a/src/code-stubs.cc |
+++ b/src/code-stubs.cc |
@@ -473,6 +473,144 @@ void StringLengthStub::GenerateAssembly( |
assembler->Return(result); |
} |
+void ToBooleanStub::GenerateAssembly( |
+ compiler::CodeStubAssembler* assembler) const { |
+ typedef compiler::Node Node; |
+ typedef compiler::CodeStubAssembler::Label Label; |
+ |
+ Node* value = assembler->Parameter(0); |
+ Label if_valueissmi(assembler), if_valueisnotsmi(assembler); |
+ |
+ // Check if {value} is a Smi or a HeapObject. |
+ assembler->Branch(assembler->WordIsSmi(value), &if_valueissmi, |
+ &if_valueisnotsmi); |
+ |
+ assembler->Bind(&if_valueissmi); |
+ { |
+ // The {value} is a Smi, only need to check against zero. |
+ Label if_valueiszero(assembler), if_valueisnotzero(assembler); |
+ assembler->Branch(assembler->SmiEqual(value, assembler->SmiConstant(0)), |
+ &if_valueiszero, &if_valueisnotzero); |
+ |
+ assembler->Bind(&if_valueiszero); |
+ assembler->Return(assembler->BooleanConstant(false)); |
+ |
+ assembler->Bind(&if_valueisnotzero); |
+ assembler->Return(assembler->BooleanConstant(true)); |
+ } |
+ |
+ assembler->Bind(&if_valueisnotsmi); |
+ { |
+ Label if_valueisstring(assembler), if_valueisheapnumber(assembler), |
+ if_valueisoddball(assembler), if_valueisother(assembler); |
+ |
+ // The {value} is a HeapObject, load its map. |
+ Node* value_map = assembler->LoadObjectField(value, HeapObject::kMapOffset); |
+ |
+ // Load the {value}s instance type. |
+ Node* value_instancetype = assembler->Load( |
+ MachineType::Uint8(), value_map, |
+ assembler->IntPtrConstant(Map::kInstanceTypeOffset - kHeapObjectTag)); |
+ |
+ // Dispatch based on the instance type; we distinguish all String instance |
+ // types, the HeapNumber type and the Oddball type. |
+ size_t const kNumCases = FIRST_NONSTRING_TYPE + 2; |
+ Label* case_labels[kNumCases]; |
+ int32_t case_values[kNumCases]; |
+ for (int32_t i = 0; i < FIRST_NONSTRING_TYPE; ++i) { |
+ case_labels[i] = new Label(assembler); |
+ case_values[i] = i; |
+ } |
+ case_labels[FIRST_NONSTRING_TYPE + 0] = &if_valueisheapnumber; |
+ case_values[FIRST_NONSTRING_TYPE + 0] = HEAP_NUMBER_TYPE; |
+ case_labels[FIRST_NONSTRING_TYPE + 1] = &if_valueisoddball; |
+ case_values[FIRST_NONSTRING_TYPE + 1] = ODDBALL_TYPE; |
+ assembler->Switch(value_instancetype, &if_valueisother, case_values, |
+ case_labels, arraysize(case_values)); |
+ for (int32_t i = 0; i < FIRST_NONSTRING_TYPE; ++i) { |
+ assembler->Bind(case_labels[i]); |
+ assembler->Goto(&if_valueisstring); |
+ delete case_labels[i]; |
+ } |
+ |
+ assembler->Bind(&if_valueisstring); |
+ { |
+ // Load the string length field of the {value}. |
+ Node* value_length = |
+ assembler->LoadObjectField(value, String::kLengthOffset); |
+ |
+ // Check if the {value} is the empty string. |
+ Label if_valueisempty(assembler), if_valueisnotempty(assembler); |
+ assembler->Branch( |
+ assembler->SmiEqual(value_length, assembler->SmiConstant(0)), |
+ &if_valueisempty, &if_valueisnotempty); |
+ |
+ assembler->Bind(&if_valueisempty); |
+ assembler->Return(assembler->BooleanConstant(false)); |
+ |
+ assembler->Bind(&if_valueisnotempty); |
+ assembler->Return(assembler->BooleanConstant(true)); |
+ } |
+ |
+ assembler->Bind(&if_valueisheapnumber); |
+ { |
+ Node* value_value = assembler->Load( |
+ MachineType::Float64(), value, |
+ assembler->IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag)); |
+ |
+ Label if_valueispositive(assembler), if_valueisnotpositive(assembler), |
+ if_valueisnegative(assembler), if_valueisnanorzero(assembler); |
+ assembler->Branch(assembler->Float64LessThan( |
+ assembler->Float64Constant(0.0), value_value), |
+ &if_valueispositive, &if_valueisnotpositive); |
+ |
+ assembler->Bind(&if_valueispositive); |
+ assembler->Return(assembler->BooleanConstant(true)); |
+ |
+ assembler->Bind(&if_valueisnotpositive); |
+ assembler->Branch(assembler->Float64LessThan( |
+ value_value, assembler->Float64Constant(0.0)), |
+ &if_valueisnegative, &if_valueisnanorzero); |
+ |
+ assembler->Bind(&if_valueisnegative); |
+ assembler->Return(assembler->BooleanConstant(true)); |
+ |
+ assembler->Bind(&if_valueisnanorzero); |
+ assembler->Return(assembler->BooleanConstant(false)); |
+ } |
+ |
+ assembler->Bind(&if_valueisoddball); |
+ { |
+ // The {value} is an Oddball, and every Oddball knows its boolean value. |
+ Node* value_toboolean = |
+ assembler->LoadObjectField(value, Oddball::kToBooleanOffset); |
+ assembler->Return(value_toboolean); |
+ } |
+ |
+ assembler->Bind(&if_valueisother); |
+ { |
+ Node* value_map_bitfield = assembler->Load( |
+ MachineType::Uint8(), value_map, |
+ assembler->IntPtrConstant(Map::kBitFieldOffset - kHeapObjectTag)); |
+ Node* value_map_undetectable = assembler->Word32And( |
+ value_map_bitfield, |
+ assembler->Int32Constant(1 << Map::kIsUndetectable)); |
+ |
+ // Check if the {value} is undetectable. |
+ Label if_valueisundetectable(assembler), |
+ if_valueisnotundetectable(assembler); |
+ assembler->Branch(assembler->Word32Equal(value_map_undetectable, |
+ assembler->Int32Constant(0)), |
+ &if_valueisnotundetectable, &if_valueisundetectable); |
+ |
+ assembler->Bind(&if_valueisundetectable); |
+ assembler->Return(assembler->BooleanConstant(false)); |
+ |
+ assembler->Bind(&if_valueisnotundetectable); |
+ assembler->Return(assembler->BooleanConstant(true)); |
+ } |
+ } |
+} |
template<class StateType> |
void HydrogenCodeStub::TraceTransition(StateType from, StateType to) { |
@@ -667,8 +805,7 @@ void AllocateInNewSpaceStub::InitializeDescriptor( |
descriptor->Initialize(); |
} |
- |
-void ToBooleanStub::InitializeDescriptor(CodeStubDescriptor* descriptor) { |
+void ToBooleanICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) { |
descriptor->Initialize(FUNCTION_ADDR(Runtime_ToBooleanIC_Miss)); |
descriptor->SetMissHandler(ExternalReference( |
Runtime::FunctionForId(Runtime::kToBooleanIC_Miss), isolate())); |
@@ -770,8 +907,7 @@ std::ostream& ArrayConstructorStubBase::BasePrintName( |
return os; |
} |
- |
-bool ToBooleanStub::UpdateStatus(Handle<Object> object) { |
+bool ToBooleanICStub::UpdateStatus(Handle<Object> object) { |
Types new_types = types(); |
Types old_types = new_types; |
bool to_boolean_value = new_types.UpdateStatus(object); |
@@ -780,30 +916,27 @@ bool ToBooleanStub::UpdateStatus(Handle<Object> object) { |
return to_boolean_value; |
} |
- |
-void ToBooleanStub::PrintState(std::ostream& os) const { // NOLINT |
+void ToBooleanICStub::PrintState(std::ostream& os) const { // NOLINT |
os << types(); |
} |
- |
-std::ostream& operator<<(std::ostream& os, const ToBooleanStub::Types& s) { |
+std::ostream& operator<<(std::ostream& os, const ToBooleanICStub::Types& s) { |
os << "("; |
SimpleListPrinter p(os); |
if (s.IsEmpty()) p.Add("None"); |
- if (s.Contains(ToBooleanStub::UNDEFINED)) p.Add("Undefined"); |
- if (s.Contains(ToBooleanStub::BOOLEAN)) p.Add("Bool"); |
- if (s.Contains(ToBooleanStub::NULL_TYPE)) p.Add("Null"); |
- if (s.Contains(ToBooleanStub::SMI)) p.Add("Smi"); |
- if (s.Contains(ToBooleanStub::SPEC_OBJECT)) p.Add("SpecObject"); |
- if (s.Contains(ToBooleanStub::STRING)) p.Add("String"); |
- if (s.Contains(ToBooleanStub::SYMBOL)) p.Add("Symbol"); |
- if (s.Contains(ToBooleanStub::HEAP_NUMBER)) p.Add("HeapNumber"); |
- if (s.Contains(ToBooleanStub::SIMD_VALUE)) p.Add("SimdValue"); |
+ if (s.Contains(ToBooleanICStub::UNDEFINED)) p.Add("Undefined"); |
+ if (s.Contains(ToBooleanICStub::BOOLEAN)) p.Add("Bool"); |
+ if (s.Contains(ToBooleanICStub::NULL_TYPE)) p.Add("Null"); |
+ if (s.Contains(ToBooleanICStub::SMI)) p.Add("Smi"); |
+ if (s.Contains(ToBooleanICStub::SPEC_OBJECT)) p.Add("SpecObject"); |
+ if (s.Contains(ToBooleanICStub::STRING)) p.Add("String"); |
+ if (s.Contains(ToBooleanICStub::SYMBOL)) p.Add("Symbol"); |
+ if (s.Contains(ToBooleanICStub::HEAP_NUMBER)) p.Add("HeapNumber"); |
+ if (s.Contains(ToBooleanICStub::SIMD_VALUE)) p.Add("SimdValue"); |
return os << ")"; |
} |
- |
-bool ToBooleanStub::Types::UpdateStatus(Handle<Object> object) { |
+bool ToBooleanICStub::Types::UpdateStatus(Handle<Object> object) { |
if (object->IsUndefined()) { |
Add(UNDEFINED); |
return false; |
@@ -841,12 +974,12 @@ bool ToBooleanStub::Types::UpdateStatus(Handle<Object> object) { |
} |
} |
- |
-bool ToBooleanStub::Types::NeedsMap() const { |
- return Contains(ToBooleanStub::SPEC_OBJECT) || |
- Contains(ToBooleanStub::STRING) || Contains(ToBooleanStub::SYMBOL) || |
- Contains(ToBooleanStub::HEAP_NUMBER) || |
- Contains(ToBooleanStub::SIMD_VALUE); |
+bool ToBooleanICStub::Types::NeedsMap() const { |
+ return Contains(ToBooleanICStub::SPEC_OBJECT) || |
+ Contains(ToBooleanICStub::STRING) || |
+ Contains(ToBooleanICStub::SYMBOL) || |
+ Contains(ToBooleanICStub::HEAP_NUMBER) || |
+ Contains(ToBooleanICStub::SIMD_VALUE); |
} |