LCOV - code coverage report
Current view: top level - src/compiler - js-context-specialization.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 50 52 96.2 %
Date: 2017-04-26 Functions: 6 8 75.0 %

          Line data    Source code
       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/compiler/js-context-specialization.h"
       6             : 
       7             : #include "src/compiler/common-operator.h"
       8             : #include "src/compiler/js-graph.h"
       9             : #include "src/compiler/js-operator.h"
      10             : #include "src/compiler/linkage.h"
      11             : #include "src/compiler/node-matchers.h"
      12             : #include "src/compiler/node-properties.h"
      13             : #include "src/contexts.h"
      14             : #include "src/objects-inl.h"
      15             : 
      16             : namespace v8 {
      17             : namespace internal {
      18             : namespace compiler {
      19             : 
      20    32422901 : Reduction JSContextSpecialization::Reduce(Node* node) {
      21    32422901 :   switch (node->opcode()) {
      22             :     case IrOpcode::kParameter:
      23     1386566 :       return ReduceParameter(node);
      24             :     case IrOpcode::kJSLoadContext:
      25      615798 :       return ReduceJSLoadContext(node);
      26             :     case IrOpcode::kJSStoreContext:
      27      158315 :       return ReduceJSStoreContext(node);
      28             :     default:
      29             :       break;
      30             :   }
      31             :   return NoChange();
      32             : }
      33             : 
      34     1751384 : Reduction JSContextSpecialization::ReduceParameter(Node* node) {
      35             :   DCHECK_EQ(IrOpcode::kParameter, node->opcode());
      36     1386566 :   int const index = ParameterIndexOf(node->op());
      37     1386567 :   if (index == Linkage::kJSCallClosureParamIndex) {
      38             :     // Constant-fold the function parameter {node}.
      39             :     Handle<JSFunction> function;
      40      392537 :     if (closure().ToHandle(&function)) {
      41      364818 :       Node* value = jsgraph()->HeapConstant(function);
      42             :       return Replace(value);
      43             :     }
      44             :   }
      45             :   return NoChange();
      46             : }
      47             : 
      48      494655 : Reduction JSContextSpecialization::SimplifyJSLoadContext(Node* node,
      49             :                                                          Node* new_context,
      50             :                                                          size_t new_depth) {
      51             :   DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
      52      745797 :   const ContextAccess& access = ContextAccessOf(node->op());
      53             :   DCHECK_LE(new_depth, access.depth());
      54             : 
      55      982213 :   if (new_depth == access.depth() &&
      56      487558 :       new_context == NodeProperties::GetContextInput(node)) {
      57             :     return NoChange();
      58             :   }
      59             : 
      60             :   const Operator* op = jsgraph_->javascript()->LoadContext(
      61      251142 :       new_depth, access.index(), access.immutable());
      62      125571 :   NodeProperties::ReplaceContextInput(node, new_context);
      63      125571 :   NodeProperties::ChangeOp(node, op);
      64             :   return Changed(node);
      65             : }
      66             : 
      67      158315 : Reduction JSContextSpecialization::SimplifyJSStoreContext(Node* node,
      68             :                                                           Node* new_context,
      69             :                                                           size_t new_depth) {
      70             :   DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode());
      71      163522 :   const ContextAccess& access = ContextAccessOf(node->op());
      72             :   DCHECK_LE(new_depth, access.depth());
      73             : 
      74      316533 :   if (new_depth == access.depth() &&
      75      158218 :       new_context == NodeProperties::GetContextInput(node)) {
      76             :     return NoChange();
      77             :   }
      78             : 
      79             :   const Operator* op =
      80        5207 :       jsgraph_->javascript()->StoreContext(new_depth, access.index());
      81        5207 :   NodeProperties::ReplaceContextInput(node, new_context);
      82        5207 :   NodeProperties::ChangeOp(node, op);
      83             :   return Changed(node);
      84             : }
      85             : 
      86      899671 : Reduction JSContextSpecialization::ReduceJSLoadContext(Node* node) {
      87             :   DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
      88             : 
      89     1142620 :   const ContextAccess& access = ContextAccessOf(node->op());
      90      615798 :   size_t depth = access.depth();
      91             : 
      92             :   // First walk up the context chain in the graph as far as possible.
      93      615798 :   Node* outer = NodeProperties::GetOuterContext(node, &depth);
      94             : 
      95             :   Handle<Context> concrete;
      96      615798 :   if (!NodeProperties::GetSpecializationContext(outer, context())
      97     1231596 :            .ToHandle(&concrete)) {
      98             :     // We do not have a concrete context object, so we can only partially reduce
      99             :     // the load by folding-in the outer context node.
     100      210782 :     return SimplifyJSLoadContext(node, outer, depth);
     101             :   }
     102             : 
     103             :   // Now walk up the concrete context chain for the remaining depth.
     104        7554 :   for (; depth > 0; --depth) {
     105             :     concrete = handle(concrete->previous(), isolate());
     106             :   }
     107             : 
     108      405016 :   if (!access.immutable()) {
     109             :     // We found the requested context object but since the context slot is
     110             :     // mutable we can only partially reduce the load.
     111      283210 :     return SimplifyJSLoadContext(node, jsgraph()->Constant(concrete), depth);
     112             :   }
     113             : 
     114             :   // Even though the context slot is immutable, the context might have escaped
     115             :   // before the function to which it belongs has initialized the slot.
     116             :   // We must be conservative and check if the value in the slot is currently
     117             :   // the hole or undefined. Only if it is neither of these, can we be sure that
     118             :   // it won't change anymore.
     119             :   Handle<Object> value(concrete->get(static_cast<int>(access.index())),
     120      121806 :                        isolate());
     121      243005 :   if (value->IsUndefined(isolate()) || value->IsTheHole(isolate())) {
     122        1326 :     return SimplifyJSLoadContext(node, jsgraph()->Constant(concrete), depth);
     123             :   }
     124             : 
     125             :   // Success. The context load can be replaced with the constant.
     126             :   // TODO(titzer): record the specialization for sharing code across multiple
     127             :   // contexts that have the same value in the corresponding context slot.
     128      121143 :   Node* constant = jsgraph_->Constant(value);
     129      121143 :   ReplaceWithValue(node, constant);
     130             :   return Replace(constant);
     131             : }
     132             : 
     133             : 
     134      164426 : Reduction JSContextSpecialization::ReduceJSStoreContext(Node* node) {
     135             :   DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode());
     136             : 
     137      158315 :   const ContextAccess& access = ContextAccessOf(node->op());
     138      158315 :   size_t depth = access.depth();
     139             : 
     140             :   // First walk up the context chain in the graph until we reduce the depth to 0
     141             :   // or hit a node that does not have a CreateXYZContext operator.
     142      158315 :   Node* outer = NodeProperties::GetOuterContext(node, &depth);
     143             : 
     144             :   Handle<Context> concrete;
     145      158315 :   if (!NodeProperties::GetSpecializationContext(outer, context())
     146      316630 :            .ToHandle(&concrete)) {
     147             :     // We do not have a concrete context object, so we can only partially reduce
     148             :     // the load by folding-in the outer context node.
     149      152204 :     return SimplifyJSStoreContext(node, outer, depth);
     150             :   }
     151             : 
     152             :   // Now walk up the concrete context chain for the remaining depth.
     153          61 :   for (; depth > 0; --depth) {
     154             :     concrete = handle(concrete->previous(), isolate());
     155             :   }
     156             : 
     157        6111 :   return SimplifyJSStoreContext(node, jsgraph()->Constant(concrete), depth);
     158             : }
     159             : 
     160             : 
     161      372426 : Isolate* JSContextSpecialization::isolate() const {
     162      372426 :   return jsgraph()->isolate();
     163             : }
     164             : 
     165             : 
     166           0 : JSOperatorBuilder* JSContextSpecialization::javascript() const {
     167           0 :   return jsgraph()->javascript();
     168             : }
     169             : 
     170             : }  // namespace compiler
     171             : }  // namespace internal
     172             : }  // namespace v8

Generated by: LCOV version 1.10