| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // 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 | 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/compiler/js-call-reducer.h" | 5 #include "src/compiler/js-call-reducer.h" |
| 6 | 6 |
| 7 #include "src/compiler/js-graph.h" | 7 #include "src/compiler/js-graph.h" |
| 8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
| 9 #include "src/compiler/simplified-operator.h" | 9 #include "src/compiler/simplified-operator.h" |
| 10 #include "src/objects-inl.h" | 10 #include "src/objects-inl.h" |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 // Try to further reduce the JSCallFunction {node}. | 187 // Try to further reduce the JSCallFunction {node}. |
| 188 Reduction const reduction = ReduceJSCallFunction(node); | 188 Reduction const reduction = ReduceJSCallFunction(node); |
| 189 return reduction.Changed() ? reduction : Changed(node); | 189 return reduction.Changed() ? reduction : Changed(node); |
| 190 } | 190 } |
| 191 | 191 |
| 192 | 192 |
| 193 Reduction JSCallReducer::ReduceJSCallFunction(Node* node) { | 193 Reduction JSCallReducer::ReduceJSCallFunction(Node* node) { |
| 194 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); | 194 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); |
| 195 CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); | 195 CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); |
| 196 Node* target = NodeProperties::GetValueInput(node, 0); | 196 Node* target = NodeProperties::GetValueInput(node, 0); |
| 197 Node* context = NodeProperties::GetContextInput(node); | |
| 198 Node* control = NodeProperties::GetControlInput(node); | 197 Node* control = NodeProperties::GetControlInput(node); |
| 199 Node* effect = NodeProperties::GetEffectInput(node); | 198 Node* effect = NodeProperties::GetEffectInput(node); |
| 200 | 199 |
| 201 // Try to specialize JSCallFunction {node}s with constant {target}s. | 200 // Try to specialize JSCallFunction {node}s with constant {target}s. |
| 202 HeapObjectMatcher m(target); | 201 HeapObjectMatcher m(target); |
| 203 if (m.HasValue()) { | 202 if (m.HasValue()) { |
| 204 if (m.Value()->IsJSFunction()) { | 203 if (m.Value()->IsJSFunction()) { |
| 205 Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value()); | 204 Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value()); |
| 206 Handle<SharedFunctionInfo> shared(function->shared(), isolate()); | 205 Handle<SharedFunctionInfo> shared(function->shared(), isolate()); |
| 207 | 206 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 // TODO(bmeurer): This should be on the AdvancedReducer somehow. | 290 // TODO(bmeurer): This should be on the AdvancedReducer somehow. |
| 292 NodeProperties::MergeControlToEnd(graph(), common(), deoptimize); | 291 NodeProperties::MergeControlToEnd(graph(), common(), deoptimize); |
| 293 Revisit(graph()->end()); | 292 Revisit(graph()->end()); |
| 294 node->TrimInputCount(0); | 293 node->TrimInputCount(0); |
| 295 NodeProperties::ChangeOp(node, common()->Dead()); | 294 NodeProperties::ChangeOp(node, common()->Dead()); |
| 296 return Changed(node); | 295 return Changed(node); |
| 297 } | 296 } |
| 298 Handle<Object> feedback(nexus.GetFeedback(), isolate()); | 297 Handle<Object> feedback(nexus.GetFeedback(), isolate()); |
| 299 if (feedback->IsAllocationSite()) { | 298 if (feedback->IsAllocationSite()) { |
| 300 // Retrieve the Array function from the {node}. | 299 // Retrieve the Array function from the {node}. |
| 301 Node* array_function; | 300 Node* array_function = jsgraph()->HeapConstant( |
| 302 Handle<Context> native_context; | 301 handle(native_context()->array_function(), isolate())); |
| 303 if (GetNativeContext(node).ToHandle(&native_context)) { | |
| 304 array_function = jsgraph()->HeapConstant( | |
| 305 handle(native_context->array_function(), isolate())); | |
| 306 } else { | |
| 307 Node* native_context = effect = graph()->NewNode( | |
| 308 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true), | |
| 309 context, context, effect); | |
| 310 array_function = effect = graph()->NewNode( | |
| 311 javascript()->LoadContext(0, Context::ARRAY_FUNCTION_INDEX, true), | |
| 312 native_context, native_context, effect); | |
| 313 } | |
| 314 | 302 |
| 315 // Check that the {target} is still the {array_function}. | 303 // Check that the {target} is still the {array_function}. |
| 316 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target, | 304 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target, |
| 317 array_function); | 305 array_function); |
| 318 effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control); | 306 effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control); |
| 319 | 307 |
| 320 // Turn the {node} into a {JSCreateArray} call. | 308 // Turn the {node} into a {JSCreateArray} call. |
| 321 NodeProperties::ReplaceValueInput(node, array_function, 0); | 309 NodeProperties::ReplaceValueInput(node, array_function, 0); |
| 322 NodeProperties::ReplaceEffectInput(node, effect); | 310 NodeProperties::ReplaceEffectInput(node, effect); |
| 323 return ReduceArrayConstructor(node); | 311 return ReduceArrayConstructor(node); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 346 } | 334 } |
| 347 | 335 |
| 348 | 336 |
| 349 Reduction JSCallReducer::ReduceJSCallConstruct(Node* node) { | 337 Reduction JSCallReducer::ReduceJSCallConstruct(Node* node) { |
| 350 DCHECK_EQ(IrOpcode::kJSCallConstruct, node->opcode()); | 338 DCHECK_EQ(IrOpcode::kJSCallConstruct, node->opcode()); |
| 351 CallConstructParameters const& p = CallConstructParametersOf(node->op()); | 339 CallConstructParameters const& p = CallConstructParametersOf(node->op()); |
| 352 DCHECK_LE(2u, p.arity()); | 340 DCHECK_LE(2u, p.arity()); |
| 353 int const arity = static_cast<int>(p.arity() - 2); | 341 int const arity = static_cast<int>(p.arity() - 2); |
| 354 Node* target = NodeProperties::GetValueInput(node, 0); | 342 Node* target = NodeProperties::GetValueInput(node, 0); |
| 355 Node* new_target = NodeProperties::GetValueInput(node, arity + 1); | 343 Node* new_target = NodeProperties::GetValueInput(node, arity + 1); |
| 356 Node* context = NodeProperties::GetContextInput(node); | |
| 357 Node* effect = NodeProperties::GetEffectInput(node); | 344 Node* effect = NodeProperties::GetEffectInput(node); |
| 358 Node* control = NodeProperties::GetControlInput(node); | 345 Node* control = NodeProperties::GetControlInput(node); |
| 359 | 346 |
| 360 // Try to specialize JSCallConstruct {node}s with constant {target}s. | 347 // Try to specialize JSCallConstruct {node}s with constant {target}s. |
| 361 HeapObjectMatcher m(target); | 348 HeapObjectMatcher m(target); |
| 362 if (m.HasValue()) { | 349 if (m.HasValue()) { |
| 363 if (m.Value()->IsJSFunction()) { | 350 if (m.Value()->IsJSFunction()) { |
| 364 Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value()); | 351 Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value()); |
| 365 | 352 |
| 366 // Raise a TypeError if the {target} is not a constructor. | 353 // Raise a TypeError if the {target} is not a constructor. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 406 CallICNexus nexus(p.feedback().vector(), p.feedback().slot()); | 393 CallICNexus nexus(p.feedback().vector(), p.feedback().slot()); |
| 407 Handle<Object> feedback(nexus.GetFeedback(), isolate()); | 394 Handle<Object> feedback(nexus.GetFeedback(), isolate()); |
| 408 if (feedback->IsAllocationSite()) { | 395 if (feedback->IsAllocationSite()) { |
| 409 // The feedback is an AllocationSite, which means we have called the | 396 // The feedback is an AllocationSite, which means we have called the |
| 410 // Array function and collected transition (and pretenuring) feedback | 397 // Array function and collected transition (and pretenuring) feedback |
| 411 // for the resulting arrays. This has to be kept in sync with the | 398 // for the resulting arrays. This has to be kept in sync with the |
| 412 // implementation of the CallConstructStub. | 399 // implementation of the CallConstructStub. |
| 413 Handle<AllocationSite> site = Handle<AllocationSite>::cast(feedback); | 400 Handle<AllocationSite> site = Handle<AllocationSite>::cast(feedback); |
| 414 | 401 |
| 415 // Retrieve the Array function from the {node}. | 402 // Retrieve the Array function from the {node}. |
| 416 Node* array_function; | 403 Node* array_function = jsgraph()->HeapConstant( |
| 417 Handle<Context> native_context; | 404 handle(native_context()->array_function(), isolate())); |
| 418 if (GetNativeContext(node).ToHandle(&native_context)) { | |
| 419 array_function = jsgraph()->HeapConstant( | |
| 420 handle(native_context->array_function(), isolate())); | |
| 421 } else { | |
| 422 Node* native_context = effect = graph()->NewNode( | |
| 423 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true), | |
| 424 context, context, effect); | |
| 425 array_function = effect = graph()->NewNode( | |
| 426 javascript()->LoadContext(0, Context::ARRAY_FUNCTION_INDEX, true), | |
| 427 native_context, native_context, effect); | |
| 428 } | |
| 429 | 405 |
| 430 // Check that the {target} is still the {array_function}. | 406 // Check that the {target} is still the {array_function}. |
| 431 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target, | 407 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target, |
| 432 array_function); | 408 array_function); |
| 433 effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control); | 409 effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control); |
| 434 | 410 |
| 435 // Turn the {node} into a {JSCreateArray} call. | 411 // Turn the {node} into a {JSCreateArray} call. |
| 436 NodeProperties::ReplaceEffectInput(node, effect); | 412 NodeProperties::ReplaceEffectInput(node, effect); |
| 437 for (int i = arity; i > 0; --i) { | 413 for (int i = arity; i > 0; --i) { |
| 438 NodeProperties::ReplaceValueInput( | 414 NodeProperties::ReplaceValueInput( |
| (...skipping 23 matching lines...) Expand all Loading... |
| 462 | 438 |
| 463 // Try to further reduce the JSCallConstruct {node}. | 439 // Try to further reduce the JSCallConstruct {node}. |
| 464 Reduction const reduction = ReduceJSCallConstruct(node); | 440 Reduction const reduction = ReduceJSCallConstruct(node); |
| 465 return reduction.Changed() ? reduction : Changed(node); | 441 return reduction.Changed() ? reduction : Changed(node); |
| 466 } | 442 } |
| 467 } | 443 } |
| 468 | 444 |
| 469 return NoChange(); | 445 return NoChange(); |
| 470 } | 446 } |
| 471 | 447 |
| 472 | |
| 473 MaybeHandle<Context> JSCallReducer::GetNativeContext(Node* node) { | |
| 474 Node* const context = NodeProperties::GetContextInput(node); | |
| 475 return NodeProperties::GetSpecializationNativeContext(context, | |
| 476 native_context()); | |
| 477 } | |
| 478 | |
| 479 | |
| 480 Graph* JSCallReducer::graph() const { return jsgraph()->graph(); } | 448 Graph* JSCallReducer::graph() const { return jsgraph()->graph(); } |
| 481 | 449 |
| 482 | |
| 483 Isolate* JSCallReducer::isolate() const { return jsgraph()->isolate(); } | 450 Isolate* JSCallReducer::isolate() const { return jsgraph()->isolate(); } |
| 484 | 451 |
| 485 | |
| 486 CommonOperatorBuilder* JSCallReducer::common() const { | 452 CommonOperatorBuilder* JSCallReducer::common() const { |
| 487 return jsgraph()->common(); | 453 return jsgraph()->common(); |
| 488 } | 454 } |
| 489 | 455 |
| 490 | |
| 491 JSOperatorBuilder* JSCallReducer::javascript() const { | 456 JSOperatorBuilder* JSCallReducer::javascript() const { |
| 492 return jsgraph()->javascript(); | 457 return jsgraph()->javascript(); |
| 493 } | 458 } |
| 494 | 459 |
| 495 SimplifiedOperatorBuilder* JSCallReducer::simplified() const { | 460 SimplifiedOperatorBuilder* JSCallReducer::simplified() const { |
| 496 return jsgraph()->simplified(); | 461 return jsgraph()->simplified(); |
| 497 } | 462 } |
| 498 | 463 |
| 499 } // namespace compiler | 464 } // namespace compiler |
| 500 } // namespace internal | 465 } // namespace internal |
| 501 } // namespace v8 | 466 } // namespace v8 |
| OLD | NEW |