| Index: src/compiler/js-generic-lowering.cc
|
| diff --git a/src/compiler/js-generic-lowering.cc b/src/compiler/js-generic-lowering.cc
|
| index df2d9086efef37fd02f73d35c947ce7538a73329..b6cd40d21df56edff64f226b2f9fb7395ff5571b 100644
|
| --- a/src/compiler/js-generic-lowering.cc
|
| +++ b/src/compiler/js-generic-lowering.cc
|
| @@ -81,22 +81,117 @@
|
| REPLACE_BINARY_OP_IC_CALL(JSModulus, Token::MOD)
|
| #undef REPLACE_BINARY_OP_IC_CALL
|
|
|
| +
|
| +// These ops are not language mode dependent; we arbitrarily pass Strength::WEAK
|
| +// here.
|
| +#define REPLACE_COMPARE_IC_CALL(op, token) \
|
| + void JSGenericLowering::Lower##op(Node* node) { \
|
| + ReplaceWithCompareIC(node, token); \
|
| + }
|
| +REPLACE_COMPARE_IC_CALL(JSEqual, Token::EQ)
|
| +REPLACE_COMPARE_IC_CALL(JSNotEqual, Token::NE)
|
| +REPLACE_COMPARE_IC_CALL(JSStrictEqual, Token::EQ_STRICT)
|
| +REPLACE_COMPARE_IC_CALL(JSStrictNotEqual, Token::NE_STRICT)
|
| +REPLACE_COMPARE_IC_CALL(JSLessThan, Token::LT)
|
| +REPLACE_COMPARE_IC_CALL(JSGreaterThan, Token::GT)
|
| +REPLACE_COMPARE_IC_CALL(JSLessThanOrEqual, Token::LTE)
|
| +REPLACE_COMPARE_IC_CALL(JSGreaterThanOrEqual, Token::GTE)
|
| +#undef REPLACE_COMPARE_IC_CALL
|
| +
|
| +
|
| #define REPLACE_RUNTIME_CALL(op, fun) \
|
| void JSGenericLowering::Lower##op(Node* node) { \
|
| ReplaceWithRuntimeCall(node, fun); \
|
| }
|
| -REPLACE_RUNTIME_CALL(JSEqual, Runtime::kEqual)
|
| -REPLACE_RUNTIME_CALL(JSNotEqual, Runtime::kNotEqual)
|
| -REPLACE_RUNTIME_CALL(JSStrictEqual, Runtime::kStrictEqual)
|
| -REPLACE_RUNTIME_CALL(JSStrictNotEqual, Runtime::kStrictNotEqual)
|
| -REPLACE_RUNTIME_CALL(JSLessThan, Runtime::kLessThan)
|
| -REPLACE_RUNTIME_CALL(JSGreaterThan, Runtime::kGreaterThan)
|
| -REPLACE_RUNTIME_CALL(JSLessThanOrEqual, Runtime::kLessThanOrEqual)
|
| -REPLACE_RUNTIME_CALL(JSGreaterThanOrEqual, Runtime::kGreaterThanOrEqual)
|
| REPLACE_RUNTIME_CALL(JSCreateWithContext, Runtime::kPushWithContext)
|
| REPLACE_RUNTIME_CALL(JSCreateModuleContext, Runtime::kPushModuleContext)
|
| REPLACE_RUNTIME_CALL(JSConvertReceiver, Runtime::kConvertReceiver)
|
| -#undef REPLACE_RUNTIME_CALL
|
| +#undef REPLACE_RUNTIME
|
| +
|
| +
|
| +static CallDescriptor::Flags FlagsForNode(Node* node) {
|
| + CallDescriptor::Flags result = CallDescriptor::kNoFlags;
|
| + if (OperatorProperties::GetFrameStateInputCount(node->op()) > 0) {
|
| + result |= CallDescriptor::kNeedsFrameState;
|
| + }
|
| + return result;
|
| +}
|
| +
|
| +void JSGenericLowering::ReplaceWithCompareIC(Node* node, Token::Value token) {
|
| + Callable callable = CodeFactory::CompareIC(isolate(), token);
|
| +
|
| + // Create a new call node asking a CompareIC for help.
|
| + NodeVector inputs(zone());
|
| + inputs.reserve(node->InputCount() + 1);
|
| + inputs.push_back(jsgraph()->HeapConstant(callable.code()));
|
| + inputs.push_back(NodeProperties::GetValueInput(node, 0));
|
| + inputs.push_back(NodeProperties::GetValueInput(node, 1));
|
| + inputs.push_back(NodeProperties::GetContextInput(node));
|
| + // Some comparisons (StrictEqual) don't have an effect, control or frame
|
| + // state inputs, so handle those cases here.
|
| + if (OperatorProperties::GetFrameStateInputCount(node->op()) > 0) {
|
| + inputs.push_back(NodeProperties::GetFrameStateInput(node, 0));
|
| + }
|
| + Node* effect = (node->op()->EffectInputCount() > 0)
|
| + ? NodeProperties::GetEffectInput(node)
|
| + : graph()->start();
|
| + inputs.push_back(effect);
|
| + Node* control = (node->op()->ControlInputCount() > 0)
|
| + ? NodeProperties::GetControlInput(node)
|
| + : graph()->start();
|
| + inputs.push_back(control);
|
| + CallDescriptor* desc_compare = Linkage::GetStubCallDescriptor(
|
| + isolate(), zone(), callable.descriptor(), 0,
|
| + CallDescriptor::kPatchableCallSiteWithNop | FlagsForNode(node),
|
| + Operator::kNoProperties, MachineType::IntPtr());
|
| + Node* compare =
|
| + graph()->NewNode(common()->Call(desc_compare),
|
| + static_cast<int>(inputs.size()), &inputs.front());
|
| +
|
| + // Decide how the return value from the above CompareIC can be converted into
|
| + // a JavaScript boolean oddball depending on the given token.
|
| + Node* false_value = jsgraph()->FalseConstant();
|
| + Node* true_value = jsgraph()->TrueConstant();
|
| + const Operator* op = nullptr;
|
| + switch (token) {
|
| + case Token::EQ: // a == 0
|
| + case Token::EQ_STRICT:
|
| + op = machine()->WordEqual();
|
| + break;
|
| + case Token::NE: // a != 0 becomes !(a == 0)
|
| + case Token::NE_STRICT:
|
| + op = machine()->WordEqual();
|
| + std::swap(true_value, false_value);
|
| + break;
|
| + case Token::LT: // a < 0
|
| + op = machine()->IntLessThan();
|
| + break;
|
| + case Token::GT: // a > 0 becomes !(a <= 0)
|
| + op = machine()->IntLessThanOrEqual();
|
| + std::swap(true_value, false_value);
|
| + break;
|
| + case Token::LTE: // a <= 0
|
| + op = machine()->IntLessThanOrEqual();
|
| + break;
|
| + case Token::GTE: // a >= 0 becomes !(a < 0)
|
| + op = machine()->IntLessThan();
|
| + std::swap(true_value, false_value);
|
| + break;
|
| + default:
|
| + UNREACHABLE();
|
| + }
|
| + Node* booleanize = graph()->NewNode(op, compare, jsgraph()->ZeroConstant());
|
| +
|
| + // Finally patch the original node to select a boolean.
|
| + NodeProperties::ReplaceUses(node, node, compare, compare, compare);
|
| + node->TrimInputCount(3);
|
| + node->ReplaceInput(0, booleanize);
|
| + node->ReplaceInput(1, true_value);
|
| + node->ReplaceInput(2, false_value);
|
| + NodeProperties::ChangeOp(node,
|
| + common()->Select(MachineRepresentation::kTagged));
|
| +}
|
| +
|
|
|
| void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
|
| CallDescriptor::Flags flags) {
|
| @@ -112,12 +207,11 @@
|
| void JSGenericLowering::ReplaceWithRuntimeCall(Node* node,
|
| Runtime::FunctionId f,
|
| int nargs_override) {
|
| - CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
|
| Operator::Properties properties = node->op()->properties();
|
| const Runtime::Function* fun = Runtime::FunctionForId(f);
|
| int nargs = (nargs_override < 0) ? fun->nargs : nargs_override;
|
| - CallDescriptor* desc =
|
| - Linkage::GetRuntimeCallDescriptor(zone(), f, nargs, properties, flags);
|
| + CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
|
| + zone(), f, nargs, properties, CallDescriptor::kNeedsFrameState);
|
| Node* ref = jsgraph()->ExternalConstant(ExternalReference(f, isolate()));
|
| Node* arity = jsgraph()->Int32Constant(nargs);
|
| node->InsertInput(zone(), 0, jsgraph()->CEntryStubConstant(fun->result_size));
|
|
|