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-native-context-specialization.h" | 5 #include "src/compiler/js-native-context-specialization.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/compilation-dependencies.h" | 8 #include "src/compilation-dependencies.h" |
9 #include "src/compiler/access-builder.h" | 9 #include "src/compiler/access-builder.h" |
10 #include "src/compiler/js-graph.h" | 10 #include "src/compiler/js-graph.h" |
11 #include "src/compiler/js-operator.h" | 11 #include "src/compiler/js-operator.h" |
| 12 #include "src/compiler/node-matchers.h" |
12 #include "src/contexts.h" | 13 #include "src/contexts.h" |
13 #include "src/field-index-inl.h" | 14 #include "src/field-index-inl.h" |
14 #include "src/lookup.h" | 15 #include "src/lookup.h" |
15 #include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker! | 16 #include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker! |
16 #include "src/type-cache.h" | 17 #include "src/type-cache.h" |
17 #include "src/type-feedback-vector.h" | 18 #include "src/type-feedback-vector.h" |
18 | 19 |
19 namespace v8 { | 20 namespace v8 { |
20 namespace internal { | 21 namespace internal { |
21 namespace compiler { | 22 namespace compiler { |
(...skipping 14 matching lines...) Expand all Loading... |
36 flags_(flags), | 37 flags_(flags), |
37 global_object_(global_object), | 38 global_object_(global_object), |
38 native_context_(global_object->native_context(), isolate()), | 39 native_context_(global_object->native_context(), isolate()), |
39 dependencies_(dependencies), | 40 dependencies_(dependencies), |
40 zone_(zone), | 41 zone_(zone), |
41 type_cache_(TypeCache::Get()) {} | 42 type_cache_(TypeCache::Get()) {} |
42 | 43 |
43 | 44 |
44 Reduction JSNativeContextSpecialization::Reduce(Node* node) { | 45 Reduction JSNativeContextSpecialization::Reduce(Node* node) { |
45 switch (node->opcode()) { | 46 switch (node->opcode()) { |
| 47 case IrOpcode::kJSCallFunction: |
| 48 return ReduceJSCallFunction(node); |
46 case IrOpcode::kJSLoadGlobal: | 49 case IrOpcode::kJSLoadGlobal: |
47 return ReduceJSLoadGlobal(node); | 50 return ReduceJSLoadGlobal(node); |
48 case IrOpcode::kJSStoreGlobal: | 51 case IrOpcode::kJSStoreGlobal: |
49 return ReduceJSStoreGlobal(node); | 52 return ReduceJSStoreGlobal(node); |
50 case IrOpcode::kJSLoadNamed: | 53 case IrOpcode::kJSLoadNamed: |
51 return ReduceJSLoadNamed(node); | 54 return ReduceJSLoadNamed(node); |
52 case IrOpcode::kJSStoreNamed: | 55 case IrOpcode::kJSStoreNamed: |
53 return ReduceJSStoreNamed(node); | 56 return ReduceJSStoreNamed(node); |
54 default: | 57 default: |
55 break; | 58 break; |
56 } | 59 } |
57 return NoChange(); | 60 return NoChange(); |
58 } | 61 } |
59 | 62 |
60 | 63 |
| 64 Reduction JSNativeContextSpecialization::ReduceJSCallFunction(Node* node) { |
| 65 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); |
| 66 CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); |
| 67 Node* target = NodeProperties::GetValueInput(node, 0); |
| 68 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); |
| 69 Node* control = NodeProperties::GetControlInput(node); |
| 70 Node* effect = NodeProperties::GetEffectInput(node); |
| 71 |
| 72 // Not much we can do if deoptimization support is disabled. |
| 73 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); |
| 74 |
| 75 // Don't mess with JSCallFunction nodes that have a constant {target}. |
| 76 if (HeapObjectMatcher(target).HasValue()) return NoChange(); |
| 77 if (!p.feedback().IsValid()) return NoChange(); |
| 78 CallICNexus nexus(p.feedback().vector(), p.feedback().slot()); |
| 79 Handle<Object> feedback(nexus.GetFeedback(), isolate()); |
| 80 if (feedback->IsWeakCell()) { |
| 81 Handle<WeakCell> cell = Handle<WeakCell>::cast(feedback); |
| 82 if (cell->value()->IsJSFunction()) { |
| 83 // Avoid cross-context leaks, meaning don't embed references to functions |
| 84 // in other native contexts. |
| 85 Handle<JSFunction> function(JSFunction::cast(cell->value()), isolate()); |
| 86 if (function->context()->native_context() != |
| 87 global_object()->native_context()) { |
| 88 return NoChange(); |
| 89 } |
| 90 |
| 91 // Check that the {target} is still the {target_function}. |
| 92 Node* target_function = jsgraph()->HeapConstant(function); |
| 93 Node* check = graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), |
| 94 target, target_function); |
| 95 Node* branch = |
| 96 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); |
| 97 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
| 98 Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state, |
| 99 effect, if_false); |
| 100 // TODO(bmeurer): This should be on the AdvancedReducer somehow. |
| 101 NodeProperties::MergeControlToEnd(graph(), common(), deoptimize); |
| 102 control = graph()->NewNode(common()->IfTrue(), branch); |
| 103 |
| 104 // Specialize the JSCallFunction node to the {target_function}. |
| 105 NodeProperties::ReplaceValueInput(node, target_function, 0); |
| 106 NodeProperties::ReplaceControlInput(node, control); |
| 107 return Changed(node); |
| 108 } |
| 109 // TODO(bmeurer): Also support optimizing bound functions and proxies here. |
| 110 } |
| 111 return NoChange(); |
| 112 } |
| 113 |
| 114 |
61 Reduction JSNativeContextSpecialization::ReduceJSLoadGlobal(Node* node) { | 115 Reduction JSNativeContextSpecialization::ReduceJSLoadGlobal(Node* node) { |
62 DCHECK_EQ(IrOpcode::kJSLoadGlobal, node->opcode()); | 116 DCHECK_EQ(IrOpcode::kJSLoadGlobal, node->opcode()); |
63 Handle<Name> name = LoadGlobalParametersOf(node->op()).name(); | 117 Handle<Name> name = LoadGlobalParametersOf(node->op()).name(); |
64 Node* effect = NodeProperties::GetEffectInput(node); | 118 Node* effect = NodeProperties::GetEffectInput(node); |
65 Node* control = NodeProperties::GetControlInput(node); | 119 Node* control = NodeProperties::GetControlInput(node); |
66 | 120 |
67 // Try to lookup the name on the script context table first (lexical scoping). | 121 // Try to lookup the name on the script context table first (lexical scoping). |
68 ScriptContextTableLookupResult result; | 122 ScriptContextTableLookupResult result; |
69 if (LookupInScriptContextTable(name, &result)) { | 123 if (LookupInScriptContextTable(name, &result)) { |
70 if (result.context->is_the_hole(result.index)) return NoChange(); | 124 if (result.context->is_the_hole(result.index)) return NoChange(); |
(...skipping 859 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
930 } | 984 } |
931 | 985 |
932 | 986 |
933 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { | 987 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { |
934 return jsgraph()->simplified(); | 988 return jsgraph()->simplified(); |
935 } | 989 } |
936 | 990 |
937 } // namespace compiler | 991 } // namespace compiler |
938 } // namespace internal | 992 } // namespace internal |
939 } // namespace v8 | 993 } // namespace v8 |
OLD | NEW |