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    32494705 : Reduction JSContextSpecialization::Reduce(Node* node) {
      21    32494705 :   switch (node->opcode()) {
      22             :     case IrOpcode::kParameter:
      23     1389476 :       return ReduceParameter(node);
      24             :     case IrOpcode::kJSLoadContext:
      25      615201 :       return ReduceJSLoadContext(node);
      26             :     case IrOpcode::kJSStoreContext:
      27      157925 :       return ReduceJSStoreContext(node);
      28             :     default:
      29             :       break;
      30             :   }
      31             :   return NoChange();
      32             : }
      33             : 
      34     1754996 : Reduction JSContextSpecialization::ReduceParameter(Node* node) {
      35             :   DCHECK_EQ(IrOpcode::kParameter, node->opcode());
      36     1389476 :   int const index = ParameterIndexOf(node->op());
      37     1389476 :   if (index == Linkage::kJSCallClosureParamIndex) {
      38             :     // Constant-fold the function parameter {node}.
      39             :     Handle<JSFunction> function;
      40      393276 :     if (closure().ToHandle(&function)) {
      41      365520 :       Node* value = jsgraph()->HeapConstant(function);
      42             :       return Replace(value);
      43             :     }
      44             :   }
      45             :   return NoChange();
      46             : }
      47             : 
      48      493911 : Reduction JSContextSpecialization::SimplifyJSLoadContext(Node* node,
      49             :                                                          Node* new_context,
      50             :                                                          size_t new_depth) {
      51             :   DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
      52      745095 :   const ContextAccess& access = ContextAccessOf(node->op());
      53             :   DCHECK_LE(new_depth, access.depth());
      54             : 
      55      980733 :   if (new_depth == access.depth() &&
      56      486822 :       new_context == NodeProperties::GetContextInput(node)) {
      57             :     return NoChange();
      58             :   }
      59             : 
      60             :   const Operator* op = jsgraph_->javascript()->LoadContext(
      61      251184 :       new_depth, access.index(), access.immutable());
      62      125592 :   NodeProperties::ReplaceContextInput(node, new_context);
      63      125592 :   NodeProperties::ChangeOp(node, op);
      64             :   return Changed(node);
      65             : }
      66             : 
      67      157925 : Reduction JSContextSpecialization::SimplifyJSStoreContext(Node* node,
      68             :                                                           Node* new_context,
      69             :                                                           size_t new_depth) {
      70             :   DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode());
      71      163134 :   const ContextAccess& access = ContextAccessOf(node->op());
      72             :   DCHECK_LE(new_depth, access.depth());
      73             : 
      74      315753 :   if (new_depth == access.depth() &&
      75      157828 :       new_context == NodeProperties::GetContextInput(node)) {
      76             :     return NoChange();
      77             :   }
      78             : 
      79             :   const Operator* op =
      80        5209 :       jsgraph_->javascript()->StoreContext(new_depth, access.index());
      81        5209 :   NodeProperties::ReplaceContextInput(node, new_context);
      82        5209 :   NodeProperties::ChangeOp(node, op);
      83             :   return Changed(node);
      84             : }
      85             : 
      86      898707 : Reduction JSContextSpecialization::ReduceJSLoadContext(Node* node) {
      87             :   DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
      88             : 
      89     1141946 :   const ContextAccess& access = ContextAccessOf(node->op());
      90      615200 :   size_t depth = access.depth();
      91             : 
      92             :   // First walk up the context chain in the graph as far as possible.
      93      615200 :   Node* outer = NodeProperties::GetOuterContext(node, &depth);
      94             : 
      95             :   Handle<Context> concrete;
      96      615201 :   if (!NodeProperties::GetSpecializationContext(outer, context())
      97     1230401 :            .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      210405 :     return SimplifyJSLoadContext(node, outer, depth);
     101             :   }
     102             : 
     103             :   // Now walk up the concrete context chain for the remaining depth.
     104        7557 :   for (; depth > 0; --depth) {
     105             :     concrete = handle(concrete->previous(), isolate());
     106             :   }
     107             : 
     108      404796 :   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      282847 :     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      121949 :                        isolate());
     121      243295 :   if (value->IsUndefined(isolate()) || value->IsTheHole(isolate())) {
     122        1318 :     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      121290 :   Node* constant = jsgraph_->Constant(value);
     129      121290 :   ReplaceWithValue(node, constant);
     130             :   return Replace(constant);
     131             : }
     132             : 
     133             : 
     134      164039 : Reduction JSContextSpecialization::ReduceJSStoreContext(Node* node) {
     135             :   DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode());
     136             : 
     137      157925 :   const ContextAccess& access = ContextAccessOf(node->op());
     138      157925 :   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      157925 :   Node* outer = NodeProperties::GetOuterContext(node, &depth);
     143             : 
     144             :   Handle<Context> concrete;
     145      157925 :   if (!NodeProperties::GetSpecializationContext(outer, context())
     146      315850 :            .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      151811 :     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        6114 :   return SimplifyJSStoreContext(node, jsgraph()->Constant(concrete), depth);
     158             : }
     159             : 
     160             : 
     161      372862 : Isolate* JSContextSpecialization::isolate() const {
     162      372862 :   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