Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: src/compiler/js-generic-lowering.cc

Issue 426233002: Land the Fan (disabled) (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Review feedback, rebase and "git cl format" Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/compiler/js-generic-lowering.h ('k') | src/compiler/js-graph.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "src/code-stubs.h"
6 #include "src/compiler/common-operator.h"
7 #include "src/compiler/graph-inl.h"
8 #include "src/compiler/js-generic-lowering.h"
9 #include "src/compiler/machine-operator.h"
10 #include "src/compiler/node-aux-data-inl.h"
11 #include "src/compiler/node-properties-inl.h"
12 #include "src/unique.h"
13
14 namespace v8 {
15 namespace internal {
16 namespace compiler {
17
18
19 // TODO(mstarzinger): This is a temporary workaround for non-hydrogen stubs for
20 // which we don't have an interface descriptor yet. Use ReplaceWithICStubCall
21 // once these stub have been made into a HydrogenCodeStub.
22 template <typename T>
23 static CodeStubInterfaceDescriptor* GetInterfaceDescriptor(Isolate* isolate,
24 T* stub) {
25 CodeStub::Major key = static_cast<CodeStub*>(stub)->MajorKey();
26 CodeStubInterfaceDescriptor* d = isolate->code_stub_interface_descriptor(key);
27 stub->InitializeInterfaceDescriptor(isolate, d);
28 return d;
29 }
30
31
32 JSGenericLowering::JSGenericLowering(CompilationInfo* info, JSGraph* jsgraph,
33 MachineOperatorBuilder* machine,
34 SourcePositionTable* source_positions)
35 : LoweringBuilder(jsgraph->graph(), source_positions),
36 info_(info),
37 jsgraph_(jsgraph),
38 linkage_(new (jsgraph->zone()) Linkage(info)),
39 machine_(machine) {}
40
41
42 void JSGenericLowering::PatchOperator(Node* node, Operator* op) {
43 node->set_op(op);
44 }
45
46
47 void JSGenericLowering::PatchInsertInput(Node* node, int index, Node* input) {
48 node->InsertInput(zone(), index, input);
49 }
50
51
52 Node* JSGenericLowering::SmiConstant(int32_t immediate) {
53 return jsgraph()->SmiConstant(immediate);
54 }
55
56
57 Node* JSGenericLowering::Int32Constant(int immediate) {
58 return jsgraph()->Int32Constant(immediate);
59 }
60
61
62 Node* JSGenericLowering::CodeConstant(Handle<Code> code) {
63 return jsgraph()->HeapConstant(code);
64 }
65
66
67 Node* JSGenericLowering::FunctionConstant(Handle<JSFunction> function) {
68 return jsgraph()->HeapConstant(function);
69 }
70
71
72 Node* JSGenericLowering::ExternalConstant(ExternalReference ref) {
73 return jsgraph()->ExternalConstant(ref);
74 }
75
76
77 void JSGenericLowering::Lower(Node* node) {
78 Node* replacement = NULL;
79 // Dispatch according to the opcode.
80 switch (node->opcode()) {
81 #define DECLARE_CASE(x) \
82 case IrOpcode::k##x: \
83 replacement = Lower##x(node); \
84 break;
85 DECLARE_CASE(Branch)
86 JS_OP_LIST(DECLARE_CASE)
87 #undef DECLARE_CASE
88 default:
89 // Nothing to see.
90 return;
91 }
92
93 // Nothing to do if lowering was done by patching the existing node.
94 if (replacement == node) return;
95
96 // Iterate through uses of the original node and replace uses accordingly.
97 UNIMPLEMENTED();
98 }
99
100
101 #define REPLACE_IC_STUB_CALL(op, StubDeclaration) \
102 Node* JSGenericLowering::Lower##op(Node* node) { \
103 StubDeclaration; \
104 ReplaceWithICStubCall(node, &stub); \
105 return node; \
106 }
107 REPLACE_IC_STUB_CALL(JSBitwiseOr, BinaryOpICStub stub(isolate(), Token::BIT_OR))
108 REPLACE_IC_STUB_CALL(JSBitwiseXor,
109 BinaryOpICStub stub(isolate(), Token::BIT_XOR))
110 REPLACE_IC_STUB_CALL(JSBitwiseAnd,
111 BinaryOpICStub stub(isolate(), Token::BIT_AND))
112 REPLACE_IC_STUB_CALL(JSShiftLeft, BinaryOpICStub stub(isolate(), Token::SHL))
113 REPLACE_IC_STUB_CALL(JSShiftRight, BinaryOpICStub stub(isolate(), Token::SAR))
114 REPLACE_IC_STUB_CALL(JSShiftRightLogical,
115 BinaryOpICStub stub(isolate(), Token::SHR))
116 REPLACE_IC_STUB_CALL(JSAdd, BinaryOpICStub stub(isolate(), Token::ADD))
117 REPLACE_IC_STUB_CALL(JSSubtract, BinaryOpICStub stub(isolate(), Token::SUB))
118 REPLACE_IC_STUB_CALL(JSMultiply, BinaryOpICStub stub(isolate(), Token::MUL))
119 REPLACE_IC_STUB_CALL(JSDivide, BinaryOpICStub stub(isolate(), Token::DIV))
120 REPLACE_IC_STUB_CALL(JSModulus, BinaryOpICStub stub(isolate(), Token::MOD))
121 REPLACE_IC_STUB_CALL(JSToNumber, ToNumberStub stub(isolate()))
122 #undef REPLACE_IC_STUB_CALL
123
124
125 #define REPLACE_COMPARE_IC_CALL(op, token, pure) \
126 Node* JSGenericLowering::Lower##op(Node* node) { \
127 ReplaceWithCompareIC(node, token, pure); \
128 return node; \
129 }
130 REPLACE_COMPARE_IC_CALL(JSEqual, Token::EQ, false)
131 REPLACE_COMPARE_IC_CALL(JSNotEqual, Token::NE, false)
132 REPLACE_COMPARE_IC_CALL(JSStrictEqual, Token::EQ_STRICT, true)
133 REPLACE_COMPARE_IC_CALL(JSStrictNotEqual, Token::NE_STRICT, true)
134 REPLACE_COMPARE_IC_CALL(JSLessThan, Token::LT, false)
135 REPLACE_COMPARE_IC_CALL(JSGreaterThan, Token::GT, false)
136 REPLACE_COMPARE_IC_CALL(JSLessThanOrEqual, Token::LTE, false)
137 REPLACE_COMPARE_IC_CALL(JSGreaterThanOrEqual, Token::GTE, false)
138 #undef REPLACE_COMPARE_IC_CALL
139
140
141 #define REPLACE_RUNTIME_CALL(op, fun) \
142 Node* JSGenericLowering::Lower##op(Node* node) { \
143 ReplaceWithRuntimeCall(node, fun); \
144 return node; \
145 }
146 REPLACE_RUNTIME_CALL(JSTypeOf, Runtime::kTypeof)
147 REPLACE_RUNTIME_CALL(JSCreate, Runtime::kAbort)
148 REPLACE_RUNTIME_CALL(JSCreateFunctionContext, Runtime::kNewFunctionContext)
149 REPLACE_RUNTIME_CALL(JSCreateCatchContext, Runtime::kPushCatchContext)
150 REPLACE_RUNTIME_CALL(JSCreateWithContext, Runtime::kPushWithContext)
151 REPLACE_RUNTIME_CALL(JSCreateBlockContext, Runtime::kPushBlockContext)
152 REPLACE_RUNTIME_CALL(JSCreateModuleContext, Runtime::kPushModuleContext)
153 REPLACE_RUNTIME_CALL(JSCreateGlobalContext, Runtime::kAbort)
154 #undef REPLACE_RUNTIME
155
156
157 #define REPLACE_UNIMPLEMENTED(op) \
158 Node* JSGenericLowering::Lower##op(Node* node) { \
159 UNIMPLEMENTED(); \
160 return node; \
161 }
162 REPLACE_UNIMPLEMENTED(JSToString)
163 REPLACE_UNIMPLEMENTED(JSToName)
164 REPLACE_UNIMPLEMENTED(JSYield)
165 REPLACE_UNIMPLEMENTED(JSDebugger)
166 #undef REPLACE_UNIMPLEMENTED
167
168
169 void JSGenericLowering::ReplaceWithCompareIC(Node* node, Token::Value token,
170 bool pure) {
171 BinaryOpICStub stub(isolate(), Token::ADD); // TODO(mstarzinger): Hack.
172 CodeStubInterfaceDescriptor* d = stub.GetInterfaceDescriptor();
173 CallDescriptor* desc_compare = linkage()->GetStubCallDescriptor(d);
174 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), token);
175 Node* compare;
176 if (pure) {
177 // A pure (strict) comparison doesn't have an effect or control.
178 // But for the graph, we need to add these inputs.
179 compare = graph()->NewNode(common()->Call(desc_compare), CodeConstant(ic),
180 NodeProperties::GetValueInput(node, 0),
181 NodeProperties::GetValueInput(node, 1),
182 NodeProperties::GetContextInput(node),
183 graph()->start(), graph()->start());
184 } else {
185 compare = graph()->NewNode(common()->Call(desc_compare), CodeConstant(ic),
186 NodeProperties::GetValueInput(node, 0),
187 NodeProperties::GetValueInput(node, 1),
188 NodeProperties::GetContextInput(node),
189 NodeProperties::GetEffectInput(node),
190 NodeProperties::GetControlInput(node));
191 }
192 node->ReplaceInput(0, compare);
193 node->ReplaceInput(1, SmiConstant(token));
194 ReplaceWithRuntimeCall(node, Runtime::kBooleanize);
195 }
196
197
198 void JSGenericLowering::ReplaceWithICStubCall(Node* node,
199 HydrogenCodeStub* stub) {
200 CodeStubInterfaceDescriptor* d = stub->GetInterfaceDescriptor();
201 CallDescriptor* desc = linkage()->GetStubCallDescriptor(d);
202 Node* stub_code = CodeConstant(stub->GetCode());
203 PatchInsertInput(node, 0, stub_code);
204 PatchOperator(node, common()->Call(desc));
205 }
206
207
208 void JSGenericLowering::ReplaceWithBuiltinCall(Node* node,
209 Builtins::JavaScript id,
210 int nargs) {
211 CallFunctionStub stub(isolate(), nargs - 1, NO_CALL_FUNCTION_FLAGS);
212 CodeStubInterfaceDescriptor* d = GetInterfaceDescriptor(isolate(), &stub);
213 CallDescriptor* desc = linkage()->GetStubCallDescriptor(d, nargs);
214 // TODO(mstarzinger): Accessing the builtins object this way prevents sharing
215 // of code across native contexts. Fix this by loading from given context.
216 Handle<JSFunction> function(
217 JSFunction::cast(info()->context()->builtins()->javascript_builtin(id)));
218 Node* stub_code = CodeConstant(stub.GetCode());
219 Node* function_node = FunctionConstant(function);
220 PatchInsertInput(node, 0, stub_code);
221 PatchInsertInput(node, 1, function_node);
222 PatchOperator(node, common()->Call(desc));
223 }
224
225
226 void JSGenericLowering::ReplaceWithRuntimeCall(Node* node,
227 Runtime::FunctionId f,
228 int nargs_override) {
229 Operator::Property props = node->op()->properties();
230 const Runtime::Function* fun = Runtime::FunctionForId(f);
231 int nargs = (nargs_override < 0) ? fun->nargs : nargs_override;
232 CallDescriptor::DeoptimizationSupport deopt =
233 NodeProperties::CanLazilyDeoptimize(node)
234 ? CallDescriptor::kCanDeoptimize
235 : CallDescriptor::kCannotDeoptimize;
236 CallDescriptor* desc =
237 linkage()->GetRuntimeCallDescriptor(f, nargs, props, deopt);
238 Node* ref = ExternalConstant(ExternalReference(f, isolate()));
239 Node* arity = Int32Constant(nargs);
240 if (!centrystub_constant_.is_set()) {
241 centrystub_constant_.set(CodeConstant(CEntryStub(isolate(), 1).GetCode()));
242 }
243 PatchInsertInput(node, 0, centrystub_constant_.get());
244 PatchInsertInput(node, nargs + 1, ref);
245 PatchInsertInput(node, nargs + 2, arity);
246 PatchOperator(node, common()->Call(desc));
247 }
248
249
250 Node* JSGenericLowering::LowerBranch(Node* node) {
251 Node* test = graph()->NewNode(machine()->WordEqual(), node->InputAt(0),
252 jsgraph()->TrueConstant());
253 node->ReplaceInput(0, test);
254 return node;
255 }
256
257
258 Node* JSGenericLowering::LowerJSUnaryNot(Node* node) {
259 ToBooleanStub stub(isolate());
260 CodeStubInterfaceDescriptor* d = stub.GetInterfaceDescriptor();
261 CallDescriptor* desc = linkage()->GetStubCallDescriptor(d);
262 Node* to_bool =
263 graph()->NewNode(common()->Call(desc), CodeConstant(stub.GetCode()),
264 NodeProperties::GetValueInput(node, 0),
265 NodeProperties::GetContextInput(node),
266 NodeProperties::GetEffectInput(node),
267 NodeProperties::GetControlInput(node));
268 node->ReplaceInput(0, to_bool);
269 PatchInsertInput(node, 1, SmiConstant(Token::EQ));
270 ReplaceWithRuntimeCall(node, Runtime::kBooleanize);
271 return node;
272 }
273
274
275 Node* JSGenericLowering::LowerJSToBoolean(Node* node) {
276 ToBooleanStub stub(isolate());
277 CodeStubInterfaceDescriptor* d = stub.GetInterfaceDescriptor();
278 CallDescriptor* desc = linkage()->GetStubCallDescriptor(d);
279 Node* to_bool =
280 graph()->NewNode(common()->Call(desc), CodeConstant(stub.GetCode()),
281 NodeProperties::GetValueInput(node, 0),
282 NodeProperties::GetContextInput(node),
283 NodeProperties::GetEffectInput(node),
284 NodeProperties::GetControlInput(node));
285 node->ReplaceInput(0, to_bool);
286 PatchInsertInput(node, 1, SmiConstant(Token::NE));
287 ReplaceWithRuntimeCall(node, Runtime::kBooleanize);
288 return node;
289 }
290
291
292 Node* JSGenericLowering::LowerJSToObject(Node* node) {
293 ReplaceWithBuiltinCall(node, Builtins::TO_OBJECT, 1);
294 return node;
295 }
296
297
298 Node* JSGenericLowering::LowerJSLoadProperty(Node* node) {
299 if (FLAG_compiled_keyed_generic_loads) {
300 KeyedLoadGenericStub stub(isolate());
301 ReplaceWithICStubCall(node, &stub);
302 } else {
303 ReplaceWithRuntimeCall(node, Runtime::kKeyedGetProperty);
304 }
305 return node;
306 }
307
308
309 Node* JSGenericLowering::LowerJSLoadNamed(Node* node) {
310 Node* key =
311 jsgraph()->HeapConstant(OpParameter<PrintableUnique<Name> >(node));
312 PatchInsertInput(node, 1, key);
313 // TODO(mstarzinger): We cannot yet use KeyedLoadGenericElementStub here,
314 // because named interceptors would not fire correctly yet.
315 ReplaceWithRuntimeCall(node, Runtime::kGetProperty);
316 return node;
317 }
318
319
320 Node* JSGenericLowering::LowerJSStoreProperty(Node* node) {
321 // TODO(mstarzinger): The strict_mode needs to be carried along in the
322 // operator so that graphs are fully compositional for inlining.
323 StrictMode strict_mode = info()->strict_mode();
324 PatchInsertInput(node, 3, SmiConstant(strict_mode));
325 ReplaceWithRuntimeCall(node, Runtime::kSetProperty, 4);
326 return node;
327 }
328
329
330 Node* JSGenericLowering::LowerJSStoreNamed(Node* node) {
331 // TODO(mstarzinger): The strict_mode needs to be carried along in the
332 // operator so that graphs are fully compositional for inlining.
333 StrictMode strict_mode = info()->strict_mode();
334 Node* key =
335 jsgraph()->HeapConstant(OpParameter<PrintableUnique<Name> >(node));
336 PatchInsertInput(node, 1, key);
337 PatchInsertInput(node, 3, SmiConstant(strict_mode));
338 ReplaceWithRuntimeCall(node, Runtime::kSetProperty, 4);
339 return node;
340 }
341
342
343 Node* JSGenericLowering::LowerJSDeleteProperty(Node* node) {
344 StrictMode strict_mode = OpParameter<StrictMode>(node);
345 PatchInsertInput(node, 2, SmiConstant(strict_mode));
346 ReplaceWithBuiltinCall(node, Builtins::DELETE, 3);
347 return node;
348 }
349
350
351 Node* JSGenericLowering::LowerJSHasProperty(Node* node) {
352 ReplaceWithBuiltinCall(node, Builtins::IN, 2);
353 return node;
354 }
355
356
357 Node* JSGenericLowering::LowerJSInstanceOf(Node* node) {
358 InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>(
359 InstanceofStub::kReturnTrueFalseObject |
360 InstanceofStub::kArgsInRegisters);
361 InstanceofStub stub(isolate(), flags);
362 CodeStubInterfaceDescriptor* d = GetInterfaceDescriptor(isolate(), &stub);
363 CallDescriptor* desc = linkage()->GetStubCallDescriptor(d, 0);
364 Node* stub_code = CodeConstant(stub.GetCode());
365 PatchInsertInput(node, 0, stub_code);
366 PatchOperator(node, common()->Call(desc));
367 return node;
368 }
369
370
371 Node* JSGenericLowering::LowerJSLoadContext(Node* node) {
372 ContextAccess access = OpParameter<ContextAccess>(node);
373 PatchInsertInput(node, 1, SmiConstant(access.depth()));
374 PatchInsertInput(node, 2, SmiConstant(access.index()));
375 ReplaceWithRuntimeCall(node, Runtime::kLoadContextRelative, 3);
376 return node;
377 }
378
379
380 Node* JSGenericLowering::LowerJSStoreContext(Node* node) {
381 ContextAccess access = OpParameter<ContextAccess>(node);
382 PatchInsertInput(node, 1, SmiConstant(access.depth()));
383 PatchInsertInput(node, 2, SmiConstant(access.index()));
384 ReplaceWithRuntimeCall(node, Runtime::kStoreContextRelative, 4);
385 return node;
386 }
387
388
389 Node* JSGenericLowering::LowerJSCallConstruct(Node* node) {
390 int arity = OpParameter<int>(node);
391 CallConstructStub stub(isolate(), NO_CALL_CONSTRUCTOR_FLAGS);
392 CodeStubInterfaceDescriptor* d = GetInterfaceDescriptor(isolate(), &stub);
393 CallDescriptor* desc = linkage()->GetStubCallDescriptor(d, arity);
394 Node* stub_code = CodeConstant(stub.GetCode());
395 Node* construct = NodeProperties::GetValueInput(node, 0);
396 PatchInsertInput(node, 0, stub_code);
397 PatchInsertInput(node, 1, Int32Constant(arity - 1));
398 PatchInsertInput(node, 2, construct);
399 PatchInsertInput(node, 3, jsgraph()->UndefinedConstant());
400 PatchOperator(node, common()->Call(desc));
401 return node;
402 }
403
404
405 Node* JSGenericLowering::LowerJSCallFunction(Node* node) {
406 CallParameters p = OpParameter<CallParameters>(node);
407 CallFunctionStub stub(isolate(), p.arity - 2, p.flags);
408 CodeStubInterfaceDescriptor* d = GetInterfaceDescriptor(isolate(), &stub);
409 CallDescriptor* desc = linkage()->GetStubCallDescriptor(d, p.arity - 1);
410 Node* stub_code = CodeConstant(stub.GetCode());
411 PatchInsertInput(node, 0, stub_code);
412 PatchOperator(node, common()->Call(desc));
413 return node;
414 }
415
416
417 Node* JSGenericLowering::LowerJSCallRuntime(Node* node) {
418 Runtime::FunctionId function = OpParameter<Runtime::FunctionId>(node);
419 int arity = NodeProperties::GetValueInputCount(node);
420 ReplaceWithRuntimeCall(node, function, arity);
421 return node;
422 }
423 }
424 }
425 } // namespace v8::internal::compiler
OLDNEW
« no previous file with comments | « src/compiler/js-generic-lowering.h ('k') | src/compiler/js-graph.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698