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 |