blob: f4b0d7b603d4ed3ac1bac47e7a1e890d9606c2f2 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// Copyright 2015 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/compiler/js-call-reducer.h"
6
7#include "src/compiler/js-graph.h"
8#include "src/compiler/node-matchers.h"
9#include "src/objects-inl.h"
10#include "src/type-feedback-vector-inl.h"
11
12namespace v8 {
13namespace internal {
14namespace compiler {
15
16namespace {
17
18VectorSlotPair CallCountFeedback(VectorSlotPair p) {
19 // Extract call count from {p}.
20 if (!p.IsValid()) return VectorSlotPair();
21 CallICNexus n(p.vector(), p.slot());
22 int const call_count = n.ExtractCallCount();
23 if (call_count <= 0) return VectorSlotPair();
24
25 // Create megamorphic CallIC feedback with the given {call_count}.
26 StaticFeedbackVectorSpec spec;
27 FeedbackVectorSlot slot = spec.AddCallICSlot();
28 Handle<TypeFeedbackMetadata> metadata =
29 TypeFeedbackMetadata::New(n.GetIsolate(), &spec);
30 Handle<TypeFeedbackVector> vector =
31 TypeFeedbackVector::New(n.GetIsolate(), metadata);
32 CallICNexus nexus(vector, slot);
33 nexus.ConfigureMegamorphic(call_count);
34 return VectorSlotPair(vector, slot);
35}
36
37} // namespace
38
39
40Reduction JSCallReducer::Reduce(Node* node) {
41 switch (node->opcode()) {
42 case IrOpcode::kJSCallConstruct:
43 return ReduceJSCallConstruct(node);
44 case IrOpcode::kJSCallFunction:
45 return ReduceJSCallFunction(node);
46 default:
47 break;
48 }
49 return NoChange();
50}
51
52
53// ES6 section 22.1.1 The Array Constructor
54Reduction JSCallReducer::ReduceArrayConstructor(Node* node) {
55 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode());
56 Node* target = NodeProperties::GetValueInput(node, 0);
57 CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
58
59 // Check if we have an allocation site from the CallIC.
60 Handle<AllocationSite> site;
61 if (p.feedback().IsValid()) {
62 CallICNexus nexus(p.feedback().vector(), p.feedback().slot());
63 Handle<Object> feedback(nexus.GetFeedback(), isolate());
64 if (feedback->IsAllocationSite()) {
65 site = Handle<AllocationSite>::cast(feedback);
66 }
67 }
68
69 // Turn the {node} into a {JSCreateArray} call.
70 DCHECK_LE(2u, p.arity());
71 size_t const arity = p.arity() - 2;
72 NodeProperties::ReplaceValueInput(node, target, 0);
73 NodeProperties::ReplaceValueInput(node, target, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000074 // TODO(bmeurer): We might need to propagate the tail call mode to
75 // the JSCreateArray operator, because an Array call in tail call
76 // position must always properly consume the parent stack frame.
77 NodeProperties::ChangeOp(node, javascript()->CreateArray(arity, site));
78 return Changed(node);
79}
80
81
82// ES6 section 20.1.1 The Number Constructor
83Reduction JSCallReducer::ReduceNumberConstructor(Node* node) {
84 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode());
85 CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
86
87 // Turn the {node} into a {JSToNumber} call.
88 DCHECK_LE(2u, p.arity());
89 Node* value = (p.arity() == 2) ? jsgraph()->ZeroConstant()
90 : NodeProperties::GetValueInput(node, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000091 NodeProperties::ReplaceValueInputs(node, value);
92 NodeProperties::ChangeOp(node, javascript()->ToNumber());
93 return Changed(node);
94}
95
96
97// ES6 section 19.2.3.1 Function.prototype.apply ( thisArg, argArray )
98Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) {
99 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode());
100 Node* target = NodeProperties::GetValueInput(node, 0);
101 CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
102 Handle<JSFunction> apply =
103 Handle<JSFunction>::cast(HeapObjectMatcher(target).Value());
104 size_t arity = p.arity();
105 DCHECK_LE(2u, arity);
106 ConvertReceiverMode convert_mode = ConvertReceiverMode::kAny;
107 if (arity == 2) {
108 // Neither thisArg nor argArray was provided.
109 convert_mode = ConvertReceiverMode::kNullOrUndefined;
110 node->ReplaceInput(0, node->InputAt(1));
111 node->ReplaceInput(1, jsgraph()->UndefinedConstant());
112 } else if (arity == 3) {
113 // The argArray was not provided, just remove the {target}.
114 node->RemoveInput(0);
115 --arity;
116 } else if (arity == 4) {
117 // Check if argArray is an arguments object, and {node} is the only value
118 // user of argArray (except for value uses in frame states).
119 Node* arg_array = NodeProperties::GetValueInput(node, 3);
120 if (arg_array->opcode() != IrOpcode::kJSCreateArguments) return NoChange();
121 for (Edge edge : arg_array->use_edges()) {
122 if (edge.from()->opcode() == IrOpcode::kStateValues) continue;
123 if (!NodeProperties::IsValueEdge(edge)) continue;
124 if (edge.from() == node) continue;
125 return NoChange();
126 }
127 // Get to the actual frame state from which to extract the arguments;
128 // we can only optimize this in case the {node} was already inlined into
129 // some other function (and same for the {arg_array}).
Ben Murdoch097c5b22016-05-18 11:27:45 +0100130 CreateArgumentsType type = CreateArgumentsTypeOf(arg_array->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000131 Node* frame_state = NodeProperties::GetFrameStateInput(arg_array, 0);
132 Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
133 if (outer_state->opcode() != IrOpcode::kFrameState) return NoChange();
134 FrameStateInfo outer_info = OpParameter<FrameStateInfo>(outer_state);
135 if (outer_info.type() == FrameStateType::kArgumentsAdaptor) {
136 // Need to take the parameters from the arguments adaptor.
137 frame_state = outer_state;
138 }
139 FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100140 int start_index = 0;
141 if (type == CreateArgumentsType::kMappedArguments) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000142 // Mapped arguments (sloppy mode) cannot be handled if they are aliased.
143 Handle<SharedFunctionInfo> shared;
144 if (!state_info.shared_info().ToHandle(&shared)) return NoChange();
145 if (shared->internal_formal_parameter_count() != 0) return NoChange();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100146 } else if (type == CreateArgumentsType::kRestParameter) {
147 Handle<SharedFunctionInfo> shared;
148 if (!state_info.shared_info().ToHandle(&shared)) return NoChange();
149 start_index = shared->internal_formal_parameter_count();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000150 }
151 // Remove the argArray input from the {node}.
152 node->RemoveInput(static_cast<int>(--arity));
153 // Add the actual parameters to the {node}, skipping the receiver.
154 Node* const parameters = frame_state->InputAt(kFrameStateParametersInput);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100155 for (int i = start_index + 1; i < state_info.parameter_count(); ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000156 node->InsertInput(graph()->zone(), static_cast<int>(arity),
157 parameters->InputAt(i));
158 ++arity;
159 }
160 // Drop the {target} from the {node}.
161 node->RemoveInput(0);
162 --arity;
163 } else {
164 return NoChange();
165 }
166 // Change {node} to the new {JSCallFunction} operator.
167 NodeProperties::ChangeOp(
Ben Murdoch097c5b22016-05-18 11:27:45 +0100168 node, javascript()->CallFunction(arity, CallCountFeedback(p.feedback()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000169 convert_mode, p.tail_call_mode()));
170 // Change context of {node} to the Function.prototype.apply context,
171 // to ensure any exception is thrown in the correct context.
172 NodeProperties::ReplaceContextInput(
173 node, jsgraph()->HeapConstant(handle(apply->context(), isolate())));
174 // Try to further reduce the JSCallFunction {node}.
175 Reduction const reduction = ReduceJSCallFunction(node);
176 return reduction.Changed() ? reduction : Changed(node);
177}
178
179
180// ES6 section 19.2.3.3 Function.prototype.call (thisArg, ...args)
181Reduction JSCallReducer::ReduceFunctionPrototypeCall(Node* node) {
182 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode());
183 CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
184 Handle<JSFunction> call = Handle<JSFunction>::cast(
185 HeapObjectMatcher(NodeProperties::GetValueInput(node, 0)).Value());
186 // Change context of {node} to the Function.prototype.call context,
187 // to ensure any exception is thrown in the correct context.
188 NodeProperties::ReplaceContextInput(
189 node, jsgraph()->HeapConstant(handle(call->context(), isolate())));
190 // Remove the target from {node} and use the receiver as target instead, and
191 // the thisArg becomes the new target. If thisArg was not provided, insert
192 // undefined instead.
193 size_t arity = p.arity();
194 DCHECK_LE(2u, arity);
195 ConvertReceiverMode convert_mode;
196 if (arity == 2) {
197 // The thisArg was not provided, use undefined as receiver.
198 convert_mode = ConvertReceiverMode::kNullOrUndefined;
199 node->ReplaceInput(0, node->InputAt(1));
200 node->ReplaceInput(1, jsgraph()->UndefinedConstant());
201 } else {
202 // Just remove the target, which is the first value input.
203 convert_mode = ConvertReceiverMode::kAny;
204 node->RemoveInput(0);
205 --arity;
206 }
207 NodeProperties::ChangeOp(
Ben Murdoch097c5b22016-05-18 11:27:45 +0100208 node, javascript()->CallFunction(arity, CallCountFeedback(p.feedback()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000209 convert_mode, p.tail_call_mode()));
210 // Try to further reduce the JSCallFunction {node}.
211 Reduction const reduction = ReduceJSCallFunction(node);
212 return reduction.Changed() ? reduction : Changed(node);
213}
214
215
216Reduction JSCallReducer::ReduceJSCallFunction(Node* node) {
217 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode());
218 CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
219 Node* target = NodeProperties::GetValueInput(node, 0);
220 Node* context = NodeProperties::GetContextInput(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000221 Node* control = NodeProperties::GetControlInput(node);
222 Node* effect = NodeProperties::GetEffectInput(node);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100223 Node* frame_state = NodeProperties::FindFrameStateBefore(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000224
225 // Try to specialize JSCallFunction {node}s with constant {target}s.
226 HeapObjectMatcher m(target);
227 if (m.HasValue()) {
228 if (m.Value()->IsJSFunction()) {
229 Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value());
230 Handle<SharedFunctionInfo> shared(function->shared(), isolate());
231
232 // Raise a TypeError if the {target} is a "classConstructor".
233 if (IsClassConstructor(shared->kind())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000234 NodeProperties::ReplaceValueInputs(node, target);
235 NodeProperties::ChangeOp(
236 node, javascript()->CallRuntime(
237 Runtime::kThrowConstructorNonCallableError, 1));
238 return Changed(node);
239 }
240
241 // Check for known builtin functions.
242 if (shared->HasBuiltinFunctionId()) {
243 switch (shared->builtin_function_id()) {
244 case kFunctionApply:
245 return ReduceFunctionPrototypeApply(node);
246 case kFunctionCall:
247 return ReduceFunctionPrototypeCall(node);
248 default:
249 break;
250 }
251 }
252
253 // Check for the Array constructor.
254 if (*function == function->native_context()->array_function()) {
255 return ReduceArrayConstructor(node);
256 }
257
258 // Check for the Number constructor.
259 if (*function == function->native_context()->number_function()) {
260 return ReduceNumberConstructor(node);
261 }
262 } else if (m.Value()->IsJSBoundFunction()) {
263 Handle<JSBoundFunction> function =
264 Handle<JSBoundFunction>::cast(m.Value());
265 Handle<JSReceiver> bound_target_function(
266 function->bound_target_function(), isolate());
267 Handle<Object> bound_this(function->bound_this(), isolate());
268 Handle<FixedArray> bound_arguments(function->bound_arguments(),
269 isolate());
270 CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
271 ConvertReceiverMode const convert_mode =
Ben Murdoch61f157c2016-09-16 13:49:30 +0100272 (bound_this->IsNull(isolate()) || bound_this->IsUndefined(isolate()))
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000273 ? ConvertReceiverMode::kNullOrUndefined
274 : ConvertReceiverMode::kNotNullOrUndefined;
275 size_t arity = p.arity();
276 DCHECK_LE(2u, arity);
277 // Patch {node} to use [[BoundTargetFunction]] and [[BoundThis]].
278 NodeProperties::ReplaceValueInput(
279 node, jsgraph()->Constant(bound_target_function), 0);
280 NodeProperties::ReplaceValueInput(node, jsgraph()->Constant(bound_this),
281 1);
282 // Insert the [[BoundArguments]] for {node}.
283 for (int i = 0; i < bound_arguments->length(); ++i) {
284 node->InsertInput(
285 graph()->zone(), i + 2,
286 jsgraph()->Constant(handle(bound_arguments->get(i), isolate())));
287 arity++;
288 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100289 NodeProperties::ChangeOp(node, javascript()->CallFunction(
290 arity, CallCountFeedback(p.feedback()),
291 convert_mode, p.tail_call_mode()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000292 // Try to further reduce the JSCallFunction {node}.
293 Reduction const reduction = ReduceJSCallFunction(node);
294 return reduction.Changed() ? reduction : Changed(node);
295 }
296
297 // Don't mess with other {node}s that have a constant {target}.
298 // TODO(bmeurer): Also support proxies here.
299 return NoChange();
300 }
301
302 // Not much we can do if deoptimization support is disabled.
303 if (!(flags() & kDeoptimizationEnabled)) return NoChange();
304
305 // Extract feedback from the {node} using the CallICNexus.
306 if (!p.feedback().IsValid()) return NoChange();
307 CallICNexus nexus(p.feedback().vector(), p.feedback().slot());
308 Handle<Object> feedback(nexus.GetFeedback(), isolate());
309 if (feedback->IsAllocationSite()) {
310 // Retrieve the Array function from the {node}.
311 Node* array_function;
312 Handle<Context> native_context;
313 if (GetNativeContext(node).ToHandle(&native_context)) {
314 array_function = jsgraph()->HeapConstant(
315 handle(native_context->array_function(), isolate()));
316 } else {
317 Node* native_context = effect = graph()->NewNode(
318 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
319 context, context, effect);
320 array_function = effect = graph()->NewNode(
321 javascript()->LoadContext(0, Context::ARRAY_FUNCTION_INDEX, true),
322 native_context, native_context, effect);
323 }
324
325 // Check that the {target} is still the {array_function}.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100326 Node* check = graph()->NewNode(
327 javascript()->StrictEqual(CompareOperationHints::Any()), target,
328 array_function, context);
329 control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check,
330 frame_state, effect, control);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000331
332 // Turn the {node} into a {JSCreateArray} call.
333 NodeProperties::ReplaceValueInput(node, array_function, 0);
334 NodeProperties::ReplaceEffectInput(node, effect);
335 NodeProperties::ReplaceControlInput(node, control);
336 return ReduceArrayConstructor(node);
337 } else if (feedback->IsWeakCell()) {
338 Handle<WeakCell> cell = Handle<WeakCell>::cast(feedback);
339 if (cell->value()->IsJSFunction()) {
340 Node* target_function =
341 jsgraph()->Constant(handle(cell->value(), isolate()));
342
343 // Check that the {target} is still the {target_function}.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100344 Node* check = graph()->NewNode(
345 javascript()->StrictEqual(CompareOperationHints::Any()), target,
346 target_function, context);
347 control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check,
348 frame_state, effect, control);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000349
350 // Specialize the JSCallFunction node to the {target_function}.
351 NodeProperties::ReplaceValueInput(node, target_function, 0);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100352 NodeProperties::ReplaceEffectInput(node, effect);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000353 NodeProperties::ReplaceControlInput(node, control);
354
355 // Try to further reduce the JSCallFunction {node}.
356 Reduction const reduction = ReduceJSCallFunction(node);
357 return reduction.Changed() ? reduction : Changed(node);
358 }
359 }
360 return NoChange();
361}
362
363
364Reduction JSCallReducer::ReduceJSCallConstruct(Node* node) {
365 DCHECK_EQ(IrOpcode::kJSCallConstruct, node->opcode());
366 CallConstructParameters const& p = CallConstructParametersOf(node->op());
367 DCHECK_LE(2u, p.arity());
368 int const arity = static_cast<int>(p.arity() - 2);
369 Node* target = NodeProperties::GetValueInput(node, 0);
370 Node* new_target = NodeProperties::GetValueInput(node, arity + 1);
371 Node* context = NodeProperties::GetContextInput(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000372 Node* effect = NodeProperties::GetEffectInput(node);
373 Node* control = NodeProperties::GetControlInput(node);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100374 Node* frame_state = NodeProperties::FindFrameStateBefore(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000375
376 // Try to specialize JSCallConstruct {node}s with constant {target}s.
377 HeapObjectMatcher m(target);
378 if (m.HasValue()) {
379 if (m.Value()->IsJSFunction()) {
380 Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value());
381
382 // Raise a TypeError if the {target} is not a constructor.
383 if (!function->IsConstructor()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000384 NodeProperties::ReplaceValueInputs(node, target);
385 NodeProperties::ChangeOp(
Ben Murdoch097c5b22016-05-18 11:27:45 +0100386 node, javascript()->CallRuntime(Runtime::kThrowCalledNonCallable));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000387 return Changed(node);
388 }
389
390 // Check for the ArrayConstructor.
391 if (*function == function->native_context()->array_function()) {
392 // Check if we have an allocation site.
393 Handle<AllocationSite> site;
394 if (p.feedback().IsValid()) {
395 Handle<Object> feedback(
396 p.feedback().vector()->Get(p.feedback().slot()), isolate());
397 if (feedback->IsAllocationSite()) {
398 site = Handle<AllocationSite>::cast(feedback);
399 }
400 }
401
402 // Turn the {node} into a {JSCreateArray} call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000403 for (int i = arity; i > 0; --i) {
404 NodeProperties::ReplaceValueInput(
405 node, NodeProperties::GetValueInput(node, i), i + 1);
406 }
407 NodeProperties::ReplaceValueInput(node, new_target, 1);
408 NodeProperties::ChangeOp(node, javascript()->CreateArray(arity, site));
409 return Changed(node);
410 }
411 }
412
413 // Don't mess with other {node}s that have a constant {target}.
414 // TODO(bmeurer): Also support optimizing bound functions and proxies here.
415 return NoChange();
416 }
417
418 // Not much we can do if deoptimization support is disabled.
419 if (!(flags() & kDeoptimizationEnabled)) return NoChange();
420
421 // TODO(mvstanton): Use ConstructICNexus here, once available.
422 Handle<Object> feedback;
423 if (!p.feedback().IsValid()) return NoChange();
424 feedback = handle(p.feedback().vector()->Get(p.feedback().slot()), isolate());
425 if (feedback->IsAllocationSite()) {
426 // The feedback is an AllocationSite, which means we have called the
427 // Array function and collected transition (and pretenuring) feedback
428 // for the resulting arrays. This has to be kept in sync with the
429 // implementation of the CallConstructStub.
430 Handle<AllocationSite> site = Handle<AllocationSite>::cast(feedback);
431
432 // Retrieve the Array function from the {node}.
433 Node* array_function;
434 Handle<Context> native_context;
435 if (GetNativeContext(node).ToHandle(&native_context)) {
436 array_function = jsgraph()->HeapConstant(
437 handle(native_context->array_function(), isolate()));
438 } else {
439 Node* native_context = effect = graph()->NewNode(
440 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
441 context, context, effect);
442 array_function = effect = graph()->NewNode(
443 javascript()->LoadContext(0, Context::ARRAY_FUNCTION_INDEX, true),
444 native_context, native_context, effect);
445 }
446
447 // Check that the {target} is still the {array_function}.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100448 Node* check = graph()->NewNode(
449 javascript()->StrictEqual(CompareOperationHints::Any()), target,
450 array_function, context);
451 control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check,
452 frame_state, effect, control);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000453
454 // Turn the {node} into a {JSCreateArray} call.
455 NodeProperties::ReplaceEffectInput(node, effect);
456 NodeProperties::ReplaceControlInput(node, control);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000457 for (int i = arity; i > 0; --i) {
458 NodeProperties::ReplaceValueInput(
459 node, NodeProperties::GetValueInput(node, i), i + 1);
460 }
461 NodeProperties::ReplaceValueInput(node, new_target, 1);
462 NodeProperties::ChangeOp(node, javascript()->CreateArray(arity, site));
463 return Changed(node);
464 } else if (feedback->IsWeakCell()) {
465 Handle<WeakCell> cell = Handle<WeakCell>::cast(feedback);
466 if (cell->value()->IsJSFunction()) {
467 Node* target_function =
468 jsgraph()->Constant(handle(cell->value(), isolate()));
469
470 // Check that the {target} is still the {target_function}.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100471 Node* check = graph()->NewNode(
472 javascript()->StrictEqual(CompareOperationHints::Any()), target,
473 target_function, context);
474 control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check,
475 frame_state, effect, control);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000476
477 // Specialize the JSCallConstruct node to the {target_function}.
478 NodeProperties::ReplaceValueInput(node, target_function, 0);
479 NodeProperties::ReplaceEffectInput(node, effect);
480 NodeProperties::ReplaceControlInput(node, control);
481 if (target == new_target) {
482 NodeProperties::ReplaceValueInput(node, target_function, arity + 1);
483 }
484
485 // Try to further reduce the JSCallConstruct {node}.
486 Reduction const reduction = ReduceJSCallConstruct(node);
487 return reduction.Changed() ? reduction : Changed(node);
488 }
489 }
490
491 return NoChange();
492}
493
494
495MaybeHandle<Context> JSCallReducer::GetNativeContext(Node* node) {
496 Node* const context = NodeProperties::GetContextInput(node);
497 return NodeProperties::GetSpecializationNativeContext(context,
498 native_context());
499}
500
501
502Graph* JSCallReducer::graph() const { return jsgraph()->graph(); }
503
504
505Isolate* JSCallReducer::isolate() const { return jsgraph()->isolate(); }
506
507
508CommonOperatorBuilder* JSCallReducer::common() const {
509 return jsgraph()->common();
510}
511
512
513JSOperatorBuilder* JSCallReducer::javascript() const {
514 return jsgraph()->javascript();
515}
516
517} // namespace compiler
518} // namespace internal
519} // namespace v8