| Index: src/code-stubs.cc
|
| diff --git a/src/code-stubs.cc b/src/code-stubs.cc
|
| index 365ededc1bed166bf09d463337b0153c01701626..3798b79e2bd7ee834c44d7979f5b096e926608e6 100644
|
| --- a/src/code-stubs.cc
|
| +++ b/src/code-stubs.cc
|
| @@ -662,368 +662,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,
|
| @@ -1180,180 +818,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,
|
| @@ -1486,158 +950,6 @@ compiler::Node* SubtractWithFeedbackStub::Generate(
|
| 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);
|
| -
|
| - 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->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);
|
| - }
|
| - }
|
| - }
|
| -
|
| - assembler->Bind(&lhs_is_not_smi);
|
| - {
|
| - Node* lhs_map = assembler->LoadMap(lhs);
|
| -
|
| - // 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);
|
| -
|
| - 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);
|
| -
|
| - 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(&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);
|
| - }
|
| - }
|
| - }
|
| -
|
| - 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(&do_fmul);
|
| - {
|
| - 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);
|
| - }
|
| -
|
| - assembler->Bind(&return_result);
|
| - return var_result.value();
|
| -}
|
|
|
| // static
|
| compiler::Node* MultiplyWithFeedbackStub::Generate(
|
| @@ -1756,290 +1068,73 @@ compiler::Node* MultiplyWithFeedbackStub::Generate(
|
| return var_result.value();
|
| }
|
|
|
| +
|
| // static
|
| -compiler::Node* DivideStub::Generate(CodeStubAssembler* assembler,
|
| - compiler::Node* left,
|
| - compiler::Node* right,
|
| - compiler::Node* context) {
|
| +compiler::Node* DivideWithFeedbackStub::Generate(
|
| + CodeStubAssembler* assembler, compiler::Node* dividend,
|
| + compiler::Node* divisor, compiler::Node* slot_id,
|
| + compiler::Node* type_feedback_vector, compiler::Node* context) {
|
| using compiler::Node;
|
| typedef CodeStubAssembler::Label Label;
|
| typedef CodeStubAssembler::Variable Variable;
|
|
|
| // Shared entry point for floating point division.
|
| - Label do_fdiv(assembler), end(assembler);
|
| + Label do_fdiv(assembler), end(assembler), call_divide_stub(assembler);
|
| Variable var_dividend_float64(assembler, MachineRepresentation::kFloat64),
|
| - var_divisor_float64(assembler, MachineRepresentation::kFloat64);
|
| + var_divisor_float64(assembler, MachineRepresentation::kFloat64),
|
| + var_result(assembler, MachineRepresentation::kTagged),
|
| + var_type_feedback(assembler, MachineRepresentation::kWord32);
|
|
|
| Node* number_map = assembler->HeapNumberMapConstant();
|
|
|
| - // 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);
|
| - {
|
| - 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), ÷nd_is_smi,
|
| + ÷nd_is_not_smi);
|
|
|
| - Label dividend_is_smi(assembler), dividend_is_not_smi(assembler);
|
| - assembler->Branch(assembler->WordIsSmi(dividend), ÷nd_is_smi,
|
| - ÷nd_is_not_smi);
|
| + assembler->Bind(÷nd_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(÷nd_is_smi);
|
| + assembler->Bind(&divisor_is_smi);
|
| {
|
| - Label divisor_is_smi(assembler), divisor_is_not_smi(assembler);
|
| - assembler->Branch(assembler->WordIsSmi(divisor), &divisor_is_smi,
|
| - &divisor_is_not_smi);
|
| + Label bailout(assembler);
|
|
|
| - 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)),
|
| + ÷nd_is_zero, ÷nd_is_not_zero);
|
|
|
| - // Do floating point division if {divisor} is zero.
|
| + assembler->Bind(÷nd_is_zero);
|
| + {
|
| assembler->GotoIf(
|
| - assembler->WordEqual(divisor, assembler->IntPtrConstant(0)),
|
| + assembler->IntPtrLessThan(divisor, assembler->IntPtrConstant(0)),
|
| &bailout);
|
| + assembler->Goto(÷nd_is_not_zero);
|
| + }
|
| + assembler->Bind(÷nd_is_not_zero);
|
|
|
| - // 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)),
|
| - ÷nd_is_zero, ÷nd_is_not_zero);
|
| -
|
| - assembler->Bind(÷nd_is_zero);
|
| - {
|
| - assembler->GotoIf(
|
| - assembler->IntPtrLessThan(divisor, assembler->IntPtrConstant(0)),
|
| - &bailout);
|
| - assembler->Goto(÷nd_is_not_zero);
|
| - }
|
| - assembler->Bind(÷nd_is_not_zero);
|
| -
|
| - Node* untagged_divisor = assembler->SmiUntag(divisor);
|
| - Node* untagged_dividend = assembler->SmiUntag(dividend);
|
| + 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);
|
| + // 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(÷nd_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),
|
| - ÷nd_is_number, ÷nd_is_not_number);
|
| -
|
| - assembler->Bind(÷nd_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);
|
| - }
|
| -
|
| - 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(÷nd_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(&do_fdiv);
|
| - {
|
| - Node* value = assembler->Float64Div(var_dividend_float64.value(),
|
| - var_divisor_float64.value());
|
| - var_result.Bind(assembler->ChangeFloat64ToTagged(value));
|
| - assembler->Goto(&end);
|
| - }
|
| - assembler->Bind(&end);
|
| - return var_result.value();
|
| -}
|
| -
|
| -// static
|
| -compiler::Node* DivideWithFeedbackStub::Generate(
|
| - CodeStubAssembler* assembler, compiler::Node* dividend,
|
| - compiler::Node* divisor, compiler::Node* slot_id,
|
| - compiler::Node* type_feedback_vector, compiler::Node* context) {
|
| - using compiler::Node;
|
| - typedef CodeStubAssembler::Label Label;
|
| - typedef CodeStubAssembler::Variable Variable;
|
| -
|
| - // Shared entry point for floating point division.
|
| - Label do_fdiv(assembler), end(assembler), call_divide_stub(assembler);
|
| - Variable var_dividend_float64(assembler, MachineRepresentation::kFloat64),
|
| - var_divisor_float64(assembler, MachineRepresentation::kFloat64),
|
| - var_result(assembler, MachineRepresentation::kTagged),
|
| - var_type_feedback(assembler, MachineRepresentation::kWord32);
|
| -
|
| - Node* number_map = assembler->HeapNumberMapConstant();
|
| -
|
| - Label dividend_is_smi(assembler), dividend_is_not_smi(assembler);
|
| - assembler->Branch(assembler->WordIsSmi(dividend), ÷nd_is_smi,
|
| - ÷nd_is_not_smi);
|
| -
|
| - assembler->Bind(÷nd_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)),
|
| - ÷nd_is_zero, ÷nd_is_not_zero);
|
| -
|
| - assembler->Bind(÷nd_is_zero);
|
| - {
|
| - assembler->GotoIf(
|
| - assembler->IntPtrLessThan(divisor, assembler->IntPtrConstant(0)),
|
| - &bailout);
|
| - assembler->Goto(÷nd_is_not_zero);
|
| - }
|
| - assembler->Bind(÷nd_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->Bind(&divisor_is_minus_one);
|
| + {
|
| assembler->GotoIf(
|
| assembler->Word32Equal(
|
| untagged_dividend,
|
| @@ -2151,165 +1246,6 @@ compiler::Node* DivideWithFeedbackStub::Generate(
|
| }
|
|
|
| // 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);
|
| -
|
| - // Shared entry point for floating point modulus.
|
| - Label do_fmod(assembler);
|
| - Variable var_dividend_float64(assembler, MachineRepresentation::kFloat64),
|
| - var_divisor_float64(assembler, MachineRepresentation::kFloat64);
|
| -
|
| - Node* number_map = assembler->HeapNumberMapConstant();
|
| -
|
| - // 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);
|
| - {
|
| - 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), ÷nd_is_smi,
|
| - ÷nd_is_not_smi);
|
| -
|
| - assembler->Bind(÷nd_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(÷nd_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),
|
| - ÷nd_is_number, ÷nd_is_not_number);
|
| -
|
| - assembler->Bind(÷nd_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);
|
| - }
|
| -
|
| - 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(÷nd_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(&do_fmod);
|
| - {
|
| - Node* value = assembler->Float64Mod(var_dividend_float64.value(),
|
| - var_divisor_float64.value());
|
| - var_result.Bind(assembler->ChangeFloat64ToTagged(value));
|
| - assembler->Goto(&return_result);
|
| - }
|
| -
|
| - assembler->Bind(&return_result);
|
| - return var_result.value();
|
| -}
|
| -
|
| -// static
|
| compiler::Node* ModulusWithFeedbackStub::Generate(
|
| CodeStubAssembler* assembler, compiler::Node* dividend,
|
| compiler::Node* divisor, compiler::Node* slot_id,
|
| @@ -2425,95 +1361,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,
|
| @@ -2595,1573 +1442,140 @@ compiler::Node* IncStub::Generate(CodeStubAssembler* assembler,
|
| var_type_feedback.Bind(
|
| assembler->Int32Constant(BinaryOperationFeedback::kAny));
|
| value_var.Bind(assembler->CallStub(callable, context, value));
|
| - assembler->Goto(&start);
|
| - }
|
| - }
|
| - }
|
| -
|
| - assembler->Bind(&do_finc);
|
| - {
|
| - Node* finc_value = var_finc_value.value();
|
| - Node* one = assembler->Float64Constant(1.0);
|
| - Node* finc_result = assembler->Float64Add(finc_value, one);
|
| - var_type_feedback.Bind(assembler->Word32Or(
|
| - var_type_feedback.value(),
|
| - assembler->Int32Constant(BinaryOperationFeedback::kNumber)));
|
| - result_var.Bind(assembler->ChangeFloat64ToTagged(finc_result));
|
| - assembler->Goto(&end);
|
| - }
|
| -
|
| - assembler->Bind(&end);
|
| - assembler->UpdateFeedback(var_type_feedback.value(), type_feedback_vector,
|
| - slot_id);
|
| - return result_var.value();
|
| -}
|
| -
|
| -// static
|
| -compiler::Node* DecStub::Generate(CodeStubAssembler* assembler,
|
| - compiler::Node* value,
|
| - compiler::Node* context,
|
| - compiler::Node* type_feedback_vector,
|
| - compiler::Node* slot_id) {
|
| - typedef CodeStubAssembler::Label Label;
|
| - typedef compiler::Node Node;
|
| - typedef CodeStubAssembler::Variable Variable;
|
| -
|
| - // Shared entry for floating point decrement.
|
| - Label do_fdec(assembler), end(assembler);
|
| - Variable var_fdec_value(assembler, MachineRepresentation::kFloat64);
|
| -
|
| - // We might need to try again due to ToNumber conversion.
|
| - Variable value_var(assembler, MachineRepresentation::kTagged);
|
| - Variable result_var(assembler, MachineRepresentation::kTagged);
|
| - Variable var_type_feedback(assembler, MachineRepresentation::kWord32);
|
| - Variable* loop_vars[] = {&value_var, &var_type_feedback};
|
| - Label start(assembler, 2, loop_vars);
|
| - var_type_feedback.Bind(
|
| - assembler->Int32Constant(BinaryOperationFeedback::kNone));
|
| - value_var.Bind(value);
|
| - assembler->Goto(&start);
|
| - assembler->Bind(&start);
|
| - {
|
| - value = value_var.value();
|
| -
|
| - Label if_issmi(assembler), if_isnotsmi(assembler);
|
| - assembler->Branch(assembler->WordIsSmi(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* 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_notoverflow);
|
| - var_type_feedback.Bind(assembler->Word32Or(
|
| - var_type_feedback.value(),
|
| - assembler->Int32Constant(BinaryOperationFeedback::kSignedSmall)));
|
| - result_var.Bind(assembler->Projection(0, pair));
|
| - assembler->Goto(&end);
|
| -
|
| - assembler->Bind(&if_overflow);
|
| - {
|
| - var_fdec_value.Bind(assembler->SmiToFloat64(value));
|
| - assembler->Goto(&do_fdec);
|
| - }
|
| - }
|
| -
|
| - assembler->Bind(&if_isnotsmi);
|
| - {
|
| - // Check if the value is a HeapNumber.
|
| - Label if_valueisnumber(assembler),
|
| - if_valuenotnumber(assembler, Label::kDeferred);
|
| - Node* value_map = assembler->LoadMap(value);
|
| - assembler->Branch(assembler->IsHeapNumberMap(value_map),
|
| - &if_valueisnumber, &if_valuenotnumber);
|
| -
|
| - assembler->Bind(&if_valueisnumber);
|
| - {
|
| - // Load the HeapNumber value.
|
| - var_fdec_value.Bind(assembler->LoadHeapNumberValue(value));
|
| - assembler->Goto(&do_fdec);
|
| - }
|
| -
|
| - 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);
|
| - }
|
| - }
|
| - }
|
| -
|
| - assembler->Bind(&do_fdec);
|
| - {
|
| - Node* fdec_value = var_fdec_value.value();
|
| - Node* one = assembler->Float64Constant(1.0);
|
| - Node* fdec_result = assembler->Float64Sub(fdec_value, one);
|
| - var_type_feedback.Bind(assembler->Word32Or(
|
| - var_type_feedback.value(),
|
| - assembler->Int32Constant(BinaryOperationFeedback::kNumber)));
|
| - result_var.Bind(assembler->ChangeFloat64ToTagged(fdec_result));
|
| - assembler->Goto(&end);
|
| - }
|
| -
|
| - assembler->Bind(&end);
|
| - assembler->UpdateFeedback(var_type_feedback.value(), type_feedback_vector,
|
| - slot_id);
|
| - return result_var.value();
|
| -}
|
| -
|
| -// ES6 section 21.1.3.19 String.prototype.substring ( start, end )
|
| -compiler::Node* SubStringStub::Generate(CodeStubAssembler* assembler,
|
| - compiler::Node* string,
|
| - compiler::Node* from,
|
| - compiler::Node* to,
|
| - compiler::Node* context) {
|
| - 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->Goto(&start);
|
| }
|
| }
|
| -
|
| - 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);
|
| + assembler->Bind(&do_finc);
|
| {
|
| - result.Bind(assembler->BooleanConstant(mode == kNegateResult));
|
| + Node* finc_value = var_finc_value.value();
|
| + Node* one = assembler->Float64Constant(1.0);
|
| + Node* finc_result = assembler->Float64Add(finc_value, one);
|
| + var_type_feedback.Bind(assembler->Word32Or(
|
| + var_type_feedback.value(),
|
| + assembler->Int32Constant(BinaryOperationFeedback::kNumber)));
|
| + result_var.Bind(assembler->ChangeFloat64ToTagged(finc_result));
|
| assembler->Goto(&end);
|
| }
|
|
|
| assembler->Bind(&end);
|
| - return result.value();
|
| + assembler->UpdateFeedback(var_type_feedback.value(), type_feedback_vector,
|
| + slot_id);
|
| + return result_var.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;
|
| - // }
|
| - // }
|
| - // }
|
| -
|
| +// static
|
| +compiler::Node* DecStub::Generate(CodeStubAssembler* assembler,
|
| + compiler::Node* value,
|
| + compiler::Node* context,
|
| + compiler::Node* type_feedback_vector,
|
| + compiler::Node* slot_id) {
|
| typedef CodeStubAssembler::Label Label;
|
| - typedef CodeStubAssembler::Variable Variable;
|
| typedef compiler::Node Node;
|
| + typedef CodeStubAssembler::Variable Variable;
|
|
|
| - 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);
|
| - }
|
| + // Shared entry for floating point decrement.
|
| + Label do_fdec(assembler), end(assembler);
|
| + Variable var_fdec_value(assembler, MachineRepresentation::kFloat64);
|
|
|
| - assembler->Bind(&if_notsame);
|
| + // We might need to try again due to ToNumber conversion.
|
| + Variable value_var(assembler, MachineRepresentation::kTagged);
|
| + Variable result_var(assembler, MachineRepresentation::kTagged);
|
| + Variable var_type_feedback(assembler, MachineRepresentation::kWord32);
|
| + Variable* loop_vars[] = {&value_var, &var_type_feedback};
|
| + Label start(assembler, 2, loop_vars);
|
| + var_type_feedback.Bind(
|
| + assembler->Int32Constant(BinaryOperationFeedback::kNone));
|
| + value_var.Bind(value);
|
| + assembler->Goto(&start);
|
| + assembler->Bind(&start);
|
| {
|
| - // 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();
|
| + value = value_var.value();
|
|
|
| - // 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);
|
| + Label if_issmi(assembler), if_isnotsmi(assembler);
|
| + assembler->Branch(assembler->WordIsSmi(value), &if_issmi, &if_isnotsmi);
|
|
|
| - assembler->Bind(&if_lhsisnotsmi);
|
| + assembler->Bind(&if_issmi);
|
| {
|
| - // 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);
|
| + // Try fast Smi subtraction first.
|
| + Node* one = assembler->SmiConstant(Smi::FromInt(1));
|
| + Node* pair = assembler->SmiSubWithOverflow(value, one);
|
| + Node* overflow = assembler->Projection(1, pair);
|
|
|
| - // Perform a floating point comparison of {lhs} and {rhs}.
|
| - assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_equal,
|
| - &if_notequal);
|
| - }
|
| + // Check if the Smi subtraction overflowed.
|
| + Label if_overflow(assembler), if_notoverflow(assembler);
|
| + assembler->Branch(overflow, &if_overflow, &if_notoverflow);
|
|
|
| - 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_notoverflow);
|
| + var_type_feedback.Bind(assembler->Word32Or(
|
| + var_type_feedback.value(),
|
| + assembler->Int32Constant(BinaryOperationFeedback::kSignedSmall)));
|
| + result_var.Bind(assembler->Projection(0, pair));
|
| + assembler->Goto(&end);
|
|
|
| - assembler->Bind(&if_lhsisnotnumber);
|
| + assembler->Bind(&if_overflow);
|
| {
|
| - // 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);
|
| - }
|
| - }
|
| + var_fdec_value.Bind(assembler->SmiToFloat64(value));
|
| + assembler->Goto(&do_fdec);
|
| }
|
| }
|
|
|
| - assembler->Bind(&if_lhsissmi);
|
| + assembler->Bind(&if_isnotsmi);
|
| {
|
| - // 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);
|
| + // Check if the value is a HeapNumber.
|
| + Label if_valueisnumber(assembler),
|
| + if_valuenotnumber(assembler, Label::kDeferred);
|
| + Node* value_map = assembler->LoadMap(value);
|
| + assembler->Branch(assembler->IsHeapNumberMap(value_map),
|
| + &if_valueisnumber, &if_valuenotnumber);
|
|
|
| - assembler->Bind(&if_rhsisnotsmi);
|
| + assembler->Bind(&if_valueisnumber);
|
| {
|
| - // 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);
|
| - }
|
| + // Load the HeapNumber value.
|
| + var_fdec_value.Bind(assembler->LoadHeapNumberValue(value));
|
| + assembler->Goto(&do_fdec);
|
| + }
|
|
|
| - assembler->Bind(&if_rhsisnotnumber);
|
| - assembler->Goto(&if_notequal);
|
| + 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);
|
| }
|
| }
|
| }
|
|
|
| - assembler->Bind(&if_equal);
|
| - {
|
| - result.Bind(assembler->BooleanConstant(mode == kDontNegateResult));
|
| - assembler->Goto(&end);
|
| - }
|
| -
|
| - assembler->Bind(&if_notequal);
|
| + assembler->Bind(&do_fdec);
|
| {
|
| - result.Bind(assembler->BooleanConstant(mode == kNegateResult));
|
| + Node* fdec_value = var_fdec_value.value();
|
| + Node* one = assembler->Float64Constant(1.0);
|
| + Node* fdec_result = assembler->Float64Sub(fdec_value, one);
|
| + var_type_feedback.Bind(assembler->Word32Or(
|
| + var_type_feedback.value(),
|
| + assembler->Int32Constant(BinaryOperationFeedback::kNumber)));
|
| + result_var.Bind(assembler->ChangeFloat64ToTagged(fdec_result));
|
| assembler->Goto(&end);
|
| }
|
|
|
| assembler->Bind(&end);
|
| - return result.value();
|
| + assembler->UpdateFeedback(var_type_feedback.value(), type_feedback_vector,
|
| + slot_id);
|
| + return result_var.value();
|
| }
|
|
|
| -} // namespace
|
| +// ES6 section 21.1.3.19 String.prototype.substring ( start, end )
|
| +compiler::Node* SubStringStub::Generate(CodeStubAssembler* assembler,
|
| + compiler::Node* string,
|
| + compiler::Node* from,
|
| + compiler::Node* to,
|
| + compiler::Node* context) {
|
| + return assembler->SubString(context, string, from, to);
|
| +}
|
|
|
| void LoadApiGetterStub::GenerateAssembly(CodeStubAssembler* assembler) const {
|
| typedef compiler::Node Node;
|
| @@ -4392,155 +1806,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;
|
| @@ -4841,111 +2106,6 @@ void StringAddStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
|
| 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;
|
|
|