aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/code-stubs.cc
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2017-02-14 11:27:26 +0100
committerMichaël Zasso <targos@protonmail.com>2017-02-22 15:55:42 +0100
commit7a77daf24344db7942e34c962b0f1ee729ab7af5 (patch)
treee7cbe7bf4e2f4b802a8f5bc18336c546cd6a0d7f /deps/v8/src/code-stubs.cc
parent5f08871ee93ea739148cc49e0f7679e33c70295a (diff)
downloadandroid-node-v8-7a77daf24344db7942e34c962b0f1ee729ab7af5.tar.gz
android-node-v8-7a77daf24344db7942e34c962b0f1ee729ab7af5.tar.bz2
android-node-v8-7a77daf24344db7942e34c962b0f1ee729ab7af5.zip
deps: update V8 to 5.6.326.55
PR-URL: https://github.com/nodejs/node/pull/10992 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps/v8/src/code-stubs.cc')
-rw-r--r--deps/v8/src/code-stubs.cc3696
1 files changed, 542 insertions, 3154 deletions
diff --git a/deps/v8/src/code-stubs.cc b/deps/v8/src/code-stubs.cc
index b899943e98..2ee5ece8da 100644
--- a/deps/v8/src/code-stubs.cc
+++ b/deps/v8/src/code-stubs.cc
@@ -22,7 +22,7 @@ namespace internal {
RUNTIME_FUNCTION(UnexpectedStubMiss) {
FATAL("Unexpected deopt of a stub");
- return Smi::FromInt(0);
+ return Smi::kZero;
}
CodeStubDescriptor::CodeStubDescriptor(CodeStub* stub)
@@ -318,33 +318,42 @@ void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(
}
}
-
-std::ostream& operator<<(std::ostream& os, const StringAddFlags& flags) {
- switch (flags) {
- case STRING_ADD_CHECK_NONE:
- return os << "CheckNone";
- case STRING_ADD_CHECK_LEFT:
- return os << "CheckLeft";
- case STRING_ADD_CHECK_RIGHT:
- return os << "CheckRight";
- case STRING_ADD_CHECK_BOTH:
- return os << "CheckBoth";
- case STRING_ADD_CONVERT_LEFT:
- return os << "ConvertLeft";
- case STRING_ADD_CONVERT_RIGHT:
- return os << "ConvertRight";
- case STRING_ADD_CONVERT:
- break;
- }
- UNREACHABLE();
- return os;
-}
-
-
void StringAddStub::PrintBaseName(std::ostream& os) const { // NOLINT
os << "StringAddStub_" << flags() << "_" << pretenure_flag();
}
+void StringAddStub::GenerateAssembly(CodeStubAssembler* assembler) const {
+ typedef compiler::Node Node;
+ Node* left = assembler->Parameter(Descriptor::kLeft);
+ Node* right = assembler->Parameter(Descriptor::kRight);
+ Node* context = assembler->Parameter(Descriptor::kContext);
+
+ if ((flags() & STRING_ADD_CHECK_LEFT) != 0) {
+ DCHECK((flags() & STRING_ADD_CONVERT) != 0);
+ // TODO(danno): The ToString and JSReceiverToPrimitive below could be
+ // combined to avoid duplicate smi and instance type checks.
+ left = assembler->ToString(context,
+ assembler->JSReceiverToPrimitive(context, left));
+ }
+ if ((flags() & STRING_ADD_CHECK_RIGHT) != 0) {
+ DCHECK((flags() & STRING_ADD_CONVERT) != 0);
+ // TODO(danno): The ToString and JSReceiverToPrimitive below could be
+ // combined to avoid duplicate smi and instance type checks.
+ right = assembler->ToString(
+ context, assembler->JSReceiverToPrimitive(context, right));
+ }
+
+ if ((flags() & STRING_ADD_CHECK_BOTH) == 0) {
+ CodeStubAssembler::AllocationFlag flags =
+ (pretenure_flag() == TENURED) ? CodeStubAssembler::kPretenured
+ : CodeStubAssembler::kNone;
+ assembler->Return(assembler->StringAdd(context, left, right, flags));
+ } else {
+ Callable callable = CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE,
+ pretenure_flag());
+ assembler->TailCallStub(callable, context, left, right);
+ }
+}
InlineCacheState CompareICStub::GetICState() const {
CompareICState::State state = Max(left(), right());
@@ -411,7 +420,7 @@ void CompareICStub::Generate(MacroAssembler* masm) {
Handle<Code> TurboFanCodeStub::GenerateCode() {
const char* name = CodeStub::MajorName(MajorKey());
- Zone zone(isolate()->allocator());
+ Zone zone(isolate()->allocator(), ZONE_NAME);
CallInterfaceDescriptor descriptor(GetCallInterfaceDescriptor());
CodeStubAssembler assembler(isolate(), &zone, descriptor, GetCodeFlags(),
name);
@@ -419,7 +428,7 @@ Handle<Code> TurboFanCodeStub::GenerateCode() {
return assembler.GenerateCode();
}
-void LoadICTrampolineTFStub::GenerateAssembly(
+void LoadICTrampolineStub::GenerateAssembly(
CodeStubAssembler* assembler) const {
typedef compiler::Node Node;
@@ -433,7 +442,7 @@ void LoadICTrampolineTFStub::GenerateAssembly(
assembler->LoadIC(&p);
}
-void LoadICTFStub::GenerateAssembly(CodeStubAssembler* assembler) const {
+void LoadICStub::GenerateAssembly(CodeStubAssembler* assembler) const {
typedef compiler::Node Node;
Node* receiver = assembler->Parameter(Descriptor::kReceiver);
@@ -446,6 +455,21 @@ void LoadICTFStub::GenerateAssembly(CodeStubAssembler* assembler) const {
assembler->LoadIC(&p);
}
+void LoadICProtoArrayStub::GenerateAssembly(
+ CodeStubAssembler* assembler) const {
+ typedef compiler::Node Node;
+
+ Node* receiver = assembler->Parameter(Descriptor::kReceiver);
+ Node* name = assembler->Parameter(Descriptor::kName);
+ Node* slot = assembler->Parameter(Descriptor::kSlot);
+ Node* vector = assembler->Parameter(Descriptor::kVector);
+ Node* handler = assembler->Parameter(Descriptor::kHandler);
+ Node* context = assembler->Parameter(Descriptor::kContext);
+
+ CodeStubAssembler::LoadICParameters p(context, receiver, name, slot, vector);
+ assembler->LoadICProtoArray(&p, handler);
+}
+
void LoadGlobalICTrampolineStub::GenerateAssembly(
CodeStubAssembler* assembler) const {
typedef compiler::Node Node;
@@ -498,7 +522,7 @@ void KeyedLoadICTFStub::GenerateAssembly(CodeStubAssembler* assembler) const {
assembler->KeyedLoadIC(&p);
}
-void StoreICTrampolineTFStub::GenerateAssembly(
+void StoreICTrampolineStub::GenerateAssembly(
CodeStubAssembler* assembler) const {
typedef compiler::Node Node;
@@ -514,7 +538,7 @@ void StoreICTrampolineTFStub::GenerateAssembly(
assembler->StoreIC(&p);
}
-void StoreICTFStub::GenerateAssembly(CodeStubAssembler* assembler) const {
+void StoreICStub::GenerateAssembly(CodeStubAssembler* assembler) const {
typedef compiler::Node Node;
Node* receiver = assembler->Parameter(Descriptor::kReceiver);
@@ -529,6 +553,37 @@ void StoreICTFStub::GenerateAssembly(CodeStubAssembler* assembler) const {
assembler->StoreIC(&p);
}
+void KeyedStoreICTrampolineTFStub::GenerateAssembly(
+ CodeStubAssembler* assembler) const {
+ typedef compiler::Node Node;
+
+ Node* receiver = assembler->Parameter(Descriptor::kReceiver);
+ Node* name = assembler->Parameter(Descriptor::kName);
+ Node* value = assembler->Parameter(Descriptor::kValue);
+ Node* slot = assembler->Parameter(Descriptor::kSlot);
+ Node* context = assembler->Parameter(Descriptor::kContext);
+ Node* vector = assembler->LoadTypeFeedbackVectorForStub();
+
+ CodeStubAssembler::StoreICParameters p(context, receiver, name, value, slot,
+ vector);
+ assembler->KeyedStoreIC(&p, StoreICState::GetLanguageMode(GetExtraICState()));
+}
+
+void KeyedStoreICTFStub::GenerateAssembly(CodeStubAssembler* assembler) const {
+ typedef compiler::Node Node;
+
+ Node* receiver = assembler->Parameter(Descriptor::kReceiver);
+ Node* name = assembler->Parameter(Descriptor::kName);
+ Node* value = assembler->Parameter(Descriptor::kValue);
+ Node* slot = assembler->Parameter(Descriptor::kSlot);
+ Node* vector = assembler->Parameter(Descriptor::kVector);
+ Node* context = assembler->Parameter(Descriptor::kContext);
+
+ CodeStubAssembler::StoreICParameters p(context, receiver, name, value, slot,
+ vector);
+ assembler->KeyedStoreIC(&p, StoreICState::GetLanguageMode(GetExtraICState()));
+}
+
void StoreMapStub::GenerateAssembly(CodeStubAssembler* assembler) const {
typedef compiler::Node Node;
@@ -662,368 +717,6 @@ void StringLengthStub::GenerateAssembly(CodeStubAssembler* assembler) const {
}
// static
-compiler::Node* AddStub::Generate(CodeStubAssembler* assembler,
- compiler::Node* left, compiler::Node* right,
- compiler::Node* context) {
- typedef CodeStubAssembler::Label Label;
- typedef compiler::Node Node;
- typedef CodeStubAssembler::Variable Variable;
-
- // Shared entry for floating point addition.
- Label do_fadd(assembler);
- Variable var_fadd_lhs(assembler, MachineRepresentation::kFloat64),
- var_fadd_rhs(assembler, MachineRepresentation::kFloat64);
-
- // We might need to loop several times due to ToPrimitive, ToString and/or
- // ToNumber conversions.
- Variable var_lhs(assembler, MachineRepresentation::kTagged),
- var_rhs(assembler, MachineRepresentation::kTagged),
- var_result(assembler, MachineRepresentation::kTagged);
- Variable* loop_vars[2] = {&var_lhs, &var_rhs};
- Label loop(assembler, 2, loop_vars), end(assembler),
- string_add_convert_left(assembler, Label::kDeferred),
- string_add_convert_right(assembler, Label::kDeferred);
- var_lhs.Bind(left);
- var_rhs.Bind(right);
- assembler->Goto(&loop);
- assembler->Bind(&loop);
- {
- // Load the current {lhs} and {rhs} values.
- Node* lhs = var_lhs.value();
- Node* rhs = var_rhs.value();
-
- // Check if the {lhs} is a Smi or a HeapObject.
- Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler);
- assembler->Branch(assembler->WordIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi);
-
- assembler->Bind(&if_lhsissmi);
- {
- // Check if the {rhs} is also a Smi.
- Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler);
- assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi,
- &if_rhsisnotsmi);
-
- assembler->Bind(&if_rhsissmi);
- {
- // Try fast Smi addition first.
- Node* pair = assembler->SmiAddWithOverflow(lhs, rhs);
- Node* overflow = assembler->Projection(1, pair);
-
- // Check if the Smi additon overflowed.
- Label if_overflow(assembler), if_notoverflow(assembler);
- assembler->Branch(overflow, &if_overflow, &if_notoverflow);
-
- assembler->Bind(&if_overflow);
- {
- var_fadd_lhs.Bind(assembler->SmiToFloat64(lhs));
- var_fadd_rhs.Bind(assembler->SmiToFloat64(rhs));
- assembler->Goto(&do_fadd);
- }
-
- assembler->Bind(&if_notoverflow);
- var_result.Bind(assembler->Projection(0, pair));
- assembler->Goto(&end);
- }
-
- assembler->Bind(&if_rhsisnotsmi);
- {
- // Load the map of {rhs}.
- Node* rhs_map = assembler->LoadMap(rhs);
-
- // Check if the {rhs} is a HeapNumber.
- Label if_rhsisnumber(assembler),
- if_rhsisnotnumber(assembler, Label::kDeferred);
- assembler->Branch(assembler->IsHeapNumberMap(rhs_map), &if_rhsisnumber,
- &if_rhsisnotnumber);
-
- assembler->Bind(&if_rhsisnumber);
- {
- var_fadd_lhs.Bind(assembler->SmiToFloat64(lhs));
- var_fadd_rhs.Bind(assembler->LoadHeapNumberValue(rhs));
- assembler->Goto(&do_fadd);
- }
-
- assembler->Bind(&if_rhsisnotnumber);
- {
- // Load the instance type of {rhs}.
- Node* rhs_instance_type = assembler->LoadMapInstanceType(rhs_map);
-
- // Check if the {rhs} is a String.
- Label if_rhsisstring(assembler, Label::kDeferred),
- if_rhsisnotstring(assembler, Label::kDeferred);
- assembler->Branch(assembler->IsStringInstanceType(rhs_instance_type),
- &if_rhsisstring, &if_rhsisnotstring);
-
- assembler->Bind(&if_rhsisstring);
- {
- var_lhs.Bind(lhs);
- var_rhs.Bind(rhs);
- assembler->Goto(&string_add_convert_left);
- }
-
- assembler->Bind(&if_rhsisnotstring);
- {
- // Check if {rhs} is a JSReceiver.
- Label if_rhsisreceiver(assembler, Label::kDeferred),
- if_rhsisnotreceiver(assembler, Label::kDeferred);
- assembler->Branch(
- assembler->IsJSReceiverInstanceType(rhs_instance_type),
- &if_rhsisreceiver, &if_rhsisnotreceiver);
-
- assembler->Bind(&if_rhsisreceiver);
- {
- // Convert {rhs} to a primitive first passing no hint.
- Callable callable =
- CodeFactory::NonPrimitiveToPrimitive(assembler->isolate());
- var_rhs.Bind(assembler->CallStub(callable, context, rhs));
- assembler->Goto(&loop);
- }
-
- assembler->Bind(&if_rhsisnotreceiver);
- {
- // Convert {rhs} to a Number first.
- Callable callable =
- CodeFactory::NonNumberToNumber(assembler->isolate());
- var_rhs.Bind(assembler->CallStub(callable, context, rhs));
- assembler->Goto(&loop);
- }
- }
- }
- }
- }
-
- assembler->Bind(&if_lhsisnotsmi);
- {
- // Load the map and instance type of {lhs}.
- Node* lhs_instance_type = assembler->LoadInstanceType(lhs);
-
- // Check if {lhs} is a String.
- Label if_lhsisstring(assembler), if_lhsisnotstring(assembler);
- assembler->Branch(assembler->IsStringInstanceType(lhs_instance_type),
- &if_lhsisstring, &if_lhsisnotstring);
-
- assembler->Bind(&if_lhsisstring);
- {
- var_lhs.Bind(lhs);
- var_rhs.Bind(rhs);
- assembler->Goto(&string_add_convert_right);
- }
-
- assembler->Bind(&if_lhsisnotstring);
- {
- // Check if {rhs} is a Smi.
- Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler);
- assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi,
- &if_rhsisnotsmi);
-
- assembler->Bind(&if_rhsissmi);
- {
- // Check if {lhs} is a Number.
- Label if_lhsisnumber(assembler),
- if_lhsisnotnumber(assembler, Label::kDeferred);
- assembler->Branch(assembler->Word32Equal(
- lhs_instance_type,
- assembler->Int32Constant(HEAP_NUMBER_TYPE)),
- &if_lhsisnumber, &if_lhsisnotnumber);
-
- assembler->Bind(&if_lhsisnumber);
- {
- // The {lhs} is a HeapNumber, the {rhs} is a Smi, just add them.
- var_fadd_lhs.Bind(assembler->LoadHeapNumberValue(lhs));
- var_fadd_rhs.Bind(assembler->SmiToFloat64(rhs));
- assembler->Goto(&do_fadd);
- }
-
- assembler->Bind(&if_lhsisnotnumber);
- {
- // The {lhs} is neither a Number nor a String, and the {rhs} is a
- // Smi.
- Label if_lhsisreceiver(assembler, Label::kDeferred),
- if_lhsisnotreceiver(assembler, Label::kDeferred);
- assembler->Branch(
- assembler->IsJSReceiverInstanceType(lhs_instance_type),
- &if_lhsisreceiver, &if_lhsisnotreceiver);
-
- assembler->Bind(&if_lhsisreceiver);
- {
- // Convert {lhs} to a primitive first passing no hint.
- Callable callable =
- CodeFactory::NonPrimitiveToPrimitive(assembler->isolate());
- var_lhs.Bind(assembler->CallStub(callable, context, lhs));
- assembler->Goto(&loop);
- }
-
- assembler->Bind(&if_lhsisnotreceiver);
- {
- // Convert {lhs} to a Number first.
- Callable callable =
- CodeFactory::NonNumberToNumber(assembler->isolate());
- var_lhs.Bind(assembler->CallStub(callable, context, lhs));
- assembler->Goto(&loop);
- }
- }
- }
-
- assembler->Bind(&if_rhsisnotsmi);
- {
- // Load the instance type of {rhs}.
- Node* rhs_instance_type = assembler->LoadInstanceType(rhs);
-
- // Check if {rhs} is a String.
- Label if_rhsisstring(assembler), if_rhsisnotstring(assembler);
- assembler->Branch(assembler->IsStringInstanceType(rhs_instance_type),
- &if_rhsisstring, &if_rhsisnotstring);
-
- assembler->Bind(&if_rhsisstring);
- {
- var_lhs.Bind(lhs);
- var_rhs.Bind(rhs);
- assembler->Goto(&string_add_convert_left);
- }
-
- assembler->Bind(&if_rhsisnotstring);
- {
- // Check if {lhs} is a HeapNumber.
- Label if_lhsisnumber(assembler), if_lhsisnotnumber(assembler);
- assembler->Branch(assembler->Word32Equal(
- lhs_instance_type,
- assembler->Int32Constant(HEAP_NUMBER_TYPE)),
- &if_lhsisnumber, &if_lhsisnotnumber);
-
- assembler->Bind(&if_lhsisnumber);
- {
- // Check if {rhs} is also a HeapNumber.
- Label if_rhsisnumber(assembler),
- if_rhsisnotnumber(assembler, Label::kDeferred);
- assembler->Branch(assembler->Word32Equal(
- rhs_instance_type,
- assembler->Int32Constant(HEAP_NUMBER_TYPE)),
- &if_rhsisnumber, &if_rhsisnotnumber);
-
- assembler->Bind(&if_rhsisnumber);
- {
- // Perform a floating point addition.
- var_fadd_lhs.Bind(assembler->LoadHeapNumberValue(lhs));
- var_fadd_rhs.Bind(assembler->LoadHeapNumberValue(rhs));
- assembler->Goto(&do_fadd);
- }
-
- assembler->Bind(&if_rhsisnotnumber);
- {
- // Check if {rhs} is a JSReceiver.
- Label if_rhsisreceiver(assembler, Label::kDeferred),
- if_rhsisnotreceiver(assembler, Label::kDeferred);
- assembler->Branch(
- assembler->IsJSReceiverInstanceType(rhs_instance_type),
- &if_rhsisreceiver, &if_rhsisnotreceiver);
-
- assembler->Bind(&if_rhsisreceiver);
- {
- // Convert {rhs} to a primitive first passing no hint.
- Callable callable = CodeFactory::NonPrimitiveToPrimitive(
- assembler->isolate());
- var_rhs.Bind(assembler->CallStub(callable, context, rhs));
- assembler->Goto(&loop);
- }
-
- assembler->Bind(&if_rhsisnotreceiver);
- {
- // Convert {rhs} to a Number first.
- Callable callable =
- CodeFactory::NonNumberToNumber(assembler->isolate());
- var_rhs.Bind(assembler->CallStub(callable, context, rhs));
- assembler->Goto(&loop);
- }
- }
- }
-
- assembler->Bind(&if_lhsisnotnumber);
- {
- // Check if {lhs} is a JSReceiver.
- Label if_lhsisreceiver(assembler, Label::kDeferred),
- if_lhsisnotreceiver(assembler);
- assembler->Branch(
- assembler->IsJSReceiverInstanceType(lhs_instance_type),
- &if_lhsisreceiver, &if_lhsisnotreceiver);
-
- assembler->Bind(&if_lhsisreceiver);
- {
- // Convert {lhs} to a primitive first passing no hint.
- Callable callable =
- CodeFactory::NonPrimitiveToPrimitive(assembler->isolate());
- var_lhs.Bind(assembler->CallStub(callable, context, lhs));
- assembler->Goto(&loop);
- }
-
- assembler->Bind(&if_lhsisnotreceiver);
- {
- // Check if {rhs} is a JSReceiver.
- Label if_rhsisreceiver(assembler, Label::kDeferred),
- if_rhsisnotreceiver(assembler, Label::kDeferred);
- assembler->Branch(
- assembler->IsJSReceiverInstanceType(rhs_instance_type),
- &if_rhsisreceiver, &if_rhsisnotreceiver);
-
- assembler->Bind(&if_rhsisreceiver);
- {
- // Convert {rhs} to a primitive first passing no hint.
- Callable callable = CodeFactory::NonPrimitiveToPrimitive(
- assembler->isolate());
- var_rhs.Bind(assembler->CallStub(callable, context, rhs));
- assembler->Goto(&loop);
- }
-
- assembler->Bind(&if_rhsisnotreceiver);
- {
- // Convert {lhs} to a Number first.
- Callable callable =
- CodeFactory::NonNumberToNumber(assembler->isolate());
- var_lhs.Bind(assembler->CallStub(callable, context, lhs));
- assembler->Goto(&loop);
- }
- }
- }
- }
- }
- }
- }
- }
- assembler->Bind(&string_add_convert_left);
- {
- // Convert {lhs}, which is a Smi, to a String and concatenate the
- // resulting string with the String {rhs}.
- Callable callable = CodeFactory::StringAdd(
- assembler->isolate(), STRING_ADD_CONVERT_LEFT, NOT_TENURED);
- var_result.Bind(assembler->CallStub(callable, context, var_lhs.value(),
- var_rhs.value()));
- assembler->Goto(&end);
- }
-
- assembler->Bind(&string_add_convert_right);
- {
- // Convert {lhs}, which is a Smi, to a String and concatenate the
- // resulting string with the String {rhs}.
- Callable callable = CodeFactory::StringAdd(
- assembler->isolate(), STRING_ADD_CONVERT_RIGHT, NOT_TENURED);
- var_result.Bind(assembler->CallStub(callable, context, var_lhs.value(),
- var_rhs.value()));
- assembler->Goto(&end);
- }
-
- assembler->Bind(&do_fadd);
- {
- Node* lhs_value = var_fadd_lhs.value();
- Node* rhs_value = var_fadd_rhs.value();
- Node* value = assembler->Float64Add(lhs_value, rhs_value);
- Node* result = assembler->ChangeFloat64ToTagged(value);
- var_result.Bind(result);
- assembler->Goto(&end);
- }
- assembler->Bind(&end);
- return var_result.value();
-}
-
-// static
compiler::Node* AddWithFeedbackStub::Generate(
CodeStubAssembler* assembler, compiler::Node* lhs, compiler::Node* rhs,
compiler::Node* slot_id, compiler::Node* type_feedback_vector,
@@ -1033,8 +726,10 @@ compiler::Node* AddWithFeedbackStub::Generate(
typedef CodeStubAssembler::Variable Variable;
// Shared entry for floating point addition.
- Label do_fadd(assembler), end(assembler),
- do_add_any(assembler, Label::kDeferred), call_add_stub(assembler);
+ Label do_fadd(assembler), if_lhsisnotnumber(assembler, Label::kDeferred),
+ check_rhsisoddball(assembler, Label::kDeferred),
+ call_with_oddball_feedback(assembler), call_with_any_feedback(assembler),
+ call_add_stub(assembler), end(assembler);
Variable var_fadd_lhs(assembler, MachineRepresentation::kFloat64),
var_fadd_rhs(assembler, MachineRepresentation::kFloat64),
var_type_feedback(assembler, MachineRepresentation::kWord32),
@@ -1042,18 +737,21 @@ compiler::Node* AddWithFeedbackStub::Generate(
// Check if the {lhs} is a Smi or a HeapObject.
Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler);
- assembler->Branch(assembler->WordIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi);
+ assembler->Branch(assembler->TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi);
assembler->Bind(&if_lhsissmi);
{
// Check if the {rhs} is also a Smi.
Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler);
- assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
+ assembler->Branch(assembler->TaggedIsSmi(rhs), &if_rhsissmi,
+ &if_rhsisnotsmi);
assembler->Bind(&if_rhsissmi);
{
// Try fast Smi addition first.
- Node* pair = assembler->SmiAddWithOverflow(lhs, rhs);
+ Node* pair =
+ assembler->IntPtrAddWithOverflow(assembler->BitcastTaggedToWord(lhs),
+ assembler->BitcastTaggedToWord(rhs));
Node* overflow = assembler->Projection(1, pair);
// Check if the Smi additon overflowed.
@@ -1071,7 +769,8 @@ compiler::Node* AddWithFeedbackStub::Generate(
{
var_type_feedback.Bind(
assembler->Int32Constant(BinaryOperationFeedback::kSignedSmall));
- var_result.Bind(assembler->Projection(0, pair));
+ var_result.Bind(assembler->BitcastWordToTaggedSigned(
+ assembler->Projection(0, pair)));
assembler->Goto(&end);
}
}
@@ -1082,7 +781,8 @@ compiler::Node* AddWithFeedbackStub::Generate(
Node* rhs_map = assembler->LoadMap(rhs);
// Check if the {rhs} is a HeapNumber.
- assembler->GotoUnless(assembler->IsHeapNumberMap(rhs_map), &do_add_any);
+ assembler->GotoUnless(assembler->IsHeapNumberMap(rhs_map),
+ &check_rhsisoddball);
var_fadd_lhs.Bind(assembler->SmiToFloat64(lhs));
var_fadd_rhs.Bind(assembler->LoadHeapNumberValue(rhs));
@@ -1092,18 +792,17 @@ compiler::Node* AddWithFeedbackStub::Generate(
assembler->Bind(&if_lhsisnotsmi);
{
- Label check_string(assembler);
-
// Load the map of {lhs}.
Node* lhs_map = assembler->LoadMap(lhs);
// Check if {lhs} is a HeapNumber.
- Label if_lhsisnumber(assembler), if_lhsisnotnumber(assembler);
- assembler->GotoUnless(assembler->IsHeapNumberMap(lhs_map), &check_string);
+ assembler->GotoUnless(assembler->IsHeapNumberMap(lhs_map),
+ &if_lhsisnotnumber);
// Check if the {rhs} is Smi.
Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler);
- assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
+ assembler->Branch(assembler->TaggedIsSmi(rhs), &if_rhsissmi,
+ &if_rhsisnotsmi);
assembler->Bind(&if_rhsissmi);
{
@@ -1118,48 +817,93 @@ compiler::Node* AddWithFeedbackStub::Generate(
Node* rhs_map = assembler->LoadMap(rhs);
// Check if the {rhs} is a HeapNumber.
- assembler->GotoUnless(assembler->IsHeapNumberMap(rhs_map), &do_add_any);
+ assembler->GotoUnless(assembler->IsHeapNumberMap(rhs_map),
+ &check_rhsisoddball);
var_fadd_lhs.Bind(assembler->LoadHeapNumberValue(lhs));
var_fadd_rhs.Bind(assembler->LoadHeapNumberValue(rhs));
assembler->Goto(&do_fadd);
}
+ }
+
+ assembler->Bind(&do_fadd);
+ {
+ var_type_feedback.Bind(
+ assembler->Int32Constant(BinaryOperationFeedback::kNumber));
+ Node* value =
+ assembler->Float64Add(var_fadd_lhs.value(), var_fadd_rhs.value());
+ Node* result = assembler->AllocateHeapNumberWithValue(value);
+ var_result.Bind(result);
+ assembler->Goto(&end);
+ }
- assembler->Bind(&check_string);
+ assembler->Bind(&if_lhsisnotnumber);
+ {
+ // No checks on rhs are done yet. We just know lhs is not a number or Smi.
+ Label if_lhsisoddball(assembler), if_lhsisnotoddball(assembler);
+ Node* lhs_instance_type = assembler->LoadInstanceType(lhs);
+ Node* lhs_is_oddball = assembler->Word32Equal(
+ lhs_instance_type, assembler->Int32Constant(ODDBALL_TYPE));
+ assembler->Branch(lhs_is_oddball, &if_lhsisoddball, &if_lhsisnotoddball);
+
+ assembler->Bind(&if_lhsisoddball);
{
- // Check if the {rhs} is a smi, and exit the string check early if it is.
- assembler->GotoIf(assembler->WordIsSmi(rhs), &do_add_any);
+ assembler->GotoIf(assembler->TaggedIsSmi(rhs),
+ &call_with_oddball_feedback);
- Node* lhs_instance_type = assembler->LoadMapInstanceType(lhs_map);
+ // Load the map of the {rhs}.
+ Node* rhs_map = assembler->LoadMap(rhs);
+ // Check if {rhs} is a HeapNumber.
+ assembler->Branch(assembler->IsHeapNumberMap(rhs_map),
+ &call_with_oddball_feedback, &check_rhsisoddball);
+ }
+
+ assembler->Bind(&if_lhsisnotoddball);
+ {
// Exit unless {lhs} is a string
assembler->GotoUnless(assembler->IsStringInstanceType(lhs_instance_type),
- &do_add_any);
+ &call_with_any_feedback);
+
+ // Check if the {rhs} is a smi, and exit the string check early if it is.
+ assembler->GotoIf(assembler->TaggedIsSmi(rhs), &call_with_any_feedback);
Node* rhs_instance_type = assembler->LoadInstanceType(rhs);
- // Exit unless {rhs} is a string
+ // Exit unless {rhs} is a string. Since {lhs} is a string we no longer
+ // need an Oddball check.
assembler->GotoUnless(assembler->IsStringInstanceType(rhs_instance_type),
- &do_add_any);
+ &call_with_any_feedback);
var_type_feedback.Bind(
assembler->Int32Constant(BinaryOperationFeedback::kString));
- assembler->Goto(&call_add_stub);
+ Callable callable = CodeFactory::StringAdd(
+ assembler->isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED);
+ var_result.Bind(assembler->CallStub(callable, context, lhs, rhs));
+
+ assembler->Goto(&end);
}
}
- assembler->Bind(&do_fadd);
+ assembler->Bind(&check_rhsisoddball);
+ {
+ // Check if rhs is an oddball. At this point we know lhs is either a
+ // Smi or number or oddball and rhs is not a number or Smi.
+ Node* rhs_instance_type = assembler->LoadInstanceType(rhs);
+ Node* rhs_is_oddball = assembler->Word32Equal(
+ rhs_instance_type, assembler->Int32Constant(ODDBALL_TYPE));
+ assembler->Branch(rhs_is_oddball, &call_with_oddball_feedback,
+ &call_with_any_feedback);
+ }
+
+ assembler->Bind(&call_with_oddball_feedback);
{
var_type_feedback.Bind(
- assembler->Int32Constant(BinaryOperationFeedback::kNumber));
- Node* value =
- assembler->Float64Add(var_fadd_lhs.value(), var_fadd_rhs.value());
- Node* result = assembler->ChangeFloat64ToTagged(value);
- var_result.Bind(result);
- assembler->Goto(&end);
+ assembler->Int32Constant(BinaryOperationFeedback::kNumberOrOddball));
+ assembler->Goto(&call_add_stub);
}
- assembler->Bind(&do_add_any);
+ assembler->Bind(&call_with_any_feedback);
{
var_type_feedback.Bind(
assembler->Int32Constant(BinaryOperationFeedback::kAny));
@@ -1180,180 +924,6 @@ compiler::Node* AddWithFeedbackStub::Generate(
}
// static
-compiler::Node* SubtractStub::Generate(CodeStubAssembler* assembler,
- compiler::Node* left,
- compiler::Node* right,
- compiler::Node* context) {
- typedef CodeStubAssembler::Label Label;
- typedef compiler::Node Node;
- typedef CodeStubAssembler::Variable Variable;
-
- // Shared entry for floating point subtraction.
- Label do_fsub(assembler), end(assembler);
- Variable var_fsub_lhs(assembler, MachineRepresentation::kFloat64),
- var_fsub_rhs(assembler, MachineRepresentation::kFloat64);
-
- // We might need to loop several times due to ToPrimitive and/or ToNumber
- // conversions.
- Variable var_lhs(assembler, MachineRepresentation::kTagged),
- var_rhs(assembler, MachineRepresentation::kTagged),
- var_result(assembler, MachineRepresentation::kTagged);
- Variable* loop_vars[2] = {&var_lhs, &var_rhs};
- Label loop(assembler, 2, loop_vars);
- var_lhs.Bind(left);
- var_rhs.Bind(right);
- assembler->Goto(&loop);
- assembler->Bind(&loop);
- {
- // Load the current {lhs} and {rhs} values.
- Node* lhs = var_lhs.value();
- Node* rhs = var_rhs.value();
-
- // Check if the {lhs} is a Smi or a HeapObject.
- Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler);
- assembler->Branch(assembler->WordIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi);
-
- assembler->Bind(&if_lhsissmi);
- {
- // Check if the {rhs} is also a Smi.
- Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler);
- assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi,
- &if_rhsisnotsmi);
-
- assembler->Bind(&if_rhsissmi);
- {
- // Try a fast Smi subtraction first.
- Node* pair = assembler->SmiSubWithOverflow(lhs, rhs);
- Node* overflow = assembler->Projection(1, pair);
-
- // Check if the Smi subtraction overflowed.
- Label if_overflow(assembler), if_notoverflow(assembler);
- assembler->Branch(overflow, &if_overflow, &if_notoverflow);
-
- assembler->Bind(&if_overflow);
- {
- // The result doesn't fit into Smi range.
- var_fsub_lhs.Bind(assembler->SmiToFloat64(lhs));
- var_fsub_rhs.Bind(assembler->SmiToFloat64(rhs));
- assembler->Goto(&do_fsub);
- }
-
- assembler->Bind(&if_notoverflow);
- var_result.Bind(assembler->Projection(0, pair));
- assembler->Goto(&end);
- }
-
- assembler->Bind(&if_rhsisnotsmi);
- {
- // Load the map of the {rhs}.
- Node* rhs_map = assembler->LoadMap(rhs);
-
- // Check if {rhs} is a HeapNumber.
- Label if_rhsisnumber(assembler),
- if_rhsisnotnumber(assembler, Label::kDeferred);
- assembler->Branch(assembler->IsHeapNumberMap(rhs_map), &if_rhsisnumber,
- &if_rhsisnotnumber);
-
- assembler->Bind(&if_rhsisnumber);
- {
- // Perform a floating point subtraction.
- var_fsub_lhs.Bind(assembler->SmiToFloat64(lhs));
- var_fsub_rhs.Bind(assembler->LoadHeapNumberValue(rhs));
- assembler->Goto(&do_fsub);
- }
-
- assembler->Bind(&if_rhsisnotnumber);
- {
- // Convert the {rhs} to a Number first.
- Callable callable =
- CodeFactory::NonNumberToNumber(assembler->isolate());
- var_rhs.Bind(assembler->CallStub(callable, context, rhs));
- assembler->Goto(&loop);
- }
- }
- }
-
- assembler->Bind(&if_lhsisnotsmi);
- {
- // Load the map of the {lhs}.
- Node* lhs_map = assembler->LoadMap(lhs);
-
- // Check if the {lhs} is a HeapNumber.
- Label if_lhsisnumber(assembler),
- if_lhsisnotnumber(assembler, Label::kDeferred);
- Node* number_map = assembler->HeapNumberMapConstant();
- assembler->Branch(assembler->WordEqual(lhs_map, number_map),
- &if_lhsisnumber, &if_lhsisnotnumber);
-
- assembler->Bind(&if_lhsisnumber);
- {
- // Check if the {rhs} is a Smi.
- Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler);
- assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi,
- &if_rhsisnotsmi);
-
- assembler->Bind(&if_rhsissmi);
- {
- // Perform a floating point subtraction.
- var_fsub_lhs.Bind(assembler->LoadHeapNumberValue(lhs));
- var_fsub_rhs.Bind(assembler->SmiToFloat64(rhs));
- assembler->Goto(&do_fsub);
- }
-
- assembler->Bind(&if_rhsisnotsmi);
- {
- // Load the map of the {rhs}.
- Node* rhs_map = assembler->LoadMap(rhs);
-
- // Check if the {rhs} is a HeapNumber.
- Label if_rhsisnumber(assembler),
- if_rhsisnotnumber(assembler, Label::kDeferred);
- assembler->Branch(assembler->WordEqual(rhs_map, number_map),
- &if_rhsisnumber, &if_rhsisnotnumber);
-
- assembler->Bind(&if_rhsisnumber);
- {
- // Perform a floating point subtraction.
- var_fsub_lhs.Bind(assembler->LoadHeapNumberValue(lhs));
- var_fsub_rhs.Bind(assembler->LoadHeapNumberValue(rhs));
- assembler->Goto(&do_fsub);
- }
-
- assembler->Bind(&if_rhsisnotnumber);
- {
- // Convert the {rhs} to a Number first.
- Callable callable =
- CodeFactory::NonNumberToNumber(assembler->isolate());
- var_rhs.Bind(assembler->CallStub(callable, context, rhs));
- assembler->Goto(&loop);
- }
- }
- }
-
- assembler->Bind(&if_lhsisnotnumber);
- {
- // Convert the {lhs} to a Number first.
- Callable callable =
- CodeFactory::NonNumberToNumber(assembler->isolate());
- var_lhs.Bind(assembler->CallStub(callable, context, lhs));
- assembler->Goto(&loop);
- }
- }
- }
-
- assembler->Bind(&do_fsub);
- {
- Node* lhs_value = var_fsub_lhs.value();
- Node* rhs_value = var_fsub_rhs.value();
- Node* value = assembler->Float64Sub(lhs_value, rhs_value);
- var_result.Bind(assembler->ChangeFloat64ToTagged(value));
- assembler->Goto(&end);
- }
- assembler->Bind(&end);
- return var_result.value();
-}
-
-// static
compiler::Node* SubtractWithFeedbackStub::Generate(
CodeStubAssembler* assembler, compiler::Node* lhs, compiler::Node* rhs,
compiler::Node* slot_id, compiler::Node* type_feedback_vector,
@@ -1363,8 +933,9 @@ compiler::Node* SubtractWithFeedbackStub::Generate(
typedef CodeStubAssembler::Variable Variable;
// Shared entry for floating point subtraction.
- Label do_fsub(assembler), end(assembler),
- call_subtract_stub(assembler, Label::kDeferred);
+ Label do_fsub(assembler), end(assembler), call_subtract_stub(assembler),
+ if_lhsisnotnumber(assembler), check_rhsisoddball(assembler),
+ call_with_any_feedback(assembler);
Variable var_fsub_lhs(assembler, MachineRepresentation::kFloat64),
var_fsub_rhs(assembler, MachineRepresentation::kFloat64),
var_type_feedback(assembler, MachineRepresentation::kWord32),
@@ -1372,18 +943,21 @@ compiler::Node* SubtractWithFeedbackStub::Generate(
// Check if the {lhs} is a Smi or a HeapObject.
Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler);
- assembler->Branch(assembler->WordIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi);
+ assembler->Branch(assembler->TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi);
assembler->Bind(&if_lhsissmi);
{
// Check if the {rhs} is also a Smi.
Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler);
- assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
+ assembler->Branch(assembler->TaggedIsSmi(rhs), &if_rhsissmi,
+ &if_rhsisnotsmi);
assembler->Bind(&if_rhsissmi);
{
// Try a fast Smi subtraction first.
- Node* pair = assembler->SmiSubWithOverflow(lhs, rhs);
+ Node* pair =
+ assembler->IntPtrSubWithOverflow(assembler->BitcastTaggedToWord(lhs),
+ assembler->BitcastTaggedToWord(rhs));
Node* overflow = assembler->Projection(1, pair);
// Check if the Smi subtraction overflowed.
@@ -1403,7 +977,8 @@ compiler::Node* SubtractWithFeedbackStub::Generate(
// lhs, rhs, result smi. combined - smi.
var_type_feedback.Bind(
assembler->Int32Constant(BinaryOperationFeedback::kSignedSmall));
- var_result.Bind(assembler->Projection(0, pair));
+ var_result.Bind(
+ assembler->BitcastWordToTaggedSigned(assembler->Projection(0, pair)));
assembler->Goto(&end);
}
@@ -1414,7 +989,7 @@ compiler::Node* SubtractWithFeedbackStub::Generate(
// Check if {rhs} is a HeapNumber.
assembler->GotoUnless(assembler->IsHeapNumberMap(rhs_map),
- &call_subtract_stub);
+ &check_rhsisoddball);
// Perform a floating point subtraction.
var_fsub_lhs.Bind(assembler->SmiToFloat64(lhs));
@@ -1430,11 +1005,12 @@ compiler::Node* SubtractWithFeedbackStub::Generate(
// Check if the {lhs} is a HeapNumber.
assembler->GotoUnless(assembler->IsHeapNumberMap(lhs_map),
- &call_subtract_stub);
+ &if_lhsisnotnumber);
// Check if the {rhs} is a Smi.
Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler);
- assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
+ assembler->Branch(assembler->TaggedIsSmi(rhs), &if_rhsissmi,
+ &if_rhsisnotsmi);
assembler->Bind(&if_rhsissmi);
{
@@ -1451,7 +1027,7 @@ compiler::Node* SubtractWithFeedbackStub::Generate(
// Check if the {rhs} is a HeapNumber.
assembler->GotoUnless(assembler->IsHeapNumberMap(rhs_map),
- &call_subtract_stub);
+ &check_rhsisoddball);
// Perform a floating point subtraction.
var_fsub_lhs.Bind(assembler->LoadHeapNumberValue(lhs));
@@ -1467,178 +1043,80 @@ compiler::Node* SubtractWithFeedbackStub::Generate(
Node* lhs_value = var_fsub_lhs.value();
Node* rhs_value = var_fsub_rhs.value();
Node* value = assembler->Float64Sub(lhs_value, rhs_value);
- var_result.Bind(assembler->ChangeFloat64ToTagged(value));
+ var_result.Bind(assembler->AllocateHeapNumberWithValue(value));
assembler->Goto(&end);
}
- assembler->Bind(&call_subtract_stub);
+ assembler->Bind(&if_lhsisnotnumber);
{
- var_type_feedback.Bind(
- assembler->Int32Constant(BinaryOperationFeedback::kAny));
- Callable callable = CodeFactory::Subtract(assembler->isolate());
- var_result.Bind(assembler->CallStub(callable, context, lhs, rhs));
- assembler->Goto(&end);
- }
+ // No checks on rhs are done yet. We just know lhs is not a number or Smi.
+ // Check if lhs is an oddball.
+ Node* lhs_instance_type = assembler->LoadInstanceType(lhs);
+ Node* lhs_is_oddball = assembler->Word32Equal(
+ lhs_instance_type, assembler->Int32Constant(ODDBALL_TYPE));
+ assembler->GotoUnless(lhs_is_oddball, &call_with_any_feedback);
- assembler->Bind(&end);
- assembler->UpdateFeedback(var_type_feedback.value(), type_feedback_vector,
- slot_id);
- return var_result.value();
-}
-
-// static
-compiler::Node* MultiplyStub::Generate(CodeStubAssembler* assembler,
- compiler::Node* left,
- compiler::Node* right,
- compiler::Node* context) {
- using compiler::Node;
- typedef CodeStubAssembler::Label Label;
- typedef CodeStubAssembler::Variable Variable;
-
- // Shared entry point for floating point multiplication.
- Label do_fmul(assembler), return_result(assembler);
- Variable var_lhs_float64(assembler, MachineRepresentation::kFloat64),
- var_rhs_float64(assembler, MachineRepresentation::kFloat64);
-
- Node* number_map = assembler->HeapNumberMapConstant();
-
- // We might need to loop one or two times due to ToNumber conversions.
- Variable var_lhs(assembler, MachineRepresentation::kTagged),
- var_rhs(assembler, MachineRepresentation::kTagged),
- var_result(assembler, MachineRepresentation::kTagged);
- Variable* loop_variables[] = {&var_lhs, &var_rhs};
- Label loop(assembler, 2, loop_variables);
- var_lhs.Bind(left);
- var_rhs.Bind(right);
- assembler->Goto(&loop);
- assembler->Bind(&loop);
- {
- Node* lhs = var_lhs.value();
- Node* rhs = var_rhs.value();
-
- Label lhs_is_smi(assembler), lhs_is_not_smi(assembler);
- assembler->Branch(assembler->WordIsSmi(lhs), &lhs_is_smi, &lhs_is_not_smi);
+ Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler);
+ assembler->Branch(assembler->TaggedIsSmi(rhs), &if_rhsissmi,
+ &if_rhsisnotsmi);
- assembler->Bind(&lhs_is_smi);
+ assembler->Bind(&if_rhsissmi);
{
- Label rhs_is_smi(assembler), rhs_is_not_smi(assembler);
- assembler->Branch(assembler->WordIsSmi(rhs), &rhs_is_smi,
- &rhs_is_not_smi);
-
- assembler->Bind(&rhs_is_smi);
- {
- // Both {lhs} and {rhs} are Smis. The result is not necessarily a smi,
- // in case of overflow.
- var_result.Bind(assembler->SmiMul(lhs, rhs));
- assembler->Goto(&return_result);
- }
-
- assembler->Bind(&rhs_is_not_smi);
- {
- Node* rhs_map = assembler->LoadMap(rhs);
-
- // Check if {rhs} is a HeapNumber.
- Label rhs_is_number(assembler),
- rhs_is_not_number(assembler, Label::kDeferred);
- assembler->Branch(assembler->WordEqual(rhs_map, number_map),
- &rhs_is_number, &rhs_is_not_number);
-
- assembler->Bind(&rhs_is_number);
- {
- // Convert {lhs} to a double and multiply it with the value of {rhs}.
- var_lhs_float64.Bind(assembler->SmiToFloat64(lhs));
- var_rhs_float64.Bind(assembler->LoadHeapNumberValue(rhs));
- assembler->Goto(&do_fmul);
- }
-
- assembler->Bind(&rhs_is_not_number);
- {
- // Multiplication is commutative, swap {lhs} with {rhs} and loop.
- var_lhs.Bind(rhs);
- var_rhs.Bind(lhs);
- assembler->Goto(&loop);
- }
- }
+ var_type_feedback.Bind(
+ assembler->Int32Constant(BinaryOperationFeedback::kNumberOrOddball));
+ assembler->Goto(&call_subtract_stub);
}
- assembler->Bind(&lhs_is_not_smi);
+ assembler->Bind(&if_rhsisnotsmi);
{
- Node* lhs_map = assembler->LoadMap(lhs);
+ // Load the map of the {rhs}.
+ Node* rhs_map = assembler->LoadMap(rhs);
- // Check if {lhs} is a HeapNumber.
- Label lhs_is_number(assembler),
- lhs_is_not_number(assembler, Label::kDeferred);
- assembler->Branch(assembler->WordEqual(lhs_map, number_map),
- &lhs_is_number, &lhs_is_not_number);
+ // Check if {rhs} is a HeapNumber.
+ assembler->GotoUnless(assembler->IsHeapNumberMap(rhs_map),
+ &check_rhsisoddball);
- assembler->Bind(&lhs_is_number);
- {
- // Check if {rhs} is a Smi.
- Label rhs_is_smi(assembler), rhs_is_not_smi(assembler);
- assembler->Branch(assembler->WordIsSmi(rhs), &rhs_is_smi,
- &rhs_is_not_smi);
+ var_type_feedback.Bind(
+ assembler->Int32Constant(BinaryOperationFeedback::kNumberOrOddball));
+ assembler->Goto(&call_subtract_stub);
+ }
+ }
- assembler->Bind(&rhs_is_smi);
- {
- // Convert {rhs} to a double and multiply it with the value of {lhs}.
- var_lhs_float64.Bind(assembler->LoadHeapNumberValue(lhs));
- var_rhs_float64.Bind(assembler->SmiToFloat64(rhs));
- assembler->Goto(&do_fmul);
- }
+ assembler->Bind(&check_rhsisoddball);
+ {
+ // Check if rhs is an oddball. At this point we know lhs is either a
+ // Smi or number or oddball and rhs is not a number or Smi.
+ Node* rhs_instance_type = assembler->LoadInstanceType(rhs);
+ Node* rhs_is_oddball = assembler->Word32Equal(
+ rhs_instance_type, assembler->Int32Constant(ODDBALL_TYPE));
+ assembler->GotoUnless(rhs_is_oddball, &call_with_any_feedback);
- assembler->Bind(&rhs_is_not_smi);
- {
- Node* rhs_map = assembler->LoadMap(rhs);
-
- // Check if {rhs} is a HeapNumber.
- Label rhs_is_number(assembler),
- rhs_is_not_number(assembler, Label::kDeferred);
- assembler->Branch(assembler->WordEqual(rhs_map, number_map),
- &rhs_is_number, &rhs_is_not_number);
-
- assembler->Bind(&rhs_is_number);
- {
- // Both {lhs} and {rhs} are HeapNumbers. Load their values and
- // multiply them.
- var_lhs_float64.Bind(assembler->LoadHeapNumberValue(lhs));
- var_rhs_float64.Bind(assembler->LoadHeapNumberValue(rhs));
- assembler->Goto(&do_fmul);
- }
-
- assembler->Bind(&rhs_is_not_number);
- {
- // Multiplication is commutative, swap {lhs} with {rhs} and loop.
- var_lhs.Bind(rhs);
- var_rhs.Bind(lhs);
- assembler->Goto(&loop);
- }
- }
- }
+ var_type_feedback.Bind(
+ assembler->Int32Constant(BinaryOperationFeedback::kNumberOrOddball));
+ assembler->Goto(&call_subtract_stub);
+ }
- assembler->Bind(&lhs_is_not_number);
- {
- // Convert {lhs} to a Number and loop.
- Callable callable =
- CodeFactory::NonNumberToNumber(assembler->isolate());
- var_lhs.Bind(assembler->CallStub(callable, context, lhs));
- assembler->Goto(&loop);
- }
- }
+ assembler->Bind(&call_with_any_feedback);
+ {
+ var_type_feedback.Bind(
+ assembler->Int32Constant(BinaryOperationFeedback::kAny));
+ assembler->Goto(&call_subtract_stub);
}
- assembler->Bind(&do_fmul);
+ assembler->Bind(&call_subtract_stub);
{
- Node* value =
- assembler->Float64Mul(var_lhs_float64.value(), var_rhs_float64.value());
- Node* result = assembler->ChangeFloat64ToTagged(value);
- var_result.Bind(result);
- assembler->Goto(&return_result);
+ Callable callable = CodeFactory::Subtract(assembler->isolate());
+ var_result.Bind(assembler->CallStub(callable, context, lhs, rhs));
+ assembler->Goto(&end);
}
- assembler->Bind(&return_result);
+ assembler->Bind(&end);
+ assembler->UpdateFeedback(var_type_feedback.value(), type_feedback_vector,
+ slot_id);
return var_result.value();
}
+
// static
compiler::Node* MultiplyWithFeedbackStub::Generate(
CodeStubAssembler* assembler, compiler::Node* lhs, compiler::Node* rhs,
@@ -1649,8 +1127,10 @@ compiler::Node* MultiplyWithFeedbackStub::Generate(
typedef CodeStubAssembler::Variable Variable;
// Shared entry point for floating point multiplication.
- Label do_fmul(assembler), end(assembler),
- call_multiply_stub(assembler, Label::kDeferred);
+ Label do_fmul(assembler), if_lhsisnotnumber(assembler, Label::kDeferred),
+ check_rhsisoddball(assembler, Label::kDeferred),
+ call_with_oddball_feedback(assembler), call_with_any_feedback(assembler),
+ call_multiply_stub(assembler), end(assembler);
Variable var_lhs_float64(assembler, MachineRepresentation::kFloat64),
var_rhs_float64(assembler, MachineRepresentation::kFloat64),
var_result(assembler, MachineRepresentation::kTagged),
@@ -1659,12 +1139,13 @@ compiler::Node* MultiplyWithFeedbackStub::Generate(
Node* number_map = assembler->HeapNumberMapConstant();
Label lhs_is_smi(assembler), lhs_is_not_smi(assembler);
- assembler->Branch(assembler->WordIsSmi(lhs), &lhs_is_smi, &lhs_is_not_smi);
+ assembler->Branch(assembler->TaggedIsSmi(lhs), &lhs_is_smi, &lhs_is_not_smi);
assembler->Bind(&lhs_is_smi);
{
Label rhs_is_smi(assembler), rhs_is_not_smi(assembler);
- assembler->Branch(assembler->WordIsSmi(rhs), &rhs_is_smi, &rhs_is_not_smi);
+ assembler->Branch(assembler->TaggedIsSmi(rhs), &rhs_is_smi,
+ &rhs_is_not_smi);
assembler->Bind(&rhs_is_smi);
{
@@ -1672,7 +1153,7 @@ compiler::Node* MultiplyWithFeedbackStub::Generate(
// in case of overflow.
var_result.Bind(assembler->SmiMul(lhs, rhs));
var_type_feedback.Bind(assembler->Select(
- assembler->WordIsSmi(var_result.value()),
+ assembler->TaggedIsSmi(var_result.value()),
assembler->Int32Constant(BinaryOperationFeedback::kSignedSmall),
assembler->Int32Constant(BinaryOperationFeedback::kNumber),
MachineRepresentation::kWord32));
@@ -1685,7 +1166,7 @@ compiler::Node* MultiplyWithFeedbackStub::Generate(
// Check if {rhs} is a HeapNumber.
assembler->GotoUnless(assembler->WordEqual(rhs_map, number_map),
- &call_multiply_stub);
+ &check_rhsisoddball);
// Convert {lhs} to a double and multiply it with the value of {rhs}.
var_lhs_float64.Bind(assembler->SmiToFloat64(lhs));
@@ -1700,11 +1181,12 @@ compiler::Node* MultiplyWithFeedbackStub::Generate(
// Check if {lhs} is a HeapNumber.
assembler->GotoUnless(assembler->WordEqual(lhs_map, number_map),
- &call_multiply_stub);
+ &if_lhsisnotnumber);
// Check if {rhs} is a Smi.
Label rhs_is_smi(assembler), rhs_is_not_smi(assembler);
- assembler->Branch(assembler->WordIsSmi(rhs), &rhs_is_smi, &rhs_is_not_smi);
+ assembler->Branch(assembler->TaggedIsSmi(rhs), &rhs_is_smi,
+ &rhs_is_not_smi);
assembler->Bind(&rhs_is_smi);
{
@@ -1720,7 +1202,7 @@ compiler::Node* MultiplyWithFeedbackStub::Generate(
// Check if {rhs} is a HeapNumber.
assembler->GotoUnless(assembler->WordEqual(rhs_map, number_map),
- &call_multiply_stub);
+ &check_rhsisoddball);
// Both {lhs} and {rhs} are HeapNumbers. Load their values and
// multiply them.
@@ -1736,244 +1218,69 @@ compiler::Node* MultiplyWithFeedbackStub::Generate(
assembler->Int32Constant(BinaryOperationFeedback::kNumber));
Node* value =
assembler->Float64Mul(var_lhs_float64.value(), var_rhs_float64.value());
- Node* result = assembler->ChangeFloat64ToTagged(value);
+ Node* result = assembler->AllocateHeapNumberWithValue(value);
var_result.Bind(result);
assembler->Goto(&end);
}
- assembler->Bind(&call_multiply_stub);
+ assembler->Bind(&if_lhsisnotnumber);
{
- var_type_feedback.Bind(
- assembler->Int32Constant(BinaryOperationFeedback::kAny));
- Callable callable = CodeFactory::Multiply(assembler->isolate());
- var_result.Bind(assembler->CallStub(callable, context, lhs, rhs));
- assembler->Goto(&end);
- }
-
- assembler->Bind(&end);
- assembler->UpdateFeedback(var_type_feedback.value(), type_feedback_vector,
- slot_id);
- return var_result.value();
-}
+ // No checks on rhs are done yet. We just know lhs is not a number or Smi.
+ // Check if lhs is an oddball.
+ Node* lhs_instance_type = assembler->LoadInstanceType(lhs);
+ Node* lhs_is_oddball = assembler->Word32Equal(
+ lhs_instance_type, assembler->Int32Constant(ODDBALL_TYPE));
+ assembler->GotoUnless(lhs_is_oddball, &call_with_any_feedback);
-// static
-compiler::Node* DivideStub::Generate(CodeStubAssembler* assembler,
- compiler::Node* left,
- compiler::Node* right,
- compiler::Node* context) {
- using compiler::Node;
- typedef CodeStubAssembler::Label Label;
- typedef CodeStubAssembler::Variable Variable;
+ assembler->GotoIf(assembler->TaggedIsSmi(rhs), &call_with_oddball_feedback);
- // Shared entry point for floating point division.
- Label do_fdiv(assembler), end(assembler);
- Variable var_dividend_float64(assembler, MachineRepresentation::kFloat64),
- var_divisor_float64(assembler, MachineRepresentation::kFloat64);
+ // Load the map of the {rhs}.
+ Node* rhs_map = assembler->LoadMap(rhs);
- Node* number_map = assembler->HeapNumberMapConstant();
+ // Check if {rhs} is a HeapNumber.
+ assembler->Branch(assembler->IsHeapNumberMap(rhs_map),
+ &call_with_oddball_feedback, &check_rhsisoddball);
+ }
- // We might need to loop one or two times due to ToNumber conversions.
- Variable var_dividend(assembler, MachineRepresentation::kTagged),
- var_divisor(assembler, MachineRepresentation::kTagged),
- var_result(assembler, MachineRepresentation::kTagged);
- Variable* loop_variables[] = {&var_dividend, &var_divisor};
- Label loop(assembler, 2, loop_variables);
- var_dividend.Bind(left);
- var_divisor.Bind(right);
- assembler->Goto(&loop);
- assembler->Bind(&loop);
+ assembler->Bind(&check_rhsisoddball);
{
- Node* dividend = var_dividend.value();
- Node* divisor = var_divisor.value();
-
- Label dividend_is_smi(assembler), dividend_is_not_smi(assembler);
- assembler->Branch(assembler->WordIsSmi(dividend), &dividend_is_smi,
- &dividend_is_not_smi);
-
- assembler->Bind(&dividend_is_smi);
- {
- Label divisor_is_smi(assembler), divisor_is_not_smi(assembler);
- assembler->Branch(assembler->WordIsSmi(divisor), &divisor_is_smi,
- &divisor_is_not_smi);
-
- assembler->Bind(&divisor_is_smi);
- {
- Label bailout(assembler);
-
- // Do floating point division if {divisor} is zero.
- assembler->GotoIf(
- assembler->WordEqual(divisor, assembler->IntPtrConstant(0)),
- &bailout);
-
- // Do floating point division {dividend} is zero and {divisor} is
- // negative.
- Label dividend_is_zero(assembler), dividend_is_not_zero(assembler);
- assembler->Branch(
- assembler->WordEqual(dividend, assembler->IntPtrConstant(0)),
- &dividend_is_zero, &dividend_is_not_zero);
-
- assembler->Bind(&dividend_is_zero);
- {
- assembler->GotoIf(
- assembler->IntPtrLessThan(divisor, assembler->IntPtrConstant(0)),
- &bailout);
- assembler->Goto(&dividend_is_not_zero);
- }
- assembler->Bind(&dividend_is_not_zero);
-
- Node* untagged_divisor = assembler->SmiUntag(divisor);
- Node* untagged_dividend = assembler->SmiUntag(dividend);
-
- // Do floating point division if {dividend} is kMinInt (or kMinInt - 1
- // if the Smi size is 31) and {divisor} is -1.
- Label divisor_is_minus_one(assembler),
- divisor_is_not_minus_one(assembler);
- assembler->Branch(assembler->Word32Equal(untagged_divisor,
- assembler->Int32Constant(-1)),
- &divisor_is_minus_one, &divisor_is_not_minus_one);
-
- assembler->Bind(&divisor_is_minus_one);
- {
- assembler->GotoIf(
- assembler->Word32Equal(
- untagged_dividend,
- assembler->Int32Constant(
- kSmiValueSize == 32 ? kMinInt : (kMinInt >> 1))),
- &bailout);
- assembler->Goto(&divisor_is_not_minus_one);
- }
- assembler->Bind(&divisor_is_not_minus_one);
-
- // TODO(epertoso): consider adding a machine instruction that returns
- // both the result and the remainder.
- Node* untagged_result =
- assembler->Int32Div(untagged_dividend, untagged_divisor);
- Node* truncated =
- assembler->Int32Mul(untagged_result, untagged_divisor);
- // Do floating point division if the remainder is not 0.
- assembler->GotoIf(
- assembler->Word32NotEqual(untagged_dividend, truncated), &bailout);
- var_result.Bind(assembler->SmiTag(untagged_result));
- assembler->Goto(&end);
-
- // Bailout: convert {dividend} and {divisor} to double and do double
- // division.
- assembler->Bind(&bailout);
- {
- var_dividend_float64.Bind(assembler->SmiToFloat64(dividend));
- var_divisor_float64.Bind(assembler->SmiToFloat64(divisor));
- assembler->Goto(&do_fdiv);
- }
- }
-
- assembler->Bind(&divisor_is_not_smi);
- {
- Node* divisor_map = assembler->LoadMap(divisor);
-
- // Check if {divisor} is a HeapNumber.
- Label divisor_is_number(assembler),
- divisor_is_not_number(assembler, Label::kDeferred);
- assembler->Branch(assembler->WordEqual(divisor_map, number_map),
- &divisor_is_number, &divisor_is_not_number);
-
- assembler->Bind(&divisor_is_number);
- {
- // Convert {dividend} to a double and divide it with the value of
- // {divisor}.
- var_dividend_float64.Bind(assembler->SmiToFloat64(dividend));
- var_divisor_float64.Bind(assembler->LoadHeapNumberValue(divisor));
- assembler->Goto(&do_fdiv);
- }
-
- assembler->Bind(&divisor_is_not_number);
- {
- // Convert {divisor} to a number and loop.
- Callable callable =
- CodeFactory::NonNumberToNumber(assembler->isolate());
- var_divisor.Bind(assembler->CallStub(callable, context, divisor));
- assembler->Goto(&loop);
- }
- }
- }
-
- assembler->Bind(&dividend_is_not_smi);
- {
- Node* dividend_map = assembler->LoadMap(dividend);
-
- // Check if {dividend} is a HeapNumber.
- Label dividend_is_number(assembler),
- dividend_is_not_number(assembler, Label::kDeferred);
- assembler->Branch(assembler->WordEqual(dividend_map, number_map),
- &dividend_is_number, &dividend_is_not_number);
-
- assembler->Bind(&dividend_is_number);
- {
- // Check if {divisor} is a Smi.
- Label divisor_is_smi(assembler), divisor_is_not_smi(assembler);
- assembler->Branch(assembler->WordIsSmi(divisor), &divisor_is_smi,
- &divisor_is_not_smi);
-
- assembler->Bind(&divisor_is_smi);
- {
- // Convert {divisor} to a double and use it for a floating point
- // division.
- var_dividend_float64.Bind(assembler->LoadHeapNumberValue(dividend));
- var_divisor_float64.Bind(assembler->SmiToFloat64(divisor));
- assembler->Goto(&do_fdiv);
- }
+ // Check if rhs is an oddball. At this point we know lhs is either a
+ // Smi or number or oddball and rhs is not a number or Smi.
+ Node* rhs_instance_type = assembler->LoadInstanceType(rhs);
+ Node* rhs_is_oddball = assembler->Word32Equal(
+ rhs_instance_type, assembler->Int32Constant(ODDBALL_TYPE));
+ assembler->Branch(rhs_is_oddball, &call_with_oddball_feedback,
+ &call_with_any_feedback);
+ }
- assembler->Bind(&divisor_is_not_smi);
- {
- Node* divisor_map = assembler->LoadMap(divisor);
-
- // Check if {divisor} is a HeapNumber.
- Label divisor_is_number(assembler),
- divisor_is_not_number(assembler, Label::kDeferred);
- assembler->Branch(assembler->WordEqual(divisor_map, number_map),
- &divisor_is_number, &divisor_is_not_number);
-
- assembler->Bind(&divisor_is_number);
- {
- // Both {dividend} and {divisor} are HeapNumbers. Load their values
- // and divide them.
- var_dividend_float64.Bind(assembler->LoadHeapNumberValue(dividend));
- var_divisor_float64.Bind(assembler->LoadHeapNumberValue(divisor));
- assembler->Goto(&do_fdiv);
- }
-
- assembler->Bind(&divisor_is_not_number);
- {
- // Convert {divisor} to a number and loop.
- Callable callable =
- CodeFactory::NonNumberToNumber(assembler->isolate());
- var_divisor.Bind(assembler->CallStub(callable, context, divisor));
- assembler->Goto(&loop);
- }
- }
- }
+ assembler->Bind(&call_with_oddball_feedback);
+ {
+ var_type_feedback.Bind(
+ assembler->Int32Constant(BinaryOperationFeedback::kNumberOrOddball));
+ assembler->Goto(&call_multiply_stub);
+ }
- assembler->Bind(&dividend_is_not_number);
- {
- // Convert {dividend} to a Number and loop.
- Callable callable =
- CodeFactory::NonNumberToNumber(assembler->isolate());
- var_dividend.Bind(assembler->CallStub(callable, context, dividend));
- assembler->Goto(&loop);
- }
- }
+ assembler->Bind(&call_with_any_feedback);
+ {
+ var_type_feedback.Bind(
+ assembler->Int32Constant(BinaryOperationFeedback::kAny));
+ assembler->Goto(&call_multiply_stub);
}
- assembler->Bind(&do_fdiv);
+ assembler->Bind(&call_multiply_stub);
{
- Node* value = assembler->Float64Div(var_dividend_float64.value(),
- var_divisor_float64.value());
- var_result.Bind(assembler->ChangeFloat64ToTagged(value));
+ Callable callable = CodeFactory::Multiply(assembler->isolate());
+ var_result.Bind(assembler->CallStub(callable, context, lhs, rhs));
assembler->Goto(&end);
}
+
assembler->Bind(&end);
+ assembler->UpdateFeedback(var_type_feedback.value(), type_feedback_vector,
+ slot_id);
return var_result.value();
}
+
// static
compiler::Node* DivideWithFeedbackStub::Generate(
CodeStubAssembler* assembler, compiler::Node* dividend,
@@ -1984,7 +1291,10 @@ compiler::Node* DivideWithFeedbackStub::Generate(
typedef CodeStubAssembler::Variable Variable;
// Shared entry point for floating point division.
- Label do_fdiv(assembler), end(assembler), call_divide_stub(assembler);
+ Label do_fdiv(assembler), dividend_is_not_number(assembler, Label::kDeferred),
+ check_divisor_for_oddball(assembler, Label::kDeferred),
+ call_with_oddball_feedback(assembler), call_with_any_feedback(assembler),
+ call_divide_stub(assembler), end(assembler);
Variable var_dividend_float64(assembler, MachineRepresentation::kFloat64),
var_divisor_float64(assembler, MachineRepresentation::kFloat64),
var_result(assembler, MachineRepresentation::kTagged),
@@ -1993,13 +1303,13 @@ compiler::Node* DivideWithFeedbackStub::Generate(
Node* number_map = assembler->HeapNumberMapConstant();
Label dividend_is_smi(assembler), dividend_is_not_smi(assembler);
- assembler->Branch(assembler->WordIsSmi(dividend), &dividend_is_smi,
+ assembler->Branch(assembler->TaggedIsSmi(dividend), &dividend_is_smi,
&dividend_is_not_smi);
assembler->Bind(&dividend_is_smi);
{
Label divisor_is_smi(assembler), divisor_is_not_smi(assembler);
- assembler->Branch(assembler->WordIsSmi(divisor), &divisor_is_smi,
+ assembler->Branch(assembler->TaggedIsSmi(divisor), &divisor_is_smi,
&divisor_is_not_smi);
assembler->Bind(&divisor_is_smi);
@@ -2077,7 +1387,7 @@ compiler::Node* DivideWithFeedbackStub::Generate(
// Check if {divisor} is a HeapNumber.
assembler->GotoUnless(assembler->WordEqual(divisor_map, number_map),
- &call_divide_stub);
+ &check_divisor_for_oddball);
// Convert {dividend} to a double and divide it with the value of
// {divisor}.
@@ -2092,11 +1402,11 @@ compiler::Node* DivideWithFeedbackStub::Generate(
// Check if {dividend} is a HeapNumber.
assembler->GotoUnless(assembler->WordEqual(dividend_map, number_map),
- &call_divide_stub);
+ &dividend_is_not_number);
// Check if {divisor} is a Smi.
Label divisor_is_smi(assembler), divisor_is_not_smi(assembler);
- assembler->Branch(assembler->WordIsSmi(divisor), &divisor_is_smi,
+ assembler->Branch(assembler->TaggedIsSmi(divisor), &divisor_is_smi,
&divisor_is_not_smi);
assembler->Bind(&divisor_is_smi);
@@ -2114,7 +1424,7 @@ compiler::Node* DivideWithFeedbackStub::Generate(
// Check if {divisor} is a HeapNumber.
assembler->GotoUnless(assembler->WordEqual(divisor_map, number_map),
- &call_divide_stub);
+ &check_divisor_for_oddball);
// Both {dividend} and {divisor} are HeapNumbers. Load their values
// and divide them.
@@ -2131,181 +1441,65 @@ compiler::Node* DivideWithFeedbackStub::Generate(
assembler->Int32Constant(BinaryOperationFeedback::kNumber));
Node* value = assembler->Float64Div(var_dividend_float64.value(),
var_divisor_float64.value());
- var_result.Bind(assembler->ChangeFloat64ToTagged(value));
+ var_result.Bind(assembler->AllocateHeapNumberWithValue(value));
assembler->Goto(&end);
}
- assembler->Bind(&call_divide_stub);
+ assembler->Bind(&dividend_is_not_number);
{
- var_type_feedback.Bind(
- assembler->Int32Constant(BinaryOperationFeedback::kAny));
- Callable callable = CodeFactory::Divide(assembler->isolate());
- var_result.Bind(assembler->CallStub(callable, context, dividend, divisor));
- assembler->Goto(&end);
- }
+ // We just know dividend is not a number or Smi. No checks on divisor yet.
+ // Check if dividend is an oddball.
+ Node* dividend_instance_type = assembler->LoadInstanceType(dividend);
+ Node* dividend_is_oddball = assembler->Word32Equal(
+ dividend_instance_type, assembler->Int32Constant(ODDBALL_TYPE));
+ assembler->GotoUnless(dividend_is_oddball, &call_with_any_feedback);
- assembler->Bind(&end);
- assembler->UpdateFeedback(var_type_feedback.value(), type_feedback_vector,
- slot_id);
- return var_result.value();
-}
-
-// static
-compiler::Node* ModulusStub::Generate(CodeStubAssembler* assembler,
- compiler::Node* left,
- compiler::Node* right,
- compiler::Node* context) {
- using compiler::Node;
- typedef CodeStubAssembler::Label Label;
- typedef CodeStubAssembler::Variable Variable;
-
- Variable var_result(assembler, MachineRepresentation::kTagged);
- Label return_result(assembler, &var_result);
+ assembler->GotoIf(assembler->TaggedIsSmi(divisor),
+ &call_with_oddball_feedback);
- // Shared entry point for floating point modulus.
- Label do_fmod(assembler);
- Variable var_dividend_float64(assembler, MachineRepresentation::kFloat64),
- var_divisor_float64(assembler, MachineRepresentation::kFloat64);
+ // Load the map of the {divisor}.
+ Node* divisor_map = assembler->LoadMap(divisor);
- Node* number_map = assembler->HeapNumberMapConstant();
+ // Check if {divisor} is a HeapNumber.
+ assembler->Branch(assembler->IsHeapNumberMap(divisor_map),
+ &call_with_oddball_feedback, &check_divisor_for_oddball);
+ }
- // We might need to loop one or two times due to ToNumber conversions.
- Variable var_dividend(assembler, MachineRepresentation::kTagged),
- var_divisor(assembler, MachineRepresentation::kTagged);
- Variable* loop_variables[] = {&var_dividend, &var_divisor};
- Label loop(assembler, 2, loop_variables);
- var_dividend.Bind(left);
- var_divisor.Bind(right);
- assembler->Goto(&loop);
- assembler->Bind(&loop);
+ assembler->Bind(&check_divisor_for_oddball);
{
- Node* dividend = var_dividend.value();
- Node* divisor = var_divisor.value();
-
- Label dividend_is_smi(assembler), dividend_is_not_smi(assembler);
- assembler->Branch(assembler->WordIsSmi(dividend), &dividend_is_smi,
- &dividend_is_not_smi);
-
- assembler->Bind(&dividend_is_smi);
- {
- Label dividend_is_not_zero(assembler);
- Label divisor_is_smi(assembler), divisor_is_not_smi(assembler);
- assembler->Branch(assembler->WordIsSmi(divisor), &divisor_is_smi,
- &divisor_is_not_smi);
-
- assembler->Bind(&divisor_is_smi);
- {
- // Compute the modulus of two Smis.
- var_result.Bind(assembler->SmiMod(dividend, divisor));
- assembler->Goto(&return_result);
- }
-
- assembler->Bind(&divisor_is_not_smi);
- {
- Node* divisor_map = assembler->LoadMap(divisor);
-
- // Check if {divisor} is a HeapNumber.
- Label divisor_is_number(assembler),
- divisor_is_not_number(assembler, Label::kDeferred);
- assembler->Branch(assembler->WordEqual(divisor_map, number_map),
- &divisor_is_number, &divisor_is_not_number);
-
- assembler->Bind(&divisor_is_number);
- {
- // Convert {dividend} to a double and compute its modulus with the
- // value of {dividend}.
- var_dividend_float64.Bind(assembler->SmiToFloat64(dividend));
- var_divisor_float64.Bind(assembler->LoadHeapNumberValue(divisor));
- assembler->Goto(&do_fmod);
- }
-
- assembler->Bind(&divisor_is_not_number);
- {
- // Convert {divisor} to a number and loop.
- Callable callable =
- CodeFactory::NonNumberToNumber(assembler->isolate());
- var_divisor.Bind(assembler->CallStub(callable, context, divisor));
- assembler->Goto(&loop);
- }
- }
- }
-
- assembler->Bind(&dividend_is_not_smi);
- {
- Node* dividend_map = assembler->LoadMap(dividend);
-
- // Check if {dividend} is a HeapNumber.
- Label dividend_is_number(assembler),
- dividend_is_not_number(assembler, Label::kDeferred);
- assembler->Branch(assembler->WordEqual(dividend_map, number_map),
- &dividend_is_number, &dividend_is_not_number);
-
- assembler->Bind(&dividend_is_number);
- {
- // Check if {divisor} is a Smi.
- Label divisor_is_smi(assembler), divisor_is_not_smi(assembler);
- assembler->Branch(assembler->WordIsSmi(divisor), &divisor_is_smi,
- &divisor_is_not_smi);
-
- assembler->Bind(&divisor_is_smi);
- {
- // Convert {divisor} to a double and compute {dividend}'s modulus with
- // it.
- var_dividend_float64.Bind(assembler->LoadHeapNumberValue(dividend));
- var_divisor_float64.Bind(assembler->SmiToFloat64(divisor));
- assembler->Goto(&do_fmod);
- }
+ // Check if divisor is an oddball. At this point we know dividend is either
+ // a Smi or number or oddball and divisor is not a number or Smi.
+ Node* divisor_instance_type = assembler->LoadInstanceType(divisor);
+ Node* divisor_is_oddball = assembler->Word32Equal(
+ divisor_instance_type, assembler->Int32Constant(ODDBALL_TYPE));
+ assembler->Branch(divisor_is_oddball, &call_with_oddball_feedback,
+ &call_with_any_feedback);
+ }
- assembler->Bind(&divisor_is_not_smi);
- {
- Node* divisor_map = assembler->LoadMap(divisor);
-
- // Check if {divisor} is a HeapNumber.
- Label divisor_is_number(assembler),
- divisor_is_not_number(assembler, Label::kDeferred);
- assembler->Branch(assembler->WordEqual(divisor_map, number_map),
- &divisor_is_number, &divisor_is_not_number);
-
- assembler->Bind(&divisor_is_number);
- {
- // Both {dividend} and {divisor} are HeapNumbers. Load their values
- // and compute their modulus.
- var_dividend_float64.Bind(assembler->LoadHeapNumberValue(dividend));
- var_divisor_float64.Bind(assembler->LoadHeapNumberValue(divisor));
- assembler->Goto(&do_fmod);
- }
-
- assembler->Bind(&divisor_is_not_number);
- {
- // Convert {divisor} to a number and loop.
- Callable callable =
- CodeFactory::NonNumberToNumber(assembler->isolate());
- var_divisor.Bind(assembler->CallStub(callable, context, divisor));
- assembler->Goto(&loop);
- }
- }
- }
+ assembler->Bind(&call_with_oddball_feedback);
+ {
+ var_type_feedback.Bind(
+ assembler->Int32Constant(BinaryOperationFeedback::kNumberOrOddball));
+ assembler->Goto(&call_divide_stub);
+ }
- assembler->Bind(&dividend_is_not_number);
- {
- // Convert {dividend} to a Number and loop.
- Callable callable =
- CodeFactory::NonNumberToNumber(assembler->isolate());
- var_dividend.Bind(assembler->CallStub(callable, context, dividend));
- assembler->Goto(&loop);
- }
- }
+ assembler->Bind(&call_with_any_feedback);
+ {
+ var_type_feedback.Bind(
+ assembler->Int32Constant(BinaryOperationFeedback::kAny));
+ assembler->Goto(&call_divide_stub);
}
- assembler->Bind(&do_fmod);
+ assembler->Bind(&call_divide_stub);
{
- Node* value = assembler->Float64Mod(var_dividend_float64.value(),
- var_divisor_float64.value());
- var_result.Bind(assembler->ChangeFloat64ToTagged(value));
- assembler->Goto(&return_result);
+ Callable callable = CodeFactory::Divide(assembler->isolate());
+ var_result.Bind(assembler->CallStub(callable, context, dividend, divisor));
+ assembler->Goto(&end);
}
- assembler->Bind(&return_result);
+ assembler->Bind(&end);
+ assembler->UpdateFeedback(var_type_feedback.value(), type_feedback_vector,
+ slot_id);
return var_result.value();
}
@@ -2319,7 +1513,10 @@ compiler::Node* ModulusWithFeedbackStub::Generate(
typedef CodeStubAssembler::Variable Variable;
// Shared entry point for floating point division.
- Label do_fmod(assembler), end(assembler), call_modulus_stub(assembler);
+ Label do_fmod(assembler), dividend_is_not_number(assembler, Label::kDeferred),
+ check_divisor_for_oddball(assembler, Label::kDeferred),
+ call_with_oddball_feedback(assembler), call_with_any_feedback(assembler),
+ call_modulus_stub(assembler), end(assembler);
Variable var_dividend_float64(assembler, MachineRepresentation::kFloat64),
var_divisor_float64(assembler, MachineRepresentation::kFloat64),
var_result(assembler, MachineRepresentation::kTagged),
@@ -2328,20 +1525,20 @@ compiler::Node* ModulusWithFeedbackStub::Generate(
Node* number_map = assembler->HeapNumberMapConstant();
Label dividend_is_smi(assembler), dividend_is_not_smi(assembler);
- assembler->Branch(assembler->WordIsSmi(dividend), &dividend_is_smi,
+ assembler->Branch(assembler->TaggedIsSmi(dividend), &dividend_is_smi,
&dividend_is_not_smi);
assembler->Bind(&dividend_is_smi);
{
Label divisor_is_smi(assembler), divisor_is_not_smi(assembler);
- assembler->Branch(assembler->WordIsSmi(divisor), &divisor_is_smi,
+ assembler->Branch(assembler->TaggedIsSmi(divisor), &divisor_is_smi,
&divisor_is_not_smi);
assembler->Bind(&divisor_is_smi);
{
var_result.Bind(assembler->SmiMod(dividend, divisor));
var_type_feedback.Bind(assembler->Select(
- assembler->WordIsSmi(var_result.value()),
+ assembler->TaggedIsSmi(var_result.value()),
assembler->Int32Constant(BinaryOperationFeedback::kSignedSmall),
assembler->Int32Constant(BinaryOperationFeedback::kNumber)));
assembler->Goto(&end);
@@ -2353,7 +1550,7 @@ compiler::Node* ModulusWithFeedbackStub::Generate(
// Check if {divisor} is a HeapNumber.
assembler->GotoUnless(assembler->WordEqual(divisor_map, number_map),
- &call_modulus_stub);
+ &check_divisor_for_oddball);
// Convert {dividend} to a double and divide it with the value of
// {divisor}.
@@ -2369,11 +1566,11 @@ compiler::Node* ModulusWithFeedbackStub::Generate(
// Check if {dividend} is a HeapNumber.
assembler->GotoUnless(assembler->WordEqual(dividend_map, number_map),
- &call_modulus_stub);
+ &dividend_is_not_number);
// Check if {divisor} is a Smi.
Label divisor_is_smi(assembler), divisor_is_not_smi(assembler);
- assembler->Branch(assembler->WordIsSmi(divisor), &divisor_is_smi,
+ assembler->Branch(assembler->TaggedIsSmi(divisor), &divisor_is_smi,
&divisor_is_not_smi);
assembler->Bind(&divisor_is_smi);
@@ -2391,7 +1588,7 @@ compiler::Node* ModulusWithFeedbackStub::Generate(
// Check if {divisor} is a HeapNumber.
assembler->GotoUnless(assembler->WordEqual(divisor_map, number_map),
- &call_modulus_stub);
+ &check_divisor_for_oddball);
// Both {dividend} and {divisor} are HeapNumbers. Load their values
// and divide them.
@@ -2407,14 +1604,57 @@ compiler::Node* ModulusWithFeedbackStub::Generate(
assembler->Int32Constant(BinaryOperationFeedback::kNumber));
Node* value = assembler->Float64Mod(var_dividend_float64.value(),
var_divisor_float64.value());
- var_result.Bind(assembler->ChangeFloat64ToTagged(value));
+ var_result.Bind(assembler->AllocateHeapNumberWithValue(value));
assembler->Goto(&end);
}
- assembler->Bind(&call_modulus_stub);
+ assembler->Bind(&dividend_is_not_number);
+ {
+ // No checks on divisor yet. We just know dividend is not a number or Smi.
+ // Check if dividend is an oddball.
+ Node* dividend_instance_type = assembler->LoadInstanceType(dividend);
+ Node* dividend_is_oddball = assembler->Word32Equal(
+ dividend_instance_type, assembler->Int32Constant(ODDBALL_TYPE));
+ assembler->GotoUnless(dividend_is_oddball, &call_with_any_feedback);
+
+ assembler->GotoIf(assembler->TaggedIsSmi(divisor),
+ &call_with_oddball_feedback);
+
+ // Load the map of the {divisor}.
+ Node* divisor_map = assembler->LoadMap(divisor);
+
+ // Check if {divisor} is a HeapNumber.
+ assembler->Branch(assembler->IsHeapNumberMap(divisor_map),
+ &call_with_oddball_feedback, &check_divisor_for_oddball);
+ }
+
+ assembler->Bind(&check_divisor_for_oddball);
+ {
+ // Check if divisor is an oddball. At this point we know dividend is either
+ // a Smi or number or oddball and divisor is not a number or Smi.
+ Node* divisor_instance_type = assembler->LoadInstanceType(divisor);
+ Node* divisor_is_oddball = assembler->Word32Equal(
+ divisor_instance_type, assembler->Int32Constant(ODDBALL_TYPE));
+ assembler->Branch(divisor_is_oddball, &call_with_oddball_feedback,
+ &call_with_any_feedback);
+ }
+
+ assembler->Bind(&call_with_oddball_feedback);
+ {
+ var_type_feedback.Bind(
+ assembler->Int32Constant(BinaryOperationFeedback::kNumberOrOddball));
+ assembler->Goto(&call_modulus_stub);
+ }
+
+ assembler->Bind(&call_with_any_feedback);
{
var_type_feedback.Bind(
assembler->Int32Constant(BinaryOperationFeedback::kAny));
+ assembler->Goto(&call_modulus_stub);
+ }
+
+ assembler->Bind(&call_modulus_stub);
+ {
Callable callable = CodeFactory::Modulus(assembler->isolate());
var_result.Bind(assembler->CallStub(callable, context, dividend, divisor));
assembler->Goto(&end);
@@ -2425,95 +1665,6 @@ compiler::Node* ModulusWithFeedbackStub::Generate(
slot_id);
return var_result.value();
}
-// static
-compiler::Node* ShiftLeftStub::Generate(CodeStubAssembler* assembler,
- compiler::Node* left,
- compiler::Node* right,
- compiler::Node* context) {
- using compiler::Node;
-
- Node* lhs_value = assembler->TruncateTaggedToWord32(context, left);
- Node* rhs_value = assembler->TruncateTaggedToWord32(context, right);
- Node* shift_count =
- assembler->Word32And(rhs_value, assembler->Int32Constant(0x1f));
- Node* value = assembler->Word32Shl(lhs_value, shift_count);
- Node* result = assembler->ChangeInt32ToTagged(value);
- return result;
-}
-
-// static
-compiler::Node* ShiftRightStub::Generate(CodeStubAssembler* assembler,
- compiler::Node* left,
- compiler::Node* right,
- compiler::Node* context) {
- using compiler::Node;
-
- Node* lhs_value = assembler->TruncateTaggedToWord32(context, left);
- Node* rhs_value = assembler->TruncateTaggedToWord32(context, right);
- Node* shift_count =
- assembler->Word32And(rhs_value, assembler->Int32Constant(0x1f));
- Node* value = assembler->Word32Sar(lhs_value, shift_count);
- Node* result = assembler->ChangeInt32ToTagged(value);
- return result;
-}
-
-// static
-compiler::Node* ShiftRightLogicalStub::Generate(CodeStubAssembler* assembler,
- compiler::Node* left,
- compiler::Node* right,
- compiler::Node* context) {
- using compiler::Node;
-
- Node* lhs_value = assembler->TruncateTaggedToWord32(context, left);
- Node* rhs_value = assembler->TruncateTaggedToWord32(context, right);
- Node* shift_count =
- assembler->Word32And(rhs_value, assembler->Int32Constant(0x1f));
- Node* value = assembler->Word32Shr(lhs_value, shift_count);
- Node* result = assembler->ChangeUint32ToTagged(value);
- return result;
-}
-
-// static
-compiler::Node* BitwiseAndStub::Generate(CodeStubAssembler* assembler,
- compiler::Node* left,
- compiler::Node* right,
- compiler::Node* context) {
- using compiler::Node;
-
- Node* lhs_value = assembler->TruncateTaggedToWord32(context, left);
- Node* rhs_value = assembler->TruncateTaggedToWord32(context, right);
- Node* value = assembler->Word32And(lhs_value, rhs_value);
- Node* result = assembler->ChangeInt32ToTagged(value);
- return result;
-}
-
-// static
-compiler::Node* BitwiseOrStub::Generate(CodeStubAssembler* assembler,
- compiler::Node* left,
- compiler::Node* right,
- compiler::Node* context) {
- using compiler::Node;
-
- Node* lhs_value = assembler->TruncateTaggedToWord32(context, left);
- Node* rhs_value = assembler->TruncateTaggedToWord32(context, right);
- Node* value = assembler->Word32Or(lhs_value, rhs_value);
- Node* result = assembler->ChangeInt32ToTagged(value);
- return result;
-}
-
-// static
-compiler::Node* BitwiseXorStub::Generate(CodeStubAssembler* assembler,
- compiler::Node* left,
- compiler::Node* right,
- compiler::Node* context) {
- using compiler::Node;
-
- Node* lhs_value = assembler->TruncateTaggedToWord32(context, left);
- Node* rhs_value = assembler->TruncateTaggedToWord32(context, right);
- Node* value = assembler->Word32Xor(lhs_value, rhs_value);
- Node* result = assembler->ChangeInt32ToTagged(value);
- return result;
-}
// static
compiler::Node* IncStub::Generate(CodeStubAssembler* assembler,
@@ -2544,13 +1695,15 @@ compiler::Node* IncStub::Generate(CodeStubAssembler* assembler,
value = value_var.value();
Label if_issmi(assembler), if_isnotsmi(assembler);
- assembler->Branch(assembler->WordIsSmi(value), &if_issmi, &if_isnotsmi);
+ assembler->Branch(assembler->TaggedIsSmi(value), &if_issmi, &if_isnotsmi);
assembler->Bind(&if_issmi);
{
// Try fast Smi addition first.
Node* one = assembler->SmiConstant(Smi::FromInt(1));
- Node* pair = assembler->SmiAddWithOverflow(value, one);
+ Node* pair = assembler->IntPtrAddWithOverflow(
+ assembler->BitcastTaggedToWord(value),
+ assembler->BitcastTaggedToWord(one));
Node* overflow = assembler->Projection(1, pair);
// Check if the Smi addition overflowed.
@@ -2561,7 +1714,8 @@ compiler::Node* IncStub::Generate(CodeStubAssembler* assembler,
var_type_feedback.Bind(assembler->Word32Or(
var_type_feedback.value(),
assembler->Int32Constant(BinaryOperationFeedback::kSignedSmall)));
- result_var.Bind(assembler->Projection(0, pair));
+ result_var.Bind(
+ assembler->BitcastWordToTaggedSigned(assembler->Projection(0, pair)));
assembler->Goto(&end);
assembler->Bind(&if_overflow);
@@ -2589,13 +1743,40 @@ compiler::Node* IncStub::Generate(CodeStubAssembler* assembler,
assembler->Bind(&if_valuenotnumber);
{
- // Convert to a Number first and try again.
- Callable callable =
- CodeFactory::NonNumberToNumber(assembler->isolate());
- var_type_feedback.Bind(
- assembler->Int32Constant(BinaryOperationFeedback::kAny));
- value_var.Bind(assembler->CallStub(callable, context, value));
- assembler->Goto(&start);
+ // We do not require an Or with earlier feedback here because once we
+ // convert the value to a number, we cannot reach this path. We can
+ // only reach this path on the first pass when the feedback is kNone.
+ CSA_ASSERT(assembler,
+ assembler->Word32Equal(var_type_feedback.value(),
+ assembler->Int32Constant(
+ BinaryOperationFeedback::kNone)));
+
+ Label if_valueisoddball(assembler), if_valuenotoddball(assembler);
+ Node* instance_type = assembler->LoadMapInstanceType(value_map);
+ Node* is_oddball = assembler->Word32Equal(
+ instance_type, assembler->Int32Constant(ODDBALL_TYPE));
+ assembler->Branch(is_oddball, &if_valueisoddball, &if_valuenotoddball);
+
+ assembler->Bind(&if_valueisoddball);
+ {
+ // Convert Oddball to Number and check again.
+ value_var.Bind(
+ assembler->LoadObjectField(value, Oddball::kToNumberOffset));
+ var_type_feedback.Bind(assembler->Int32Constant(
+ BinaryOperationFeedback::kNumberOrOddball));
+ assembler->Goto(&start);
+ }
+
+ assembler->Bind(&if_valuenotoddball);
+ {
+ // Convert to a Number first and try again.
+ Callable callable =
+ CodeFactory::NonNumberToNumber(assembler->isolate());
+ var_type_feedback.Bind(
+ assembler->Int32Constant(BinaryOperationFeedback::kAny));
+ value_var.Bind(assembler->CallStub(callable, context, value));
+ assembler->Goto(&start);
+ }
}
}
}
@@ -2608,7 +1789,7 @@ compiler::Node* IncStub::Generate(CodeStubAssembler* assembler,
var_type_feedback.Bind(assembler->Word32Or(
var_type_feedback.value(),
assembler->Int32Constant(BinaryOperationFeedback::kNumber)));
- result_var.Bind(assembler->ChangeFloat64ToTagged(finc_result));
+ result_var.Bind(assembler->AllocateHeapNumberWithValue(finc_result));
assembler->Goto(&end);
}
@@ -2618,6 +1799,13 @@ compiler::Node* IncStub::Generate(CodeStubAssembler* assembler,
return result_var.value();
}
+void NumberToStringStub::GenerateAssembly(CodeStubAssembler* assembler) const {
+ typedef compiler::Node Node;
+ Node* argument = assembler->Parameter(Descriptor::kArgument);
+ Node* context = assembler->Parameter(Descriptor::kContext);
+ assembler->Return(assembler->NumberToString(context, argument));
+}
+
// static
compiler::Node* DecStub::Generate(CodeStubAssembler* assembler,
compiler::Node* value,
@@ -2647,13 +1835,15 @@ compiler::Node* DecStub::Generate(CodeStubAssembler* assembler,
value = value_var.value();
Label if_issmi(assembler), if_isnotsmi(assembler);
- assembler->Branch(assembler->WordIsSmi(value), &if_issmi, &if_isnotsmi);
+ assembler->Branch(assembler->TaggedIsSmi(value), &if_issmi, &if_isnotsmi);
assembler->Bind(&if_issmi);
{
// Try fast Smi subtraction first.
Node* one = assembler->SmiConstant(Smi::FromInt(1));
- Node* pair = assembler->SmiSubWithOverflow(value, one);
+ Node* pair = assembler->IntPtrSubWithOverflow(
+ assembler->BitcastTaggedToWord(value),
+ assembler->BitcastTaggedToWord(one));
Node* overflow = assembler->Projection(1, pair);
// Check if the Smi subtraction overflowed.
@@ -2664,7 +1854,8 @@ compiler::Node* DecStub::Generate(CodeStubAssembler* assembler,
var_type_feedback.Bind(assembler->Word32Or(
var_type_feedback.value(),
assembler->Int32Constant(BinaryOperationFeedback::kSignedSmall)));
- result_var.Bind(assembler->Projection(0, pair));
+ result_var.Bind(
+ assembler->BitcastWordToTaggedSigned(assembler->Projection(0, pair)));
assembler->Goto(&end);
assembler->Bind(&if_overflow);
@@ -2692,13 +1883,40 @@ compiler::Node* DecStub::Generate(CodeStubAssembler* assembler,
assembler->Bind(&if_valuenotnumber);
{
- // Convert to a Number first and try again.
- Callable callable =
- CodeFactory::NonNumberToNumber(assembler->isolate());
- var_type_feedback.Bind(
- assembler->Int32Constant(BinaryOperationFeedback::kAny));
- value_var.Bind(assembler->CallStub(callable, context, value));
- assembler->Goto(&start);
+ // We do not require an Or with earlier feedback here because once we
+ // convert the value to a number, we cannot reach this path. We can
+ // only reach this path on the first pass when the feedback is kNone.
+ CSA_ASSERT(assembler,
+ assembler->Word32Equal(var_type_feedback.value(),
+ assembler->Int32Constant(
+ BinaryOperationFeedback::kNone)));
+
+ Label if_valueisoddball(assembler), if_valuenotoddball(assembler);
+ Node* instance_type = assembler->LoadMapInstanceType(value_map);
+ Node* is_oddball = assembler->Word32Equal(
+ instance_type, assembler->Int32Constant(ODDBALL_TYPE));
+ assembler->Branch(is_oddball, &if_valueisoddball, &if_valuenotoddball);
+
+ assembler->Bind(&if_valueisoddball);
+ {
+ // Convert Oddball to Number and check again.
+ value_var.Bind(
+ assembler->LoadObjectField(value, Oddball::kToNumberOffset));
+ var_type_feedback.Bind(assembler->Int32Constant(
+ BinaryOperationFeedback::kNumberOrOddball));
+ assembler->Goto(&start);
+ }
+
+ assembler->Bind(&if_valuenotoddball);
+ {
+ // Convert to a Number first and try again.
+ Callable callable =
+ CodeFactory::NonNumberToNumber(assembler->isolate());
+ var_type_feedback.Bind(
+ assembler->Int32Constant(BinaryOperationFeedback::kAny));
+ value_var.Bind(assembler->CallStub(callable, context, value));
+ assembler->Goto(&start);
+ }
}
}
}
@@ -2711,7 +1929,7 @@ compiler::Node* DecStub::Generate(CodeStubAssembler* assembler,
var_type_feedback.Bind(assembler->Word32Or(
var_type_feedback.value(),
assembler->Int32Constant(BinaryOperationFeedback::kNumber)));
- result_var.Bind(assembler->ChangeFloat64ToTagged(fdec_result));
+ result_var.Bind(assembler->AllocateHeapNumberWithValue(fdec_result));
assembler->Goto(&end);
}
@@ -2730,1439 +1948,6 @@ compiler::Node* SubStringStub::Generate(CodeStubAssembler* assembler,
return assembler->SubString(context, string, from, to);
}
-// ES6 section 7.1.13 ToObject (argument)
-void ToObjectStub::GenerateAssembly(CodeStubAssembler* assembler) const {
- typedef compiler::Node Node;
- typedef CodeStubAssembler::Label Label;
- typedef CodeStubAssembler::Variable Variable;
-
- Label if_number(assembler, Label::kDeferred), if_notsmi(assembler),
- if_jsreceiver(assembler), if_noconstructor(assembler, Label::kDeferred),
- if_wrapjsvalue(assembler);
-
- Node* object = assembler->Parameter(Descriptor::kArgument);
- Node* context = assembler->Parameter(Descriptor::kContext);
-
- Variable constructor_function_index_var(assembler,
- MachineType::PointerRepresentation());
-
- assembler->Branch(assembler->WordIsSmi(object), &if_number, &if_notsmi);
-
- assembler->Bind(&if_notsmi);
- Node* map = assembler->LoadMap(object);
-
- assembler->GotoIf(assembler->IsHeapNumberMap(map), &if_number);
-
- Node* instance_type = assembler->LoadMapInstanceType(map);
- assembler->GotoIf(assembler->IsJSReceiverInstanceType(instance_type),
- &if_jsreceiver);
-
- Node* constructor_function_index =
- assembler->LoadMapConstructorFunctionIndex(map);
- assembler->GotoIf(assembler->WordEqual(constructor_function_index,
- assembler->IntPtrConstant(
- Map::kNoConstructorFunctionIndex)),
- &if_noconstructor);
- constructor_function_index_var.Bind(constructor_function_index);
- assembler->Goto(&if_wrapjsvalue);
-
- assembler->Bind(&if_number);
- constructor_function_index_var.Bind(
- assembler->IntPtrConstant(Context::NUMBER_FUNCTION_INDEX));
- assembler->Goto(&if_wrapjsvalue);
-
- assembler->Bind(&if_wrapjsvalue);
- Node* native_context = assembler->LoadNativeContext(context);
- Node* constructor = assembler->LoadFixedArrayElement(
- native_context, constructor_function_index_var.value(), 0,
- CodeStubAssembler::INTPTR_PARAMETERS);
- Node* initial_map = assembler->LoadObjectField(
- constructor, JSFunction::kPrototypeOrInitialMapOffset);
- Node* js_value = assembler->Allocate(JSValue::kSize);
- assembler->StoreMapNoWriteBarrier(js_value, initial_map);
- assembler->StoreObjectFieldRoot(js_value, JSValue::kPropertiesOffset,
- Heap::kEmptyFixedArrayRootIndex);
- assembler->StoreObjectFieldRoot(js_value, JSObject::kElementsOffset,
- Heap::kEmptyFixedArrayRootIndex);
- assembler->StoreObjectField(js_value, JSValue::kValueOffset, object);
- assembler->Return(js_value);
-
- assembler->Bind(&if_noconstructor);
- assembler->TailCallRuntime(
- Runtime::kThrowUndefinedOrNullToObject, context,
- assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked(
- "ToObject", TENURED)));
-
- assembler->Bind(&if_jsreceiver);
- assembler->Return(object);
-}
-
-// static
-// ES6 section 12.5.5 typeof operator
-compiler::Node* TypeofStub::Generate(CodeStubAssembler* assembler,
- compiler::Node* value,
- compiler::Node* context) {
- typedef compiler::Node Node;
- typedef CodeStubAssembler::Label Label;
- typedef CodeStubAssembler::Variable Variable;
-
- Variable result_var(assembler, MachineRepresentation::kTagged);
-
- Label return_number(assembler, Label::kDeferred), if_oddball(assembler),
- return_function(assembler), return_undefined(assembler),
- return_object(assembler), return_string(assembler),
- return_result(assembler);
-
- assembler->GotoIf(assembler->WordIsSmi(value), &return_number);
-
- Node* map = assembler->LoadMap(value);
-
- assembler->GotoIf(assembler->IsHeapNumberMap(map), &return_number);
-
- Node* instance_type = assembler->LoadMapInstanceType(map);
-
- assembler->GotoIf(assembler->Word32Equal(
- instance_type, assembler->Int32Constant(ODDBALL_TYPE)),
- &if_oddball);
-
- Node* callable_or_undetectable_mask =
- assembler->Word32And(assembler->LoadMapBitField(map),
- assembler->Int32Constant(1 << Map::kIsCallable |
- 1 << Map::kIsUndetectable));
-
- assembler->GotoIf(
- assembler->Word32Equal(callable_or_undetectable_mask,
- assembler->Int32Constant(1 << Map::kIsCallable)),
- &return_function);
-
- assembler->GotoUnless(assembler->Word32Equal(callable_or_undetectable_mask,
- assembler->Int32Constant(0)),
- &return_undefined);
-
- assembler->GotoIf(assembler->IsJSReceiverInstanceType(instance_type),
- &return_object);
-
- assembler->GotoIf(assembler->IsStringInstanceType(instance_type),
- &return_string);
-
-#define SIMD128_BRANCH(TYPE, Type, type, lane_count, lane_type) \
- Label return_##type(assembler); \
- Node* type##_map = \
- assembler->HeapConstant(assembler->factory()->type##_map()); \
- assembler->GotoIf(assembler->WordEqual(map, type##_map), &return_##type);
- SIMD128_TYPES(SIMD128_BRANCH)
-#undef SIMD128_BRANCH
-
- assembler->Assert(assembler->Word32Equal(
- instance_type, assembler->Int32Constant(SYMBOL_TYPE)));
- result_var.Bind(assembler->HeapConstant(
- assembler->isolate()->factory()->symbol_string()));
- assembler->Goto(&return_result);
-
- assembler->Bind(&return_number);
- {
- result_var.Bind(assembler->HeapConstant(
- assembler->isolate()->factory()->number_string()));
- assembler->Goto(&return_result);
- }
-
- assembler->Bind(&if_oddball);
- {
- Node* type = assembler->LoadObjectField(value, Oddball::kTypeOfOffset);
- result_var.Bind(type);
- assembler->Goto(&return_result);
- }
-
- assembler->Bind(&return_function);
- {
- result_var.Bind(assembler->HeapConstant(
- assembler->isolate()->factory()->function_string()));
- assembler->Goto(&return_result);
- }
-
- assembler->Bind(&return_undefined);
- {
- result_var.Bind(assembler->HeapConstant(
- assembler->isolate()->factory()->undefined_string()));
- assembler->Goto(&return_result);
- }
-
- assembler->Bind(&return_object);
- {
- result_var.Bind(assembler->HeapConstant(
- assembler->isolate()->factory()->object_string()));
- assembler->Goto(&return_result);
- }
-
- assembler->Bind(&return_string);
- {
- result_var.Bind(assembler->HeapConstant(
- assembler->isolate()->factory()->string_string()));
- assembler->Goto(&return_result);
- }
-
-#define SIMD128_BIND_RETURN(TYPE, Type, type, lane_count, lane_type) \
- assembler->Bind(&return_##type); \
- { \
- result_var.Bind(assembler->HeapConstant( \
- assembler->isolate()->factory()->type##_string())); \
- assembler->Goto(&return_result); \
- }
- SIMD128_TYPES(SIMD128_BIND_RETURN)
-#undef SIMD128_BIND_RETURN
-
- assembler->Bind(&return_result);
- return result_var.value();
-}
-
-// static
-compiler::Node* InstanceOfStub::Generate(CodeStubAssembler* assembler,
- compiler::Node* object,
- compiler::Node* callable,
- compiler::Node* context) {
- typedef CodeStubAssembler::Label Label;
- typedef CodeStubAssembler::Variable Variable;
-
- Label return_runtime(assembler, Label::kDeferred), end(assembler);
- Variable result(assembler, MachineRepresentation::kTagged);
-
- // Check if no one installed @@hasInstance somewhere.
- assembler->GotoUnless(
- assembler->WordEqual(
- assembler->LoadObjectField(
- assembler->LoadRoot(Heap::kHasInstanceProtectorRootIndex),
- PropertyCell::kValueOffset),
- assembler->SmiConstant(Smi::FromInt(Isolate::kArrayProtectorValid))),
- &return_runtime);
-
- // Check if {callable} is a valid receiver.
- assembler->GotoIf(assembler->WordIsSmi(callable), &return_runtime);
- assembler->GotoIf(
- assembler->Word32Equal(
- assembler->Word32And(
- assembler->LoadMapBitField(assembler->LoadMap(callable)),
- assembler->Int32Constant(1 << Map::kIsCallable)),
- assembler->Int32Constant(0)),
- &return_runtime);
-
- // Use the inline OrdinaryHasInstance directly.
- result.Bind(assembler->OrdinaryHasInstance(context, callable, object));
- assembler->Goto(&end);
-
- // TODO(bmeurer): Use GetPropertyStub here once available.
- assembler->Bind(&return_runtime);
- {
- result.Bind(assembler->CallRuntime(Runtime::kInstanceOf, context, object,
- callable));
- assembler->Goto(&end);
- }
-
- assembler->Bind(&end);
- return result.value();
-}
-
-namespace {
-
-enum RelationalComparisonMode {
- kLessThan,
- kLessThanOrEqual,
- kGreaterThan,
- kGreaterThanOrEqual
-};
-
-compiler::Node* GenerateAbstractRelationalComparison(
- CodeStubAssembler* assembler, RelationalComparisonMode mode,
- compiler::Node* lhs, compiler::Node* rhs, compiler::Node* context) {
- typedef CodeStubAssembler::Label Label;
- typedef compiler::Node Node;
- typedef CodeStubAssembler::Variable Variable;
-
- Label return_true(assembler), return_false(assembler), end(assembler);
- Variable result(assembler, MachineRepresentation::kTagged);
-
- // Shared entry for floating point comparison.
- Label do_fcmp(assembler);
- Variable var_fcmp_lhs(assembler, MachineRepresentation::kFloat64),
- var_fcmp_rhs(assembler, MachineRepresentation::kFloat64);
-
- // We might need to loop several times due to ToPrimitive and/or ToNumber
- // conversions.
- Variable var_lhs(assembler, MachineRepresentation::kTagged),
- var_rhs(assembler, MachineRepresentation::kTagged);
- Variable* loop_vars[2] = {&var_lhs, &var_rhs};
- Label loop(assembler, 2, loop_vars);
- var_lhs.Bind(lhs);
- var_rhs.Bind(rhs);
- assembler->Goto(&loop);
- assembler->Bind(&loop);
- {
- // Load the current {lhs} and {rhs} values.
- lhs = var_lhs.value();
- rhs = var_rhs.value();
-
- // Check if the {lhs} is a Smi or a HeapObject.
- Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler);
- assembler->Branch(assembler->WordIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi);
-
- assembler->Bind(&if_lhsissmi);
- {
- // Check if {rhs} is a Smi or a HeapObject.
- Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler);
- assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi,
- &if_rhsisnotsmi);
-
- assembler->Bind(&if_rhsissmi);
- {
- // Both {lhs} and {rhs} are Smi, so just perform a fast Smi comparison.
- switch (mode) {
- case kLessThan:
- assembler->BranchIfSmiLessThan(lhs, rhs, &return_true,
- &return_false);
- break;
- case kLessThanOrEqual:
- assembler->BranchIfSmiLessThanOrEqual(lhs, rhs, &return_true,
- &return_false);
- break;
- case kGreaterThan:
- assembler->BranchIfSmiLessThan(rhs, lhs, &return_true,
- &return_false);
- break;
- case kGreaterThanOrEqual:
- assembler->BranchIfSmiLessThanOrEqual(rhs, lhs, &return_true,
- &return_false);
- break;
- }
- }
-
- assembler->Bind(&if_rhsisnotsmi);
- {
- // Load the map of {rhs}.
- Node* rhs_map = assembler->LoadMap(rhs);
-
- // Check if the {rhs} is a HeapNumber.
- Label if_rhsisnumber(assembler),
- if_rhsisnotnumber(assembler, Label::kDeferred);
- assembler->Branch(assembler->IsHeapNumberMap(rhs_map), &if_rhsisnumber,
- &if_rhsisnotnumber);
-
- assembler->Bind(&if_rhsisnumber);
- {
- // Convert the {lhs} and {rhs} to floating point values, and
- // perform a floating point comparison.
- var_fcmp_lhs.Bind(assembler->SmiToFloat64(lhs));
- var_fcmp_rhs.Bind(assembler->LoadHeapNumberValue(rhs));
- assembler->Goto(&do_fcmp);
- }
-
- assembler->Bind(&if_rhsisnotnumber);
- {
- // Convert the {rhs} to a Number; we don't need to perform the
- // dedicated ToPrimitive(rhs, hint Number) operation, as the
- // ToNumber(rhs) will by itself already invoke ToPrimitive with
- // a Number hint.
- Callable callable =
- CodeFactory::NonNumberToNumber(assembler->isolate());
- var_rhs.Bind(assembler->CallStub(callable, context, rhs));
- assembler->Goto(&loop);
- }
- }
- }
-
- assembler->Bind(&if_lhsisnotsmi);
- {
- // Load the HeapNumber map for later comparisons.
- Node* number_map = assembler->HeapNumberMapConstant();
-
- // Load the map of {lhs}.
- Node* lhs_map = assembler->LoadMap(lhs);
-
- // Check if {rhs} is a Smi or a HeapObject.
- Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler);
- assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi,
- &if_rhsisnotsmi);
-
- assembler->Bind(&if_rhsissmi);
- {
- // Check if the {lhs} is a HeapNumber.
- Label if_lhsisnumber(assembler),
- if_lhsisnotnumber(assembler, Label::kDeferred);
- assembler->Branch(assembler->WordEqual(lhs_map, number_map),
- &if_lhsisnumber, &if_lhsisnotnumber);
-
- assembler->Bind(&if_lhsisnumber);
- {
- // Convert the {lhs} and {rhs} to floating point values, and
- // perform a floating point comparison.
- var_fcmp_lhs.Bind(assembler->LoadHeapNumberValue(lhs));
- var_fcmp_rhs.Bind(assembler->SmiToFloat64(rhs));
- assembler->Goto(&do_fcmp);
- }
-
- assembler->Bind(&if_lhsisnotnumber);
- {
- // Convert the {lhs} to a Number; we don't need to perform the
- // dedicated ToPrimitive(lhs, hint Number) operation, as the
- // ToNumber(lhs) will by itself already invoke ToPrimitive with
- // a Number hint.
- Callable callable =
- CodeFactory::NonNumberToNumber(assembler->isolate());
- var_lhs.Bind(assembler->CallStub(callable, context, lhs));
- assembler->Goto(&loop);
- }
- }
-
- assembler->Bind(&if_rhsisnotsmi);
- {
- // Load the map of {rhs}.
- Node* rhs_map = assembler->LoadMap(rhs);
-
- // Check if {lhs} is a HeapNumber.
- Label if_lhsisnumber(assembler), if_lhsisnotnumber(assembler);
- assembler->Branch(assembler->WordEqual(lhs_map, number_map),
- &if_lhsisnumber, &if_lhsisnotnumber);
-
- assembler->Bind(&if_lhsisnumber);
- {
- // Check if {rhs} is also a HeapNumber.
- Label if_rhsisnumber(assembler),
- if_rhsisnotnumber(assembler, Label::kDeferred);
- assembler->Branch(assembler->WordEqual(lhs_map, rhs_map),
- &if_rhsisnumber, &if_rhsisnotnumber);
-
- assembler->Bind(&if_rhsisnumber);
- {
- // Convert the {lhs} and {rhs} to floating point values, and
- // perform a floating point comparison.
- var_fcmp_lhs.Bind(assembler->LoadHeapNumberValue(lhs));
- var_fcmp_rhs.Bind(assembler->LoadHeapNumberValue(rhs));
- assembler->Goto(&do_fcmp);
- }
-
- assembler->Bind(&if_rhsisnotnumber);
- {
- // Convert the {rhs} to a Number; we don't need to perform
- // dedicated ToPrimitive(rhs, hint Number) operation, as the
- // ToNumber(rhs) will by itself already invoke ToPrimitive with
- // a Number hint.
- Callable callable =
- CodeFactory::NonNumberToNumber(assembler->isolate());
- var_rhs.Bind(assembler->CallStub(callable, context, rhs));
- assembler->Goto(&loop);
- }
- }
-
- assembler->Bind(&if_lhsisnotnumber);
- {
- // Load the instance type of {lhs}.
- Node* lhs_instance_type = assembler->LoadMapInstanceType(lhs_map);
-
- // Check if {lhs} is a String.
- Label if_lhsisstring(assembler),
- if_lhsisnotstring(assembler, Label::kDeferred);
- assembler->Branch(assembler->IsStringInstanceType(lhs_instance_type),
- &if_lhsisstring, &if_lhsisnotstring);
-
- assembler->Bind(&if_lhsisstring);
- {
- // Load the instance type of {rhs}.
- Node* rhs_instance_type = assembler->LoadMapInstanceType(rhs_map);
-
- // Check if {rhs} is also a String.
- Label if_rhsisstring(assembler, Label::kDeferred),
- if_rhsisnotstring(assembler, Label::kDeferred);
- assembler->Branch(
- assembler->IsStringInstanceType(rhs_instance_type),
- &if_rhsisstring, &if_rhsisnotstring);
-
- assembler->Bind(&if_rhsisstring);
- {
- // Both {lhs} and {rhs} are strings.
- switch (mode) {
- case kLessThan:
- result.Bind(assembler->CallStub(
- CodeFactory::StringLessThan(assembler->isolate()),
- context, lhs, rhs));
- assembler->Goto(&end);
- break;
- case kLessThanOrEqual:
- result.Bind(assembler->CallStub(
- CodeFactory::StringLessThanOrEqual(assembler->isolate()),
- context, lhs, rhs));
- assembler->Goto(&end);
- break;
- case kGreaterThan:
- result.Bind(assembler->CallStub(
- CodeFactory::StringGreaterThan(assembler->isolate()),
- context, lhs, rhs));
- assembler->Goto(&end);
- break;
- case kGreaterThanOrEqual:
- result.Bind(
- assembler->CallStub(CodeFactory::StringGreaterThanOrEqual(
- assembler->isolate()),
- context, lhs, rhs));
- assembler->Goto(&end);
- break;
- }
- }
-
- assembler->Bind(&if_rhsisnotstring);
- {
- // The {lhs} is a String, while {rhs} is neither a Number nor a
- // String, so we need to call ToPrimitive(rhs, hint Number) if
- // {rhs} is a receiver or ToNumber(lhs) and ToNumber(rhs) in the
- // other cases.
- STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
- Label if_rhsisreceiver(assembler, Label::kDeferred),
- if_rhsisnotreceiver(assembler, Label::kDeferred);
- assembler->Branch(
- assembler->IsJSReceiverInstanceType(rhs_instance_type),
- &if_rhsisreceiver, &if_rhsisnotreceiver);
-
- assembler->Bind(&if_rhsisreceiver);
- {
- // Convert {rhs} to a primitive first passing Number hint.
- Callable callable = CodeFactory::NonPrimitiveToPrimitive(
- assembler->isolate(), ToPrimitiveHint::kNumber);
- var_rhs.Bind(assembler->CallStub(callable, context, rhs));
- assembler->Goto(&loop);
- }
-
- assembler->Bind(&if_rhsisnotreceiver);
- {
- // Convert both {lhs} and {rhs} to Number.
- Callable callable = CodeFactory::ToNumber(assembler->isolate());
- var_lhs.Bind(assembler->CallStub(callable, context, lhs));
- var_rhs.Bind(assembler->CallStub(callable, context, rhs));
- assembler->Goto(&loop);
- }
- }
- }
-
- assembler->Bind(&if_lhsisnotstring);
- {
- // The {lhs} is neither a Number nor a String, so we need to call
- // ToPrimitive(lhs, hint Number) if {lhs} is a receiver or
- // ToNumber(lhs) and ToNumber(rhs) in the other cases.
- STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
- Label if_lhsisreceiver(assembler, Label::kDeferred),
- if_lhsisnotreceiver(assembler, Label::kDeferred);
- assembler->Branch(
- assembler->IsJSReceiverInstanceType(lhs_instance_type),
- &if_lhsisreceiver, &if_lhsisnotreceiver);
-
- assembler->Bind(&if_lhsisreceiver);
- {
- // Convert {lhs} to a primitive first passing Number hint.
- Callable callable = CodeFactory::NonPrimitiveToPrimitive(
- assembler->isolate(), ToPrimitiveHint::kNumber);
- var_lhs.Bind(assembler->CallStub(callable, context, lhs));
- assembler->Goto(&loop);
- }
-
- assembler->Bind(&if_lhsisnotreceiver);
- {
- // Convert both {lhs} and {rhs} to Number.
- Callable callable = CodeFactory::ToNumber(assembler->isolate());
- var_lhs.Bind(assembler->CallStub(callable, context, lhs));
- var_rhs.Bind(assembler->CallStub(callable, context, rhs));
- assembler->Goto(&loop);
- }
- }
- }
- }
- }
- }
-
- assembler->Bind(&do_fcmp);
- {
- // Load the {lhs} and {rhs} floating point values.
- Node* lhs = var_fcmp_lhs.value();
- Node* rhs = var_fcmp_rhs.value();
-
- // Perform a fast floating point comparison.
- switch (mode) {
- case kLessThan:
- assembler->BranchIfFloat64LessThan(lhs, rhs, &return_true,
- &return_false);
- break;
- case kLessThanOrEqual:
- assembler->BranchIfFloat64LessThanOrEqual(lhs, rhs, &return_true,
- &return_false);
- break;
- case kGreaterThan:
- assembler->BranchIfFloat64GreaterThan(lhs, rhs, &return_true,
- &return_false);
- break;
- case kGreaterThanOrEqual:
- assembler->BranchIfFloat64GreaterThanOrEqual(lhs, rhs, &return_true,
- &return_false);
- break;
- }
- }
-
- assembler->Bind(&return_true);
- {
- result.Bind(assembler->BooleanConstant(true));
- assembler->Goto(&end);
- }
-
- assembler->Bind(&return_false);
- {
- result.Bind(assembler->BooleanConstant(false));
- assembler->Goto(&end);
- }
-
- assembler->Bind(&end);
- return result.value();
-}
-
-enum ResultMode { kDontNegateResult, kNegateResult };
-
-void GenerateEqual_Same(CodeStubAssembler* assembler, compiler::Node* value,
- CodeStubAssembler::Label* if_equal,
- CodeStubAssembler::Label* if_notequal) {
- // In case of abstract or strict equality checks, we need additional checks
- // for NaN values because they are not considered equal, even if both the
- // left and the right hand side reference exactly the same value.
- // TODO(bmeurer): This seems to violate the SIMD.js specification, but it
- // seems to be what is tested in the current SIMD.js testsuite.
-
- typedef CodeStubAssembler::Label Label;
- typedef compiler::Node Node;
-
- // Check if {value} is a Smi or a HeapObject.
- Label if_valueissmi(assembler), if_valueisnotsmi(assembler);
- assembler->Branch(assembler->WordIsSmi(value), &if_valueissmi,
- &if_valueisnotsmi);
-
- assembler->Bind(&if_valueisnotsmi);
- {
- // Load the map of {value}.
- Node* value_map = assembler->LoadMap(value);
-
- // Check if {value} (and therefore {rhs}) is a HeapNumber.
- Label if_valueisnumber(assembler), if_valueisnotnumber(assembler);
- assembler->Branch(assembler->IsHeapNumberMap(value_map), &if_valueisnumber,
- &if_valueisnotnumber);
-
- assembler->Bind(&if_valueisnumber);
- {
- // Convert {value} (and therefore {rhs}) to floating point value.
- Node* value_value = assembler->LoadHeapNumberValue(value);
-
- // Check if the HeapNumber value is a NaN.
- assembler->BranchIfFloat64IsNaN(value_value, if_notequal, if_equal);
- }
-
- assembler->Bind(&if_valueisnotnumber);
- assembler->Goto(if_equal);
- }
-
- assembler->Bind(&if_valueissmi);
- assembler->Goto(if_equal);
-}
-
-void GenerateEqual_Simd128Value_HeapObject(
- CodeStubAssembler* assembler, compiler::Node* lhs, compiler::Node* lhs_map,
- compiler::Node* rhs, compiler::Node* rhs_map,
- CodeStubAssembler::Label* if_equal, CodeStubAssembler::Label* if_notequal) {
- assembler->BranchIfSimd128Equal(lhs, lhs_map, rhs, rhs_map, if_equal,
- if_notequal);
-}
-
-// ES6 section 7.2.12 Abstract Equality Comparison
-compiler::Node* GenerateEqual(CodeStubAssembler* assembler, ResultMode mode,
- compiler::Node* lhs, compiler::Node* rhs,
- compiler::Node* context) {
- // This is a slightly optimized version of Object::Equals represented as
- // scheduled TurboFan graph utilizing the CodeStubAssembler. Whenever you
- // change something functionality wise in here, remember to update the
- // Object::Equals method as well.
- typedef CodeStubAssembler::Label Label;
- typedef compiler::Node Node;
- typedef CodeStubAssembler::Variable Variable;
-
- Label if_equal(assembler), if_notequal(assembler),
- do_rhsstringtonumber(assembler, Label::kDeferred), end(assembler);
- Variable result(assembler, MachineRepresentation::kTagged);
-
- // Shared entry for floating point comparison.
- Label do_fcmp(assembler);
- Variable var_fcmp_lhs(assembler, MachineRepresentation::kFloat64),
- var_fcmp_rhs(assembler, MachineRepresentation::kFloat64);
-
- // We might need to loop several times due to ToPrimitive and/or ToNumber
- // conversions.
- Variable var_lhs(assembler, MachineRepresentation::kTagged),
- var_rhs(assembler, MachineRepresentation::kTagged);
- Variable* loop_vars[2] = {&var_lhs, &var_rhs};
- Label loop(assembler, 2, loop_vars);
- var_lhs.Bind(lhs);
- var_rhs.Bind(rhs);
- assembler->Goto(&loop);
- assembler->Bind(&loop);
- {
- // Load the current {lhs} and {rhs} values.
- lhs = var_lhs.value();
- rhs = var_rhs.value();
-
- // Check if {lhs} and {rhs} refer to the same object.
- Label if_same(assembler), if_notsame(assembler);
- assembler->Branch(assembler->WordEqual(lhs, rhs), &if_same, &if_notsame);
-
- assembler->Bind(&if_same);
- {
- // The {lhs} and {rhs} reference the exact same value, yet we need special
- // treatment for HeapNumber, as NaN is not equal to NaN.
- GenerateEqual_Same(assembler, lhs, &if_equal, &if_notequal);
- }
-
- assembler->Bind(&if_notsame);
- {
- // Check if {lhs} is a Smi or a HeapObject.
- Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler);
- assembler->Branch(assembler->WordIsSmi(lhs), &if_lhsissmi,
- &if_lhsisnotsmi);
-
- assembler->Bind(&if_lhsissmi);
- {
- // Check if {rhs} is a Smi or a HeapObject.
- Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler);
- assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi,
- &if_rhsisnotsmi);
-
- assembler->Bind(&if_rhsissmi);
- // We have already checked for {lhs} and {rhs} being the same value, so
- // if both are Smis when we get here they must not be equal.
- assembler->Goto(&if_notequal);
-
- assembler->Bind(&if_rhsisnotsmi);
- {
- // Load the map of {rhs}.
- Node* rhs_map = assembler->LoadMap(rhs);
-
- // Check if {rhs} is a HeapNumber.
- Node* number_map = assembler->HeapNumberMapConstant();
- Label if_rhsisnumber(assembler), if_rhsisnotnumber(assembler);
- assembler->Branch(assembler->WordEqual(rhs_map, number_map),
- &if_rhsisnumber, &if_rhsisnotnumber);
-
- assembler->Bind(&if_rhsisnumber);
- {
- // Convert {lhs} and {rhs} to floating point values, and
- // perform a floating point comparison.
- var_fcmp_lhs.Bind(assembler->SmiToFloat64(lhs));
- var_fcmp_rhs.Bind(assembler->LoadHeapNumberValue(rhs));
- assembler->Goto(&do_fcmp);
- }
-
- assembler->Bind(&if_rhsisnotnumber);
- {
- // Load the instance type of the {rhs}.
- Node* rhs_instance_type = assembler->LoadMapInstanceType(rhs_map);
-
- // Check if the {rhs} is a String.
- Label if_rhsisstring(assembler, Label::kDeferred),
- if_rhsisnotstring(assembler);
- assembler->Branch(
- assembler->IsStringInstanceType(rhs_instance_type),
- &if_rhsisstring, &if_rhsisnotstring);
-
- assembler->Bind(&if_rhsisstring);
- {
- // The {rhs} is a String and the {lhs} is a Smi; we need
- // to convert the {rhs} to a Number and compare the output to
- // the Number on the {lhs}.
- assembler->Goto(&do_rhsstringtonumber);
- }
-
- assembler->Bind(&if_rhsisnotstring);
- {
- // Check if the {rhs} is a Boolean.
- Label if_rhsisboolean(assembler), if_rhsisnotboolean(assembler);
- assembler->Branch(assembler->IsBooleanMap(rhs_map),
- &if_rhsisboolean, &if_rhsisnotboolean);
-
- assembler->Bind(&if_rhsisboolean);
- {
- // The {rhs} is a Boolean, load its number value.
- var_rhs.Bind(
- assembler->LoadObjectField(rhs, Oddball::kToNumberOffset));
- assembler->Goto(&loop);
- }
-
- assembler->Bind(&if_rhsisnotboolean);
- {
- // Check if the {rhs} is a Receiver.
- STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
- Label if_rhsisreceiver(assembler, Label::kDeferred),
- if_rhsisnotreceiver(assembler);
- assembler->Branch(
- assembler->IsJSReceiverInstanceType(rhs_instance_type),
- &if_rhsisreceiver, &if_rhsisnotreceiver);
-
- assembler->Bind(&if_rhsisreceiver);
- {
- // Convert {rhs} to a primitive first (passing no hint).
- Callable callable = CodeFactory::NonPrimitiveToPrimitive(
- assembler->isolate());
- var_rhs.Bind(assembler->CallStub(callable, context, rhs));
- assembler->Goto(&loop);
- }
-
- assembler->Bind(&if_rhsisnotreceiver);
- assembler->Goto(&if_notequal);
- }
- }
- }
- }
- }
-
- assembler->Bind(&if_lhsisnotsmi);
- {
- // Check if {rhs} is a Smi or a HeapObject.
- Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler);
- assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi,
- &if_rhsisnotsmi);
-
- assembler->Bind(&if_rhsissmi);
- {
- // The {lhs} is a HeapObject and the {rhs} is a Smi; swapping {lhs}
- // and {rhs} is not observable and doesn't matter for the result, so
- // we can just swap them and use the Smi handling above (for {lhs}
- // being a Smi).
- var_lhs.Bind(rhs);
- var_rhs.Bind(lhs);
- assembler->Goto(&loop);
- }
-
- assembler->Bind(&if_rhsisnotsmi);
- {
- Label if_lhsisstring(assembler), if_lhsisnumber(assembler),
- if_lhsissymbol(assembler), if_lhsissimd128value(assembler),
- if_lhsisoddball(assembler), if_lhsisreceiver(assembler);
-
- // Both {lhs} and {rhs} are HeapObjects, load their maps
- // and their instance types.
- Node* lhs_map = assembler->LoadMap(lhs);
- Node* rhs_map = assembler->LoadMap(rhs);
-
- // Load the instance types of {lhs} and {rhs}.
- Node* lhs_instance_type = assembler->LoadMapInstanceType(lhs_map);
- Node* rhs_instance_type = assembler->LoadMapInstanceType(rhs_map);
-
- // Dispatch based on the instance type of {lhs}.
- size_t const kNumCases = FIRST_NONSTRING_TYPE + 4;
- 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_lhsisnumber;
- case_values[FIRST_NONSTRING_TYPE + 0] = HEAP_NUMBER_TYPE;
- case_labels[FIRST_NONSTRING_TYPE + 1] = &if_lhsissymbol;
- case_values[FIRST_NONSTRING_TYPE + 1] = SYMBOL_TYPE;
- case_labels[FIRST_NONSTRING_TYPE + 2] = &if_lhsissimd128value;
- case_values[FIRST_NONSTRING_TYPE + 2] = SIMD128_VALUE_TYPE;
- case_labels[FIRST_NONSTRING_TYPE + 3] = &if_lhsisoddball;
- case_values[FIRST_NONSTRING_TYPE + 3] = ODDBALL_TYPE;
- assembler->Switch(lhs_instance_type, &if_lhsisreceiver, 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_lhsisstring);
- delete case_labels[i];
- }
-
- assembler->Bind(&if_lhsisstring);
- {
- // Check if {rhs} is also a String.
- Label if_rhsisstring(assembler, Label::kDeferred),
- if_rhsisnotstring(assembler);
- assembler->Branch(
- assembler->IsStringInstanceType(rhs_instance_type),
- &if_rhsisstring, &if_rhsisnotstring);
-
- assembler->Bind(&if_rhsisstring);
- {
- // Both {lhs} and {rhs} are of type String, just do the
- // string comparison then.
- Callable callable =
- (mode == kDontNegateResult)
- ? CodeFactory::StringEqual(assembler->isolate())
- : CodeFactory::StringNotEqual(assembler->isolate());
- result.Bind(assembler->CallStub(callable, context, lhs, rhs));
- assembler->Goto(&end);
- }
-
- assembler->Bind(&if_rhsisnotstring);
- {
- // The {lhs} is a String and the {rhs} is some other HeapObject.
- // Swapping {lhs} and {rhs} is not observable and doesn't matter
- // for the result, so we can just swap them and use the String
- // handling below (for {rhs} being a String).
- var_lhs.Bind(rhs);
- var_rhs.Bind(lhs);
- assembler->Goto(&loop);
- }
- }
-
- assembler->Bind(&if_lhsisnumber);
- {
- // Check if {rhs} is also a HeapNumber.
- Label if_rhsisnumber(assembler), if_rhsisnotnumber(assembler);
- assembler->Branch(
- assembler->Word32Equal(lhs_instance_type, rhs_instance_type),
- &if_rhsisnumber, &if_rhsisnotnumber);
-
- assembler->Bind(&if_rhsisnumber);
- {
- // Convert {lhs} and {rhs} to floating point values, and
- // perform a floating point comparison.
- var_fcmp_lhs.Bind(assembler->LoadHeapNumberValue(lhs));
- var_fcmp_rhs.Bind(assembler->LoadHeapNumberValue(rhs));
- assembler->Goto(&do_fcmp);
- }
-
- assembler->Bind(&if_rhsisnotnumber);
- {
- // The {lhs} is a Number, the {rhs} is some other HeapObject.
- Label if_rhsisstring(assembler, Label::kDeferred),
- if_rhsisnotstring(assembler);
- assembler->Branch(
- assembler->IsStringInstanceType(rhs_instance_type),
- &if_rhsisstring, &if_rhsisnotstring);
-
- assembler->Bind(&if_rhsisstring);
- {
- // The {rhs} is a String and the {lhs} is a HeapNumber; we need
- // to convert the {rhs} to a Number and compare the output to
- // the Number on the {lhs}.
- assembler->Goto(&do_rhsstringtonumber);
- }
-
- assembler->Bind(&if_rhsisnotstring);
- {
- // Check if the {rhs} is a JSReceiver.
- Label if_rhsisreceiver(assembler),
- if_rhsisnotreceiver(assembler);
- STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
- assembler->Branch(
- assembler->IsJSReceiverInstanceType(rhs_instance_type),
- &if_rhsisreceiver, &if_rhsisnotreceiver);
-
- assembler->Bind(&if_rhsisreceiver);
- {
- // The {lhs} is a Primitive and the {rhs} is a JSReceiver.
- // Swapping {lhs} and {rhs} is not observable and doesn't
- // matter for the result, so we can just swap them and use
- // the JSReceiver handling below (for {lhs} being a
- // JSReceiver).
- var_lhs.Bind(rhs);
- var_rhs.Bind(lhs);
- assembler->Goto(&loop);
- }
-
- assembler->Bind(&if_rhsisnotreceiver);
- {
- // Check if {rhs} is a Boolean.
- Label if_rhsisboolean(assembler),
- if_rhsisnotboolean(assembler);
- assembler->Branch(assembler->IsBooleanMap(rhs_map),
- &if_rhsisboolean, &if_rhsisnotboolean);
-
- assembler->Bind(&if_rhsisboolean);
- {
- // The {rhs} is a Boolean, convert it to a Smi first.
- var_rhs.Bind(assembler->LoadObjectField(
- rhs, Oddball::kToNumberOffset));
- assembler->Goto(&loop);
- }
-
- assembler->Bind(&if_rhsisnotboolean);
- assembler->Goto(&if_notequal);
- }
- }
- }
- }
-
- assembler->Bind(&if_lhsisoddball);
- {
- // The {lhs} is an Oddball and {rhs} is some other HeapObject.
- Label if_lhsisboolean(assembler), if_lhsisnotboolean(assembler);
- Node* boolean_map = assembler->BooleanMapConstant();
- assembler->Branch(assembler->WordEqual(lhs_map, boolean_map),
- &if_lhsisboolean, &if_lhsisnotboolean);
-
- assembler->Bind(&if_lhsisboolean);
- {
- // The {lhs} is a Boolean, check if {rhs} is also a Boolean.
- Label if_rhsisboolean(assembler), if_rhsisnotboolean(assembler);
- assembler->Branch(assembler->WordEqual(rhs_map, boolean_map),
- &if_rhsisboolean, &if_rhsisnotboolean);
-
- assembler->Bind(&if_rhsisboolean);
- {
- // Both {lhs} and {rhs} are distinct Boolean values.
- assembler->Goto(&if_notequal);
- }
-
- assembler->Bind(&if_rhsisnotboolean);
- {
- // Convert the {lhs} to a Number first.
- var_lhs.Bind(
- assembler->LoadObjectField(lhs, Oddball::kToNumberOffset));
- assembler->Goto(&loop);
- }
- }
-
- assembler->Bind(&if_lhsisnotboolean);
- {
- // The {lhs} is either Null or Undefined; check if the {rhs} is
- // undetectable (i.e. either also Null or Undefined or some
- // undetectable JSReceiver).
- Node* rhs_bitfield = assembler->LoadMapBitField(rhs_map);
- assembler->BranchIfWord32Equal(
- assembler->Word32And(
- rhs_bitfield,
- assembler->Int32Constant(1 << Map::kIsUndetectable)),
- assembler->Int32Constant(0), &if_notequal, &if_equal);
- }
- }
-
- assembler->Bind(&if_lhsissymbol);
- {
- // Check if the {rhs} is a JSReceiver.
- Label if_rhsisreceiver(assembler), if_rhsisnotreceiver(assembler);
- STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
- assembler->Branch(
- assembler->IsJSReceiverInstanceType(rhs_instance_type),
- &if_rhsisreceiver, &if_rhsisnotreceiver);
-
- assembler->Bind(&if_rhsisreceiver);
- {
- // The {lhs} is a Primitive and the {rhs} is a JSReceiver.
- // Swapping {lhs} and {rhs} is not observable and doesn't
- // matter for the result, so we can just swap them and use
- // the JSReceiver handling below (for {lhs} being a JSReceiver).
- var_lhs.Bind(rhs);
- var_rhs.Bind(lhs);
- assembler->Goto(&loop);
- }
-
- assembler->Bind(&if_rhsisnotreceiver);
- {
- // The {rhs} is not a JSReceiver and also not the same Symbol
- // as the {lhs}, so this is equality check is considered false.
- assembler->Goto(&if_notequal);
- }
- }
-
- assembler->Bind(&if_lhsissimd128value);
- {
- // Check if the {rhs} is also a Simd128Value.
- Label if_rhsissimd128value(assembler),
- if_rhsisnotsimd128value(assembler);
- assembler->Branch(
- assembler->Word32Equal(lhs_instance_type, rhs_instance_type),
- &if_rhsissimd128value, &if_rhsisnotsimd128value);
-
- assembler->Bind(&if_rhsissimd128value);
- {
- // Both {lhs} and {rhs} is a Simd128Value.
- GenerateEqual_Simd128Value_HeapObject(assembler, lhs, lhs_map,
- rhs, rhs_map, &if_equal,
- &if_notequal);
- }
-
- assembler->Bind(&if_rhsisnotsimd128value);
- {
- // Check if the {rhs} is a JSReceiver.
- Label if_rhsisreceiver(assembler), if_rhsisnotreceiver(assembler);
- STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
- assembler->Branch(
- assembler->IsJSReceiverInstanceType(rhs_instance_type),
- &if_rhsisreceiver, &if_rhsisnotreceiver);
-
- assembler->Bind(&if_rhsisreceiver);
- {
- // The {lhs} is a Primitive and the {rhs} is a JSReceiver.
- // Swapping {lhs} and {rhs} is not observable and doesn't
- // matter for the result, so we can just swap them and use
- // the JSReceiver handling below (for {lhs} being a JSReceiver).
- var_lhs.Bind(rhs);
- var_rhs.Bind(lhs);
- assembler->Goto(&loop);
- }
-
- assembler->Bind(&if_rhsisnotreceiver);
- {
- // The {rhs} is some other Primitive.
- assembler->Goto(&if_notequal);
- }
- }
- }
-
- assembler->Bind(&if_lhsisreceiver);
- {
- // Check if the {rhs} is also a JSReceiver.
- Label if_rhsisreceiver(assembler), if_rhsisnotreceiver(assembler);
- STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
- assembler->Branch(
- assembler->IsJSReceiverInstanceType(rhs_instance_type),
- &if_rhsisreceiver, &if_rhsisnotreceiver);
-
- assembler->Bind(&if_rhsisreceiver);
- {
- // Both {lhs} and {rhs} are different JSReceiver references, so
- // this cannot be considered equal.
- assembler->Goto(&if_notequal);
- }
-
- assembler->Bind(&if_rhsisnotreceiver);
- {
- // Check if {rhs} is Null or Undefined (an undetectable check
- // is sufficient here, since we already know that {rhs} is not
- // a JSReceiver).
- Label if_rhsisundetectable(assembler),
- if_rhsisnotundetectable(assembler, Label::kDeferred);
- Node* rhs_bitfield = assembler->LoadMapBitField(rhs_map);
- assembler->BranchIfWord32Equal(
- assembler->Word32And(
- rhs_bitfield,
- assembler->Int32Constant(1 << Map::kIsUndetectable)),
- assembler->Int32Constant(0), &if_rhsisnotundetectable,
- &if_rhsisundetectable);
-
- assembler->Bind(&if_rhsisundetectable);
- {
- // Check if {lhs} is an undetectable JSReceiver.
- Node* lhs_bitfield = assembler->LoadMapBitField(lhs_map);
- assembler->BranchIfWord32Equal(
- assembler->Word32And(
- lhs_bitfield,
- assembler->Int32Constant(1 << Map::kIsUndetectable)),
- assembler->Int32Constant(0), &if_notequal, &if_equal);
- }
-
- assembler->Bind(&if_rhsisnotundetectable);
- {
- // The {rhs} is some Primitive different from Null and
- // Undefined, need to convert {lhs} to Primitive first.
- Callable callable =
- CodeFactory::NonPrimitiveToPrimitive(assembler->isolate());
- var_lhs.Bind(assembler->CallStub(callable, context, lhs));
- assembler->Goto(&loop);
- }
- }
- }
- }
- }
- }
-
- assembler->Bind(&do_rhsstringtonumber);
- {
- Callable callable = CodeFactory::StringToNumber(assembler->isolate());
- var_rhs.Bind(assembler->CallStub(callable, context, rhs));
- assembler->Goto(&loop);
- }
- }
-
- assembler->Bind(&do_fcmp);
- {
- // Load the {lhs} and {rhs} floating point values.
- Node* lhs = var_fcmp_lhs.value();
- Node* rhs = var_fcmp_rhs.value();
-
- // Perform a fast floating point comparison.
- assembler->BranchIfFloat64Equal(lhs, rhs, &if_equal, &if_notequal);
- }
-
- assembler->Bind(&if_equal);
- {
- result.Bind(assembler->BooleanConstant(mode == kDontNegateResult));
- assembler->Goto(&end);
- }
-
- assembler->Bind(&if_notequal);
- {
- result.Bind(assembler->BooleanConstant(mode == kNegateResult));
- assembler->Goto(&end);
- }
-
- assembler->Bind(&end);
- return result.value();
-}
-
-compiler::Node* GenerateStrictEqual(CodeStubAssembler* assembler,
- ResultMode mode, compiler::Node* lhs,
- compiler::Node* rhs,
- compiler::Node* context) {
- // Here's pseudo-code for the algorithm below in case of kDontNegateResult
- // mode; for kNegateResult mode we properly negate the result.
- //
- // if (lhs == rhs) {
- // if (lhs->IsHeapNumber()) return HeapNumber::cast(lhs)->value() != NaN;
- // return true;
- // }
- // if (!lhs->IsSmi()) {
- // if (lhs->IsHeapNumber()) {
- // if (rhs->IsSmi()) {
- // return Smi::cast(rhs)->value() == HeapNumber::cast(lhs)->value();
- // } else if (rhs->IsHeapNumber()) {
- // return HeapNumber::cast(rhs)->value() ==
- // HeapNumber::cast(lhs)->value();
- // } else {
- // return false;
- // }
- // } else {
- // if (rhs->IsSmi()) {
- // return false;
- // } else {
- // if (lhs->IsString()) {
- // if (rhs->IsString()) {
- // return %StringEqual(lhs, rhs);
- // } else {
- // return false;
- // }
- // } else if (lhs->IsSimd128()) {
- // if (rhs->IsSimd128()) {
- // return %StrictEqual(lhs, rhs);
- // }
- // } else {
- // return false;
- // }
- // }
- // }
- // } else {
- // if (rhs->IsSmi()) {
- // return false;
- // } else {
- // if (rhs->IsHeapNumber()) {
- // return Smi::cast(lhs)->value() == HeapNumber::cast(rhs)->value();
- // } else {
- // return false;
- // }
- // }
- // }
-
- typedef CodeStubAssembler::Label Label;
- typedef CodeStubAssembler::Variable Variable;
- typedef compiler::Node Node;
-
- Label if_equal(assembler), if_notequal(assembler), end(assembler);
- Variable result(assembler, MachineRepresentation::kTagged);
-
- // Check if {lhs} and {rhs} refer to the same object.
- Label if_same(assembler), if_notsame(assembler);
- assembler->Branch(assembler->WordEqual(lhs, rhs), &if_same, &if_notsame);
-
- assembler->Bind(&if_same);
- {
- // The {lhs} and {rhs} reference the exact same value, yet we need special
- // treatment for HeapNumber, as NaN is not equal to NaN.
- GenerateEqual_Same(assembler, lhs, &if_equal, &if_notequal);
- }
-
- assembler->Bind(&if_notsame);
- {
- // The {lhs} and {rhs} reference different objects, yet for Smi, HeapNumber,
- // String and Simd128Value they can still be considered equal.
- Node* number_map = assembler->HeapNumberMapConstant();
-
- // Check if {lhs} is a Smi or a HeapObject.
- Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler);
- assembler->Branch(assembler->WordIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi);
-
- assembler->Bind(&if_lhsisnotsmi);
- {
- // Load the map of {lhs}.
- Node* lhs_map = assembler->LoadMap(lhs);
-
- // Check if {lhs} is a HeapNumber.
- Label if_lhsisnumber(assembler), if_lhsisnotnumber(assembler);
- assembler->Branch(assembler->WordEqual(lhs_map, number_map),
- &if_lhsisnumber, &if_lhsisnotnumber);
-
- assembler->Bind(&if_lhsisnumber);
- {
- // Check if {rhs} is a Smi or a HeapObject.
- Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler);
- assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi,
- &if_rhsisnotsmi);
-
- assembler->Bind(&if_rhsissmi);
- {
- // Convert {lhs} and {rhs} to floating point values.
- Node* lhs_value = assembler->LoadHeapNumberValue(lhs);
- Node* rhs_value = assembler->SmiToFloat64(rhs);
-
- // Perform a floating point comparison of {lhs} and {rhs}.
- assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_equal,
- &if_notequal);
- }
-
- assembler->Bind(&if_rhsisnotsmi);
- {
- // Load the map of {rhs}.
- Node* rhs_map = assembler->LoadMap(rhs);
-
- // Check if {rhs} is also a HeapNumber.
- Label if_rhsisnumber(assembler), if_rhsisnotnumber(assembler);
- assembler->Branch(assembler->WordEqual(rhs_map, number_map),
- &if_rhsisnumber, &if_rhsisnotnumber);
-
- assembler->Bind(&if_rhsisnumber);
- {
- // Convert {lhs} and {rhs} to floating point values.
- Node* lhs_value = assembler->LoadHeapNumberValue(lhs);
- Node* rhs_value = assembler->LoadHeapNumberValue(rhs);
-
- // Perform a floating point comparison of {lhs} and {rhs}.
- assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_equal,
- &if_notequal);
- }
-
- assembler->Bind(&if_rhsisnotnumber);
- assembler->Goto(&if_notequal);
- }
- }
-
- assembler->Bind(&if_lhsisnotnumber);
- {
- // Check if {rhs} is a Smi or a HeapObject.
- Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler);
- assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi,
- &if_rhsisnotsmi);
-
- assembler->Bind(&if_rhsissmi);
- assembler->Goto(&if_notequal);
-
- assembler->Bind(&if_rhsisnotsmi);
- {
- // Load the instance type of {lhs}.
- Node* lhs_instance_type = assembler->LoadMapInstanceType(lhs_map);
-
- // Check if {lhs} is a String.
- Label if_lhsisstring(assembler), if_lhsisnotstring(assembler);
- assembler->Branch(assembler->IsStringInstanceType(lhs_instance_type),
- &if_lhsisstring, &if_lhsisnotstring);
-
- assembler->Bind(&if_lhsisstring);
- {
- // Load the instance type of {rhs}.
- Node* rhs_instance_type = assembler->LoadInstanceType(rhs);
-
- // Check if {rhs} is also a String.
- Label if_rhsisstring(assembler, Label::kDeferred),
- if_rhsisnotstring(assembler);
- assembler->Branch(
- assembler->IsStringInstanceType(rhs_instance_type),
- &if_rhsisstring, &if_rhsisnotstring);
-
- assembler->Bind(&if_rhsisstring);
- {
- Callable callable =
- (mode == kDontNegateResult)
- ? CodeFactory::StringEqual(assembler->isolate())
- : CodeFactory::StringNotEqual(assembler->isolate());
- result.Bind(assembler->CallStub(callable, context, lhs, rhs));
- assembler->Goto(&end);
- }
-
- assembler->Bind(&if_rhsisnotstring);
- assembler->Goto(&if_notequal);
- }
-
- assembler->Bind(&if_lhsisnotstring);
- {
- // Check if {lhs} is a Simd128Value.
- Label if_lhsissimd128value(assembler),
- if_lhsisnotsimd128value(assembler);
- assembler->Branch(assembler->Word32Equal(
- lhs_instance_type,
- assembler->Int32Constant(SIMD128_VALUE_TYPE)),
- &if_lhsissimd128value, &if_lhsisnotsimd128value);
-
- assembler->Bind(&if_lhsissimd128value);
- {
- // Load the map of {rhs}.
- Node* rhs_map = assembler->LoadMap(rhs);
-
- // Check if {rhs} is also a Simd128Value that is equal to {lhs}.
- GenerateEqual_Simd128Value_HeapObject(assembler, lhs, lhs_map,
- rhs, rhs_map, &if_equal,
- &if_notequal);
- }
-
- assembler->Bind(&if_lhsisnotsimd128value);
- assembler->Goto(&if_notequal);
- }
- }
- }
- }
-
- assembler->Bind(&if_lhsissmi);
- {
- // We already know that {lhs} and {rhs} are not reference equal, and {lhs}
- // is a Smi; so {lhs} and {rhs} can only be strictly equal if {rhs} is a
- // HeapNumber with an equal floating point value.
-
- // Check if {rhs} is a Smi or a HeapObject.
- Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler);
- assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi,
- &if_rhsisnotsmi);
-
- assembler->Bind(&if_rhsissmi);
- assembler->Goto(&if_notequal);
-
- assembler->Bind(&if_rhsisnotsmi);
- {
- // Load the map of the {rhs}.
- Node* rhs_map = assembler->LoadMap(rhs);
-
- // The {rhs} could be a HeapNumber with the same value as {lhs}.
- Label if_rhsisnumber(assembler), if_rhsisnotnumber(assembler);
- assembler->Branch(assembler->WordEqual(rhs_map, number_map),
- &if_rhsisnumber, &if_rhsisnotnumber);
-
- assembler->Bind(&if_rhsisnumber);
- {
- // Convert {lhs} and {rhs} to floating point values.
- Node* lhs_value = assembler->SmiToFloat64(lhs);
- Node* rhs_value = assembler->LoadHeapNumberValue(rhs);
-
- // Perform a floating point comparison of {lhs} and {rhs}.
- assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_equal,
- &if_notequal);
- }
-
- assembler->Bind(&if_rhsisnotnumber);
- assembler->Goto(&if_notequal);
- }
- }
- }
-
- assembler->Bind(&if_equal);
- {
- result.Bind(assembler->BooleanConstant(mode == kDontNegateResult));
- assembler->Goto(&end);
- }
-
- assembler->Bind(&if_notequal);
- {
- result.Bind(assembler->BooleanConstant(mode == kNegateResult));
- assembler->Goto(&end);
- }
-
- assembler->Bind(&end);
- return result.value();
-}
-
-} // namespace
-
void LoadApiGetterStub::GenerateAssembly(CodeStubAssembler* assembler) const {
typedef compiler::Node Node;
Node* context = assembler->Parameter(Descriptor::kContext);
@@ -4244,7 +2029,7 @@ void StoreGlobalStub::GenerateAssembly(CodeStubAssembler* assembler) const {
Node* global = assembler->LoadObjectField(proxy_map, Map::kPrototypeOffset);
Node* map_cell = assembler->HeapConstant(isolate()->factory()->NewWeakCell(
StoreGlobalStub::global_map_placeholder(isolate())));
- Node* expected_map = assembler->LoadWeakCellValue(map_cell);
+ Node* expected_map = assembler->LoadWeakCellValueUnchecked(map_cell);
Node* map = assembler->LoadMap(global);
assembler->GotoIf(assembler->WordNotEqual(expected_map, map), &miss);
}
@@ -4252,7 +2037,7 @@ void StoreGlobalStub::GenerateAssembly(CodeStubAssembler* assembler) const {
Node* weak_cell = assembler->HeapConstant(isolate()->factory()->NewWeakCell(
StoreGlobalStub::property_cell_placeholder(isolate())));
Node* cell = assembler->LoadWeakCellValue(weak_cell);
- assembler->GotoIf(assembler->WordIsSmi(cell), &miss);
+ assembler->GotoIf(assembler->TaggedIsSmi(cell), &miss);
// Load the payload of the global parameter cell. A hole indicates that the
// cell has been invalidated and that the store must be handled by the
@@ -4274,7 +2059,7 @@ void StoreGlobalStub::GenerateAssembly(CodeStubAssembler* assembler) const {
if (cell_type == PropertyCellType::kConstantType) {
switch (constant_type()) {
case PropertyCellConstantType::kSmi:
- assembler->GotoUnless(assembler->WordIsSmi(value), &miss);
+ assembler->GotoUnless(assembler->TaggedIsSmi(value), &miss);
value_is_smi = true;
break;
case PropertyCellConstantType::kStableMap: {
@@ -4283,8 +2068,8 @@ void StoreGlobalStub::GenerateAssembly(CodeStubAssembler* assembler) const {
// are the maps that were originally in the cell or not. If optimized
// code will deopt when a cell has a unstable map and if it has a
// dependency on a stable map, it will deopt if the map destabilizes.
- assembler->GotoIf(assembler->WordIsSmi(value), &miss);
- assembler->GotoIf(assembler->WordIsSmi(cell_contents), &miss);
+ assembler->GotoIf(assembler->TaggedIsSmi(value), &miss);
+ assembler->GotoIf(assembler->TaggedIsSmi(cell_contents), &miss);
Node* expected_map = assembler->LoadMap(cell_contents);
Node* map = assembler->LoadMap(value);
assembler->GotoIf(assembler->WordNotEqual(expected_map, map), &miss);
@@ -4392,155 +2177,6 @@ void StoreScriptContextFieldStub::GenerateAssembly(
assembler->Return(value);
}
-// static
-compiler::Node* LessThanStub::Generate(CodeStubAssembler* assembler,
- compiler::Node* lhs, compiler::Node* rhs,
- compiler::Node* context) {
- return GenerateAbstractRelationalComparison(assembler, kLessThan, lhs, rhs,
- context);
-}
-
-// static
-compiler::Node* LessThanOrEqualStub::Generate(CodeStubAssembler* assembler,
- compiler::Node* lhs,
- compiler::Node* rhs,
- compiler::Node* context) {
- return GenerateAbstractRelationalComparison(assembler, kLessThanOrEqual, lhs,
- rhs, context);
-}
-
-// static
-compiler::Node* GreaterThanStub::Generate(CodeStubAssembler* assembler,
- compiler::Node* lhs,
- compiler::Node* rhs,
- compiler::Node* context) {
- return GenerateAbstractRelationalComparison(assembler, kGreaterThan, lhs, rhs,
- context);
-}
-
-// static
-compiler::Node* GreaterThanOrEqualStub::Generate(CodeStubAssembler* assembler,
- compiler::Node* lhs,
- compiler::Node* rhs,
- compiler::Node* context) {
- return GenerateAbstractRelationalComparison(assembler, kGreaterThanOrEqual,
- lhs, rhs, context);
-}
-
-// static
-compiler::Node* EqualStub::Generate(CodeStubAssembler* assembler,
- compiler::Node* lhs, compiler::Node* rhs,
- compiler::Node* context) {
- return GenerateEqual(assembler, kDontNegateResult, lhs, rhs, context);
-}
-
-// static
-compiler::Node* NotEqualStub::Generate(CodeStubAssembler* assembler,
- compiler::Node* lhs, compiler::Node* rhs,
- compiler::Node* context) {
- return GenerateEqual(assembler, kNegateResult, lhs, rhs, context);
-}
-
-// static
-compiler::Node* StrictEqualStub::Generate(CodeStubAssembler* assembler,
- compiler::Node* lhs,
- compiler::Node* rhs,
- compiler::Node* context) {
- return GenerateStrictEqual(assembler, kDontNegateResult, lhs, rhs, context);
-}
-
-// static
-compiler::Node* StrictNotEqualStub::Generate(CodeStubAssembler* assembler,
- compiler::Node* lhs,
- compiler::Node* rhs,
- compiler::Node* context) {
- return GenerateStrictEqual(assembler, kNegateResult, lhs, rhs, context);
-}
-
-void ToLengthStub::GenerateAssembly(CodeStubAssembler* assembler) const {
- typedef CodeStubAssembler::Label Label;
- typedef compiler::Node Node;
- typedef CodeStubAssembler::Variable Variable;
-
- Node* context = assembler->Parameter(1);
-
- // We might need to loop once for ToNumber conversion.
- Variable var_len(assembler, MachineRepresentation::kTagged);
- Label loop(assembler, &var_len);
- var_len.Bind(assembler->Parameter(0));
- assembler->Goto(&loop);
- assembler->Bind(&loop);
- {
- // Shared entry points.
- Label return_len(assembler),
- return_two53minus1(assembler, Label::kDeferred),
- return_zero(assembler, Label::kDeferred);
-
- // Load the current {len} value.
- Node* len = var_len.value();
-
- // Check if {len} is a positive Smi.
- assembler->GotoIf(assembler->WordIsPositiveSmi(len), &return_len);
-
- // Check if {len} is a (negative) Smi.
- assembler->GotoIf(assembler->WordIsSmi(len), &return_zero);
-
- // Check if {len} is a HeapNumber.
- Label if_lenisheapnumber(assembler),
- if_lenisnotheapnumber(assembler, Label::kDeferred);
- assembler->Branch(assembler->IsHeapNumberMap(assembler->LoadMap(len)),
- &if_lenisheapnumber, &if_lenisnotheapnumber);
-
- assembler->Bind(&if_lenisheapnumber);
- {
- // Load the floating-point value of {len}.
- Node* len_value = assembler->LoadHeapNumberValue(len);
-
- // Check if {len} is not greater than zero.
- assembler->GotoUnless(assembler->Float64GreaterThan(
- len_value, assembler->Float64Constant(0.0)),
- &return_zero);
-
- // Check if {len} is greater than or equal to 2^53-1.
- assembler->GotoIf(
- assembler->Float64GreaterThanOrEqual(
- len_value, assembler->Float64Constant(kMaxSafeInteger)),
- &return_two53minus1);
-
- // Round the {len} towards -Infinity.
- Node* value = assembler->Float64Floor(len_value);
- Node* result = assembler->ChangeFloat64ToTagged(value);
- assembler->Return(result);
- }
-
- assembler->Bind(&if_lenisnotheapnumber);
- {
- // Need to convert {len} to a Number first.
- Callable callable = CodeFactory::NonNumberToNumber(assembler->isolate());
- var_len.Bind(assembler->CallStub(callable, context, len));
- assembler->Goto(&loop);
- }
-
- assembler->Bind(&return_len);
- assembler->Return(var_len.value());
-
- assembler->Bind(&return_two53minus1);
- assembler->Return(assembler->NumberConstant(kMaxSafeInteger));
-
- assembler->Bind(&return_zero);
- assembler->Return(assembler->SmiConstant(Smi::FromInt(0)));
- }
-}
-
-void ToIntegerStub::GenerateAssembly(CodeStubAssembler* assembler) const {
- typedef compiler::Node Node;
-
- Node* input = assembler->Parameter(Descriptor::kArgument);
- Node* context = assembler->Parameter(Descriptor::kContext);
-
- assembler->Return(assembler->ToInteger(context, input));
-}
-
void StoreInterceptorStub::GenerateAssembly(
CodeStubAssembler* assembler) const {
typedef compiler::Node Node;
@@ -4713,27 +2349,6 @@ void HydrogenCodeStub::TraceTransition(StateType from, StateType to) {
os << ": " << from << "=>" << to << "]" << std::endl;
}
-
-// TODO(svenpanne) Make this a real infix_ostream_iterator.
-class SimpleListPrinter {
- public:
- explicit SimpleListPrinter(std::ostream& os) : os_(os), first_(true) {}
-
- void Add(const char* s) {
- if (first_) {
- first_ = false;
- } else {
- os_ << ",";
- }
- os_ << s;
- }
-
- private:
- std::ostream& os_;
- bool first_;
-};
-
-
void CallICStub::PrintState(std::ostream& os) const { // NOLINT
os << state();
}
@@ -4753,14 +2368,6 @@ void LoadDictionaryElementStub::InitializeDescriptor(
FUNCTION_ADDR(Runtime_KeyedLoadIC_MissFromStubFailure));
}
-
-void KeyedLoadGenericStub::InitializeDescriptor(
- CodeStubDescriptor* descriptor) {
- descriptor->Initialize(
- Runtime::FunctionForId(Runtime::kKeyedGetProperty)->entry);
-}
-
-
void HandlerStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
DCHECK(kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC);
if (kind() == Code::KEYED_LOAD_IC) {
@@ -4779,21 +2386,6 @@ CallInterfaceDescriptor HandlerStub::GetCallInterfaceDescriptor() const {
}
}
-
-void NumberToStringStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
- descriptor->Initialize(
- Runtime::FunctionForId(Runtime::kNumberToString)->entry);
- descriptor->SetMissHandler(Runtime::kNumberToString);
-}
-
-void RegExpConstructResultStub::InitializeDescriptor(
- CodeStubDescriptor* descriptor) {
- descriptor->Initialize(
- Runtime::FunctionForId(Runtime::kRegExpConstructResult)->entry);
- descriptor->SetMissHandler(Runtime::kRegExpConstructResult);
-}
-
-
void TransitionElementsKindStub::InitializeDescriptor(
CodeStubDescriptor* descriptor) {
descriptor->Initialize(
@@ -4835,118 +2427,6 @@ void BinaryOpWithAllocationSiteStub::InitializeDescriptor(
FUNCTION_ADDR(Runtime_BinaryOpIC_MissWithAllocationSite));
}
-
-void StringAddStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
- descriptor->Initialize(Runtime::FunctionForId(Runtime::kStringAdd)->entry);
- descriptor->SetMissHandler(Runtime::kStringAdd);
-}
-
-namespace {
-
-compiler::Node* GenerateHasProperty(
- CodeStubAssembler* assembler, compiler::Node* object, compiler::Node* key,
- compiler::Node* context, Runtime::FunctionId fallback_runtime_function_id) {
- typedef compiler::Node Node;
- typedef CodeStubAssembler::Label Label;
- typedef CodeStubAssembler::Variable Variable;
-
- Label call_runtime(assembler, Label::kDeferred), return_true(assembler),
- return_false(assembler), end(assembler);
-
- CodeStubAssembler::LookupInHolder lookup_property_in_holder =
- [assembler, &return_true](Node* receiver, Node* holder, Node* holder_map,
- Node* holder_instance_type, Node* unique_name,
- Label* next_holder, Label* if_bailout) {
- assembler->TryHasOwnProperty(holder, holder_map, holder_instance_type,
- unique_name, &return_true, next_holder,
- if_bailout);
- };
-
- CodeStubAssembler::LookupInHolder lookup_element_in_holder =
- [assembler, &return_true](Node* receiver, Node* holder, Node* holder_map,
- Node* holder_instance_type, Node* index,
- Label* next_holder, Label* if_bailout) {
- assembler->TryLookupElement(holder, holder_map, holder_instance_type,
- index, &return_true, next_holder,
- if_bailout);
- };
-
- assembler->TryPrototypeChainLookup(object, key, lookup_property_in_holder,
- lookup_element_in_holder, &return_false,
- &call_runtime);
-
- Variable result(assembler, MachineRepresentation::kTagged);
- assembler->Bind(&return_true);
- {
- result.Bind(assembler->BooleanConstant(true));
- assembler->Goto(&end);
- }
-
- assembler->Bind(&return_false);
- {
- result.Bind(assembler->BooleanConstant(false));
- assembler->Goto(&end);
- }
-
- assembler->Bind(&call_runtime);
- {
- result.Bind(assembler->CallRuntime(fallback_runtime_function_id, context,
- object, key));
- assembler->Goto(&end);
- }
-
- assembler->Bind(&end);
- return result.value();
-}
-
-} // namespace
-
-// static
-compiler::Node* HasPropertyStub::Generate(CodeStubAssembler* assembler,
- compiler::Node* key,
- compiler::Node* object,
- compiler::Node* context) {
- return GenerateHasProperty(assembler, object, key, context,
- Runtime::kHasProperty);
-}
-
-// static
-compiler::Node* ForInFilterStub::Generate(CodeStubAssembler* assembler,
- compiler::Node* key,
- compiler::Node* object,
- compiler::Node* context) {
- typedef compiler::Node Node;
- typedef CodeStubAssembler::Label Label;
- typedef CodeStubAssembler::Variable Variable;
-
- Label return_undefined(assembler, Label::kDeferred),
- return_to_name(assembler), end(assembler);
-
- Variable var_result(assembler, MachineRepresentation::kTagged);
-
- Node* has_property = GenerateHasProperty(assembler, object, key, context,
- Runtime::kForInHasProperty);
-
- assembler->Branch(
- assembler->WordEqual(has_property, assembler->BooleanConstant(true)),
- &return_to_name, &return_undefined);
-
- assembler->Bind(&return_to_name);
- {
- var_result.Bind(assembler->ToName(context, key));
- assembler->Goto(&end);
- }
-
- assembler->Bind(&return_undefined);
- {
- var_result.Bind(assembler->UndefinedConstant());
- assembler->Goto(&end);
- }
-
- assembler->Bind(&end);
- return var_result.value();
-}
-
void GetPropertyStub::GenerateAssembly(CodeStubAssembler* assembler) const {
typedef compiler::Node Node;
typedef CodeStubAssembler::Label Label;
@@ -5064,12 +2544,13 @@ compiler::Node* FastNewClosureStub::Generate(CodeStubAssembler* assembler,
if (FLAG_debug_code) {
// Function must be a function without a prototype.
- assembler->Assert(assembler->Word32And(
- compiler_hints,
- assembler->Int32Constant((FunctionKind::kAccessorFunction |
- FunctionKind::kArrowFunction |
- FunctionKind::kConciseMethod)
- << SharedFunctionInfo::kFunctionKindShift)));
+ CSA_ASSERT(assembler, assembler->Word32And(
+ compiler_hints,
+ assembler->Int32Constant(
+ (FunctionKind::kAccessorFunction |
+ FunctionKind::kArrowFunction |
+ FunctionKind::kConciseMethod)
+ << SharedFunctionInfo::kFunctionKindShift)));
}
assembler->Goto(&if_function_without_prototype);
@@ -5167,9 +2648,7 @@ void FastNewClosureStub::GenerateAssembly(CodeStubAssembler* assembler) const {
compiler::Node* FastNewFunctionContextStub::Generate(
CodeStubAssembler* assembler, compiler::Node* function,
compiler::Node* slots, compiler::Node* context) {
- typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node;
- typedef CodeStubAssembler::Variable Variable;
Node* min_context_slots =
assembler->Int32Constant(Context::MIN_CONTEXT_SLOTS);
@@ -5208,24 +2687,12 @@ compiler::Node* FastNewFunctionContextStub::Generate(
// Initialize the rest of the slots to undefined.
Node* undefined = assembler->UndefinedConstant();
- Variable var_slot_index(assembler, MachineRepresentation::kWord32);
- var_slot_index.Bind(min_context_slots);
- Label loop(assembler, &var_slot_index), after_loop(assembler);
- assembler->Goto(&loop);
-
- assembler->Bind(&loop);
- {
- Node* slot_index = var_slot_index.value();
- assembler->GotoUnless(assembler->Int32LessThan(slot_index, length),
- &after_loop);
- assembler->StoreFixedArrayElement(function_context, slot_index, undefined,
- SKIP_WRITE_BARRIER);
- Node* one = assembler->Int32Constant(1);
- Node* next_index = assembler->Int32Add(slot_index, one);
- var_slot_index.Bind(next_index);
- assembler->Goto(&loop);
- }
- assembler->Bind(&after_loop);
+ assembler->BuildFastFixedArrayForEach(
+ function_context, FAST_ELEMENTS, min_context_slots, length,
+ [undefined](CodeStubAssembler* assembler, Node* context, Node* offset) {
+ assembler->StoreNoWriteBarrier(MachineType::PointerRepresentation(),
+ context, offset, undefined);
+ });
return function_context;
}
@@ -5380,7 +2847,7 @@ compiler::Node* FastCloneShallowArrayStub::Generate(
allocation_site =
allocation_site_mode == TRACK_ALLOCATION_SITE ? allocation_site : nullptr;
- Node* zero = assembler->SmiConstant(Smi::FromInt(0));
+ Node* zero = assembler->SmiConstant(Smi::kZero);
assembler->GotoIf(assembler->SmiEqual(capacity, zero), &zero_capacity);
Node* elements_map = assembler->LoadMap(boilerplate_elements);
@@ -5391,14 +2858,16 @@ compiler::Node* FastCloneShallowArrayStub::Generate(
assembler->Comment("fast double elements path");
if (FLAG_debug_code) {
Label correct_elements_map(assembler), abort(assembler, Label::kDeferred);
- assembler->BranchIf(assembler->IsFixedDoubleArrayMap(elements_map),
- &correct_elements_map, &abort);
+ assembler->Branch(assembler->IsFixedDoubleArrayMap(elements_map),
+ &correct_elements_map, &abort);
assembler->Bind(&abort);
{
Node* abort_id = assembler->SmiConstant(
Smi::FromInt(BailoutReason::kExpectedFixedDoubleArrayMap));
- assembler->TailCallRuntime(Runtime::kAbort, context, abort_id);
+ assembler->CallRuntime(Runtime::kAbort, context, abort_id);
+ result.Bind(assembler->UndefinedConstant());
+ assembler->Goto(&return_result);
}
assembler->Bind(&correct_elements_map);
}
@@ -5544,103 +3013,54 @@ void StoreFastElementStub::GenerateAheadOfTime(Isolate* isolate) {
}
}
-void ArrayConstructorStub::PrintName(std::ostream& os) const { // NOLINT
- os << "ArrayConstructorStub";
- switch (argument_count()) {
- case ANY:
- os << "_Any";
- break;
- case NONE:
- os << "_None";
- break;
- case ONE:
- os << "_One";
- break;
- case MORE_THAN_ONE:
- os << "_More_Than_One";
- break;
- }
- return;
-}
-
-
bool ToBooleanICStub::UpdateStatus(Handle<Object> object) {
- Types new_types = types();
- Types old_types = new_types;
- bool to_boolean_value = new_types.UpdateStatus(isolate(), object);
- TraceTransition(old_types, new_types);
- set_sub_minor_key(TypesBits::update(sub_minor_key(), new_types.ToIntegral()));
- return to_boolean_value;
-}
-
-void ToBooleanICStub::PrintState(std::ostream& os) const { // NOLINT
- os << types();
-}
-
-std::ostream& operator<<(std::ostream& os, const ToBooleanICStub::Types& s) {
- os << "(";
- SimpleListPrinter p(os);
- if (s.IsEmpty()) p.Add("None");
- 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 ToBooleanICStub::Types::UpdateStatus(Isolate* isolate,
- Handle<Object> object) {
- if (object->IsUndefined(isolate)) {
- Add(UNDEFINED);
- return false;
+ ToBooleanHints old_hints = hints();
+ ToBooleanHints new_hints = old_hints;
+ bool to_boolean_value = false; // Dummy initialization.
+ if (object->IsUndefined(isolate())) {
+ new_hints |= ToBooleanHint::kUndefined;
+ to_boolean_value = false;
} else if (object->IsBoolean()) {
- Add(BOOLEAN);
- return object->IsTrue(isolate);
- } else if (object->IsNull(isolate)) {
- Add(NULL_TYPE);
- return false;
+ new_hints |= ToBooleanHint::kBoolean;
+ to_boolean_value = object->IsTrue(isolate());
+ } else if (object->IsNull(isolate())) {
+ new_hints |= ToBooleanHint::kNull;
+ to_boolean_value = false;
} else if (object->IsSmi()) {
- Add(SMI);
- return Smi::cast(*object)->value() != 0;
+ new_hints |= ToBooleanHint::kSmallInteger;
+ to_boolean_value = Smi::cast(*object)->value() != 0;
} else if (object->IsJSReceiver()) {
- Add(SPEC_OBJECT);
- return !object->IsUndetectable();
+ new_hints |= ToBooleanHint::kReceiver;
+ to_boolean_value = !object->IsUndetectable();
} else if (object->IsString()) {
DCHECK(!object->IsUndetectable());
- Add(STRING);
- return String::cast(*object)->length() != 0;
+ new_hints |= ToBooleanHint::kString;
+ to_boolean_value = String::cast(*object)->length() != 0;
} else if (object->IsSymbol()) {
- Add(SYMBOL);
- return true;
+ new_hints |= ToBooleanHint::kSymbol;
+ to_boolean_value = true;
} else if (object->IsHeapNumber()) {
DCHECK(!object->IsUndetectable());
- Add(HEAP_NUMBER);
+ new_hints |= ToBooleanHint::kHeapNumber;
double value = HeapNumber::cast(*object)->value();
- return value != 0 && !std::isnan(value);
+ to_boolean_value = value != 0 && !std::isnan(value);
} else if (object->IsSimd128Value()) {
- Add(SIMD_VALUE);
- return true;
+ new_hints |= ToBooleanHint::kSimdValue;
+ to_boolean_value = true;
} else {
// We should never see an internal object at runtime here!
UNREACHABLE();
- return true;
+ to_boolean_value = true;
}
+ TraceTransition(old_hints, new_hints);
+ set_sub_minor_key(HintsBits::update(sub_minor_key(), new_hints));
+ return to_boolean_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);
+void ToBooleanICStub::PrintState(std::ostream& os) const { // NOLINT
+ os << hints();
}
-
void StubFailureTrampolineStub::GenerateAheadOfTime(Isolate* isolate) {
StubFailureTrampolineStub stub1(isolate, NOT_JS_FUNCTION_STUB_MODE);
StubFailureTrampolineStub stub2(isolate, JS_FUNCTION_STUB_MODE);
@@ -5687,7 +3107,7 @@ void ArrayNoArgumentConstructorStub::GenerateAssembly(
Node* array = assembler->AllocateJSArray(
elements_kind(), array_map,
assembler->IntPtrConstant(JSArray::kPreallocatedArrayElements),
- assembler->SmiConstant(Smi::FromInt(0)), allocation_site);
+ assembler->SmiConstant(Smi::kZero), allocation_site);
assembler->Return(array);
}
@@ -5700,7 +3120,7 @@ void InternalArrayNoArgumentConstructorStub::GenerateAssembly(
Node* array = assembler->AllocateJSArray(
elements_kind(), array_map,
assembler->IntPtrConstant(JSArray::kPreallocatedArrayElements),
- assembler->SmiConstant(Smi::FromInt(0)), nullptr);
+ assembler->SmiConstant(Smi::kZero), nullptr);
assembler->Return(array);
}
@@ -5721,14 +3141,14 @@ void SingleArgumentConstructorCommon(CodeStubAssembler* assembler,
Label call_runtime(assembler, Label::kDeferred);
Node* size = assembler->Parameter(Descriptor::kArraySizeSmiParameter);
- assembler->Branch(assembler->WordIsSmi(size), &smi_size, &call_runtime);
+ assembler->Branch(assembler->TaggedIsSmi(size), &smi_size, &call_runtime);
assembler->Bind(&smi_size);
if (IsFastPackedElementsKind(elements_kind)) {
Label abort(assembler, Label::kDeferred);
assembler->Branch(
- assembler->SmiEqual(size, assembler->SmiConstant(Smi::FromInt(0))),
+ assembler->SmiEqual(size, assembler->SmiConstant(Smi::kZero)),
&small_smi_size, &abort);
assembler->Bind(&abort);
@@ -5828,42 +3248,10 @@ void GrowArrayElementsStub::GenerateAssembly(
}
ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate)
- : PlatformCodeStub(isolate) {
- minor_key_ = ArgumentCountBits::encode(ANY);
-}
-
-ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate,
- int argument_count)
- : PlatformCodeStub(isolate) {
- if (argument_count == 0) {
- minor_key_ = ArgumentCountBits::encode(NONE);
- } else if (argument_count == 1) {
- minor_key_ = ArgumentCountBits::encode(ONE);
- } else if (argument_count >= 2) {
- minor_key_ = ArgumentCountBits::encode(MORE_THAN_ONE);
- } else {
- UNREACHABLE();
- }
-}
+ : PlatformCodeStub(isolate) {}
InternalArrayConstructorStub::InternalArrayConstructorStub(Isolate* isolate)
: PlatformCodeStub(isolate) {}
-Representation RepresentationFromMachineType(MachineType type) {
- if (type == MachineType::Int32()) {
- return Representation::Integer32();
- }
-
- if (type == MachineType::TaggedSigned()) {
- return Representation::Smi();
- }
-
- if (type == MachineType::Pointer()) {
- return Representation::External();
- }
-
- return Representation::Tagged();
-}
-
} // namespace internal
} // namespace v8