blob: e02fc49de87f3d54eabb3dde75e6742f5341684e [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005#include "src/compiler/js-context-specialization.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007#include "src/compiler/common-operator.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008#include "src/compiler/js-graph.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009#include "src/compiler/js-operator.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include "src/compiler/node-matchers.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011#include "src/compiler/node-properties.h"
12#include "src/contexts.h"
13#include "src/objects-inl.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014
15namespace v8 {
16namespace internal {
17namespace compiler {
18
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019Reduction JSContextSpecialization::Reduce(Node* node) {
20 switch (node->opcode()) {
21 case IrOpcode::kJSLoadContext:
22 return ReduceJSLoadContext(node);
23 case IrOpcode::kJSStoreContext:
24 return ReduceJSStoreContext(node);
25 default:
26 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040027 }
28 return NoChange();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000029}
30
31
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032MaybeHandle<Context> JSContextSpecialization::GetSpecializationContext(
33 Node* node) {
34 DCHECK(node->opcode() == IrOpcode::kJSLoadContext ||
35 node->opcode() == IrOpcode::kJSStoreContext);
36 Node* const object = NodeProperties::GetValueInput(node, 0);
37 return NodeProperties::GetSpecializationContext(object, context());
38}
39
40
41Reduction JSContextSpecialization::ReduceJSLoadContext(Node* node) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000042 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
43
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000044 // Get the specialization context from the node.
45 Handle<Context> context;
46 if (!GetSpecializationContext(node).ToHandle(&context)) return NoChange();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000047
48 // Find the right parent context.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000049 const ContextAccess& access = ContextAccessOf(node->op());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040050 for (size_t i = access.depth(); i > 0; --i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000051 context = handle(context->previous(), isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000052 }
53
54 // If the access itself is mutable, only fold-in the parent.
55 if (!access.immutable()) {
56 // The access does not have to look up a parent, nothing to fold.
57 if (access.depth() == 0) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040058 return NoChange();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000059 }
60 const Operator* op = jsgraph_->javascript()->LoadContext(
61 0, access.index(), access.immutable());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000062 node->ReplaceInput(0, jsgraph_->Constant(context));
63 NodeProperties::ChangeOp(node, op);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040064 return Changed(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000065 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000066 Handle<Object> value =
67 handle(context->get(static_cast<int>(access.index())), isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000068
69 // Even though the context slot is immutable, the context might have escaped
70 // before the function to which it belongs has initialized the slot.
71 // We must be conservative and check if the value in the slot is currently the
72 // hole or undefined. If it is neither of these, then it must be initialized.
Ben Murdoch61f157c2016-09-16 13:49:30 +010073 if (value->IsUndefined(isolate()) || value->IsTheHole(isolate())) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040074 return NoChange();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000075 }
76
77 // Success. The context load can be replaced with the constant.
78 // TODO(titzer): record the specialization for sharing code across multiple
79 // contexts that have the same value in the corresponding context slot.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040080 Node* constant = jsgraph_->Constant(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000081 ReplaceWithValue(node, constant);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040082 return Replace(constant);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000083}
84
85
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000086Reduction JSContextSpecialization::ReduceJSStoreContext(Node* node) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000087 DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode());
88
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000089 // Get the specialization context from the node.
90 Handle<Context> context;
91 if (!GetSpecializationContext(node).ToHandle(&context)) return NoChange();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000092
93 // The access does not have to look up a parent, nothing to fold.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000094 const ContextAccess& access = ContextAccessOf(node->op());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000095 if (access.depth() == 0) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040096 return NoChange();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000097 }
98
99 // Find the right parent context.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400100 for (size_t i = access.depth(); i > 0; --i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000101 context = handle(context->previous(), isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000102 }
103
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000104 node->ReplaceInput(0, jsgraph_->Constant(context));
105 NodeProperties::ChangeOp(node, javascript()->StoreContext(0, access.index()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400106 return Changed(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000107}
108
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000109
110Isolate* JSContextSpecialization::isolate() const {
111 return jsgraph()->isolate();
112}
113
114
115JSOperatorBuilder* JSContextSpecialization::javascript() const {
116 return jsgraph()->javascript();
117}
118
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000119} // namespace compiler
120} // namespace internal
121} // namespace v8