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