| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/code-factory.h" | 5 #include "src/code-factory.h" |
| 6 #include "src/code-stubs.h" | 6 #include "src/code-stubs.h" |
| 7 #include "src/compiler/common-operator.h" | 7 #include "src/compiler/common-operator.h" |
| 8 #include "src/compiler/js-generic-lowering.h" | 8 #include "src/compiler/js-generic-lowering.h" |
| 9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
| 10 #include "src/compiler/machine-operator.h" | 10 #include "src/compiler/machine-operator.h" |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 REPLACE_BINARY_OP_IC_CALL(JSShiftLeft, Token::SHL) | 76 REPLACE_BINARY_OP_IC_CALL(JSShiftLeft, Token::SHL) |
| 77 REPLACE_BINARY_OP_IC_CALL(JSShiftRight, Token::SAR) | 77 REPLACE_BINARY_OP_IC_CALL(JSShiftRight, Token::SAR) |
| 78 REPLACE_BINARY_OP_IC_CALL(JSShiftRightLogical, Token::SHR) | 78 REPLACE_BINARY_OP_IC_CALL(JSShiftRightLogical, Token::SHR) |
| 79 REPLACE_BINARY_OP_IC_CALL(JSAdd, Token::ADD) | 79 REPLACE_BINARY_OP_IC_CALL(JSAdd, Token::ADD) |
| 80 REPLACE_BINARY_OP_IC_CALL(JSSubtract, Token::SUB) | 80 REPLACE_BINARY_OP_IC_CALL(JSSubtract, Token::SUB) |
| 81 REPLACE_BINARY_OP_IC_CALL(JSMultiply, Token::MUL) | 81 REPLACE_BINARY_OP_IC_CALL(JSMultiply, Token::MUL) |
| 82 REPLACE_BINARY_OP_IC_CALL(JSDivide, Token::DIV) | 82 REPLACE_BINARY_OP_IC_CALL(JSDivide, Token::DIV) |
| 83 REPLACE_BINARY_OP_IC_CALL(JSModulus, Token::MOD) | 83 REPLACE_BINARY_OP_IC_CALL(JSModulus, Token::MOD) |
| 84 #undef REPLACE_BINARY_OP_IC_CALL | 84 #undef REPLACE_BINARY_OP_IC_CALL |
| 85 | 85 |
| 86 | |
| 87 // These ops are not language mode dependent; we arbitrarily pass Strength::WEAK | |
| 88 // here. | |
| 89 #define REPLACE_COMPARE_IC_CALL(op, token) \ | |
| 90 void JSGenericLowering::Lower##op(Node* node) { \ | |
| 91 ReplaceWithCompareIC(node, token); \ | |
| 92 } | |
| 93 REPLACE_COMPARE_IC_CALL(JSEqual, Token::EQ) | |
| 94 REPLACE_COMPARE_IC_CALL(JSNotEqual, Token::NE) | |
| 95 REPLACE_COMPARE_IC_CALL(JSStrictEqual, Token::EQ_STRICT) | |
| 96 REPLACE_COMPARE_IC_CALL(JSStrictNotEqual, Token::NE_STRICT) | |
| 97 REPLACE_COMPARE_IC_CALL(JSLessThan, Token::LT) | |
| 98 REPLACE_COMPARE_IC_CALL(JSGreaterThan, Token::GT) | |
| 99 REPLACE_COMPARE_IC_CALL(JSLessThanOrEqual, Token::LTE) | |
| 100 REPLACE_COMPARE_IC_CALL(JSGreaterThanOrEqual, Token::GTE) | |
| 101 #undef REPLACE_COMPARE_IC_CALL | |
| 102 | |
| 103 | |
| 104 #define REPLACE_RUNTIME_CALL(op, fun) \ | 86 #define REPLACE_RUNTIME_CALL(op, fun) \ |
| 105 void JSGenericLowering::Lower##op(Node* node) { \ | 87 void JSGenericLowering::Lower##op(Node* node) { \ |
| 106 ReplaceWithRuntimeCall(node, fun); \ | 88 ReplaceWithRuntimeCall(node, fun); \ |
| 107 } | 89 } |
| 90 REPLACE_RUNTIME_CALL(JSEqual, Runtime::kEqual) |
| 91 REPLACE_RUNTIME_CALL(JSNotEqual, Runtime::kNotEqual) |
| 92 REPLACE_RUNTIME_CALL(JSStrictEqual, Runtime::kStrictEqual) |
| 93 REPLACE_RUNTIME_CALL(JSStrictNotEqual, Runtime::kStrictNotEqual) |
| 94 REPLACE_RUNTIME_CALL(JSLessThan, Runtime::kLessThan) |
| 95 REPLACE_RUNTIME_CALL(JSGreaterThan, Runtime::kGreaterThan) |
| 96 REPLACE_RUNTIME_CALL(JSLessThanOrEqual, Runtime::kLessThanOrEqual) |
| 97 REPLACE_RUNTIME_CALL(JSGreaterThanOrEqual, Runtime::kGreaterThanOrEqual) |
| 108 REPLACE_RUNTIME_CALL(JSCreateWithContext, Runtime::kPushWithContext) | 98 REPLACE_RUNTIME_CALL(JSCreateWithContext, Runtime::kPushWithContext) |
| 109 REPLACE_RUNTIME_CALL(JSCreateModuleContext, Runtime::kPushModuleContext) | 99 REPLACE_RUNTIME_CALL(JSCreateModuleContext, Runtime::kPushModuleContext) |
| 110 REPLACE_RUNTIME_CALL(JSConvertReceiver, Runtime::kConvertReceiver) | 100 REPLACE_RUNTIME_CALL(JSConvertReceiver, Runtime::kConvertReceiver) |
| 111 #undef REPLACE_RUNTIME | 101 #undef REPLACE_RUNTIME_CALL |
| 112 | |
| 113 | |
| 114 static CallDescriptor::Flags FlagsForNode(Node* node) { | |
| 115 CallDescriptor::Flags result = CallDescriptor::kNoFlags; | |
| 116 if (OperatorProperties::GetFrameStateInputCount(node->op()) > 0) { | |
| 117 result |= CallDescriptor::kNeedsFrameState; | |
| 118 } | |
| 119 return result; | |
| 120 } | |
| 121 | |
| 122 void JSGenericLowering::ReplaceWithCompareIC(Node* node, Token::Value token) { | |
| 123 Callable callable = CodeFactory::CompareIC(isolate(), token); | |
| 124 | |
| 125 // Create a new call node asking a CompareIC for help. | |
| 126 NodeVector inputs(zone()); | |
| 127 inputs.reserve(node->InputCount() + 1); | |
| 128 inputs.push_back(jsgraph()->HeapConstant(callable.code())); | |
| 129 inputs.push_back(NodeProperties::GetValueInput(node, 0)); | |
| 130 inputs.push_back(NodeProperties::GetValueInput(node, 1)); | |
| 131 inputs.push_back(NodeProperties::GetContextInput(node)); | |
| 132 // Some comparisons (StrictEqual) don't have an effect, control or frame | |
| 133 // state inputs, so handle those cases here. | |
| 134 if (OperatorProperties::GetFrameStateInputCount(node->op()) > 0) { | |
| 135 inputs.push_back(NodeProperties::GetFrameStateInput(node, 0)); | |
| 136 } | |
| 137 Node* effect = (node->op()->EffectInputCount() > 0) | |
| 138 ? NodeProperties::GetEffectInput(node) | |
| 139 : graph()->start(); | |
| 140 inputs.push_back(effect); | |
| 141 Node* control = (node->op()->ControlInputCount() > 0) | |
| 142 ? NodeProperties::GetControlInput(node) | |
| 143 : graph()->start(); | |
| 144 inputs.push_back(control); | |
| 145 CallDescriptor* desc_compare = Linkage::GetStubCallDescriptor( | |
| 146 isolate(), zone(), callable.descriptor(), 0, | |
| 147 CallDescriptor::kPatchableCallSiteWithNop | FlagsForNode(node), | |
| 148 Operator::kNoProperties, MachineType::IntPtr()); | |
| 149 Node* compare = | |
| 150 graph()->NewNode(common()->Call(desc_compare), | |
| 151 static_cast<int>(inputs.size()), &inputs.front()); | |
| 152 | |
| 153 // Decide how the return value from the above CompareIC can be converted into | |
| 154 // a JavaScript boolean oddball depending on the given token. | |
| 155 Node* false_value = jsgraph()->FalseConstant(); | |
| 156 Node* true_value = jsgraph()->TrueConstant(); | |
| 157 const Operator* op = nullptr; | |
| 158 switch (token) { | |
| 159 case Token::EQ: // a == 0 | |
| 160 case Token::EQ_STRICT: | |
| 161 op = machine()->WordEqual(); | |
| 162 break; | |
| 163 case Token::NE: // a != 0 becomes !(a == 0) | |
| 164 case Token::NE_STRICT: | |
| 165 op = machine()->WordEqual(); | |
| 166 std::swap(true_value, false_value); | |
| 167 break; | |
| 168 case Token::LT: // a < 0 | |
| 169 op = machine()->IntLessThan(); | |
| 170 break; | |
| 171 case Token::GT: // a > 0 becomes !(a <= 0) | |
| 172 op = machine()->IntLessThanOrEqual(); | |
| 173 std::swap(true_value, false_value); | |
| 174 break; | |
| 175 case Token::LTE: // a <= 0 | |
| 176 op = machine()->IntLessThanOrEqual(); | |
| 177 break; | |
| 178 case Token::GTE: // a >= 0 becomes !(a < 0) | |
| 179 op = machine()->IntLessThan(); | |
| 180 std::swap(true_value, false_value); | |
| 181 break; | |
| 182 default: | |
| 183 UNREACHABLE(); | |
| 184 } | |
| 185 Node* booleanize = graph()->NewNode(op, compare, jsgraph()->ZeroConstant()); | |
| 186 | |
| 187 // Finally patch the original node to select a boolean. | |
| 188 NodeProperties::ReplaceUses(node, node, compare, compare, compare); | |
| 189 node->TrimInputCount(3); | |
| 190 node->ReplaceInput(0, booleanize); | |
| 191 node->ReplaceInput(1, true_value); | |
| 192 node->ReplaceInput(2, false_value); | |
| 193 NodeProperties::ChangeOp(node, | |
| 194 common()->Select(MachineRepresentation::kTagged)); | |
| 195 } | |
| 196 | |
| 197 | 102 |
| 198 void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable, | 103 void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable, |
| 199 CallDescriptor::Flags flags) { | 104 CallDescriptor::Flags flags) { |
| 200 Operator::Properties properties = node->op()->properties(); | 105 Operator::Properties properties = node->op()->properties(); |
| 201 CallDescriptor* desc = Linkage::GetStubCallDescriptor( | 106 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
| 202 isolate(), zone(), callable.descriptor(), 0, flags, properties); | 107 isolate(), zone(), callable.descriptor(), 0, flags, properties); |
| 203 Node* stub_code = jsgraph()->HeapConstant(callable.code()); | 108 Node* stub_code = jsgraph()->HeapConstant(callable.code()); |
| 204 node->InsertInput(zone(), 0, stub_code); | 109 node->InsertInput(zone(), 0, stub_code); |
| 205 NodeProperties::ChangeOp(node, common()->Call(desc)); | 110 NodeProperties::ChangeOp(node, common()->Call(desc)); |
| 206 } | 111 } |
| 207 | 112 |
| 208 | 113 |
| 209 void JSGenericLowering::ReplaceWithRuntimeCall(Node* node, | 114 void JSGenericLowering::ReplaceWithRuntimeCall(Node* node, |
| 210 Runtime::FunctionId f, | 115 Runtime::FunctionId f, |
| 211 int nargs_override) { | 116 int nargs_override) { |
| 117 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node); |
| 212 Operator::Properties properties = node->op()->properties(); | 118 Operator::Properties properties = node->op()->properties(); |
| 213 const Runtime::Function* fun = Runtime::FunctionForId(f); | 119 const Runtime::Function* fun = Runtime::FunctionForId(f); |
| 214 int nargs = (nargs_override < 0) ? fun->nargs : nargs_override; | 120 int nargs = (nargs_override < 0) ? fun->nargs : nargs_override; |
| 215 CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor( | 121 CallDescriptor* desc = |
| 216 zone(), f, nargs, properties, CallDescriptor::kNeedsFrameState); | 122 Linkage::GetRuntimeCallDescriptor(zone(), f, nargs, properties, flags); |
| 217 Node* ref = jsgraph()->ExternalConstant(ExternalReference(f, isolate())); | 123 Node* ref = jsgraph()->ExternalConstant(ExternalReference(f, isolate())); |
| 218 Node* arity = jsgraph()->Int32Constant(nargs); | 124 Node* arity = jsgraph()->Int32Constant(nargs); |
| 219 node->InsertInput(zone(), 0, jsgraph()->CEntryStubConstant(fun->result_size)); | 125 node->InsertInput(zone(), 0, jsgraph()->CEntryStubConstant(fun->result_size)); |
| 220 node->InsertInput(zone(), nargs + 1, ref); | 126 node->InsertInput(zone(), nargs + 1, ref); |
| 221 node->InsertInput(zone(), nargs + 2, arity); | 127 node->InsertInput(zone(), nargs + 2, arity); |
| 222 NodeProperties::ChangeOp(node, common()->Call(desc)); | 128 NodeProperties::ChangeOp(node, common()->Call(desc)); |
| 223 } | 129 } |
| 224 | 130 |
| 225 | 131 |
| 226 void JSGenericLowering::LowerJSTypeOf(Node* node) { | 132 void JSGenericLowering::LowerJSTypeOf(Node* node) { |
| (...skipping 637 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 864 } | 770 } |
| 865 | 771 |
| 866 | 772 |
| 867 MachineOperatorBuilder* JSGenericLowering::machine() const { | 773 MachineOperatorBuilder* JSGenericLowering::machine() const { |
| 868 return jsgraph()->machine(); | 774 return jsgraph()->machine(); |
| 869 } | 775 } |
| 870 | 776 |
| 871 } // namespace compiler | 777 } // namespace compiler |
| 872 } // namespace internal | 778 } // namespace internal |
| 873 } // namespace v8 | 779 } // namespace v8 |
| OLD | NEW |