1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2014 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/js-context-specialization.h" 6014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler/js-graph.h" 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/js-operator.h" 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/node-matchers.h" 9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler/node-properties.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/source-position.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "test/cctest/cctest.h" 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "test/cctest/compiler/function-tester.h" 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "test/cctest/compiler/graph-builder-tester.h" 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace v8 { 16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace internal { 17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace compiler { 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass ContextSpecializationTester : public HandleAndZoneScope { 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ContextSpecializationTester() 22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch : graph_(new (main_zone()) Graph(main_zone())), 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch common_(main_zone()), 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch javascript_(main_zone()), 25958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier machine_(main_zone()), 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch simplified_(main_zone()), 27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch jsgraph_(main_isolate(), graph(), common(), &javascript_, &simplified_, 28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch &machine_), 29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch reducer_(main_zone(), graph()), 30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch spec_(&reducer_, jsgraph(), MaybeHandle<Context>()) {} 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSContextSpecialization* spec() { return &spec_; } 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Factory* factory() { return main_isolate()->factory(); } 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CommonOperatorBuilder* common() { return &common_; } 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSOperatorBuilder* javascript() { return &javascript_; } 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SimplifiedOperatorBuilder* simplified() { return &simplified_; } 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSGraph* jsgraph() { return &jsgraph_; } 38014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Graph* graph() { return graph_; } 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Graph* graph_; 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CommonOperatorBuilder common_; 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSOperatorBuilder javascript_; 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MachineOperatorBuilder machine_; 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SimplifiedOperatorBuilder simplified_; 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSGraph jsgraph_; 47014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch GraphReducer reducer_; 48014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSContextSpecialization spec_; 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ReduceJSLoadContext) { 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ContextSpecializationTester t; 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* start = t.graph()->NewNode(t.common()->Start(0)); 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch t.graph()->SetStart(start); 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make a context and initialize it a bit for this test. 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Context> native = t.factory()->NewNativeContext(); 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Context> subcontext1 = t.factory()->NewNativeContext(); 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Context> subcontext2 = t.factory()->NewNativeContext(); 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch subcontext2->set_previous(*subcontext1); 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch subcontext1->set_previous(*native); 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> expected = t.factory()->InternalizeUtf8String("gboy!"); 65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const int slot = Context::NATIVE_CONTEXT_INDEX; 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch native->set(slot, *expected); 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* const_context = t.jsgraph()->Constant(native); 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* deep_const_context = t.jsgraph()->Constant(subcontext2); 70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* param_context = t.graph()->NewNode(t.common()->Parameter(0), start); 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Mutable slot, constant context, depth = 0 => do nothing. 74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* load = t.graph()->NewNode(t.javascript()->LoadContext(0, 0, false), 75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const_context, const_context, start); 76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Reduction r = t.spec()->Reduce(load); 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!r.Changed()); 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Mutable slot, non-constant context, depth = 0 => do nothing. 82014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* load = t.graph()->NewNode(t.javascript()->LoadContext(0, 0, false), 83014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch param_context, param_context, start); 84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Reduction r = t.spec()->Reduce(load); 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!r.Changed()); 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Mutable slot, constant context, depth > 0 => fold-in parent context. 90014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* load = t.graph()->NewNode( 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch t.javascript()->LoadContext(2, Context::GLOBAL_EVAL_FUN_INDEX, false), 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch deep_const_context, deep_const_context, start); 93014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Reduction r = t.spec()->Reduce(load); 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(r.Changed()); 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* new_context_input = NodeProperties::GetValueInput(r.replacement(), 0); 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK_EQ(IrOpcode::kHeapConstant, new_context_input->opcode()); 97014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HeapObjectMatcher match(new_context_input); 98014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CHECK_EQ(*native, *match.Value()); 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ContextAccess access = OpParameter<ContextAccess>(r.replacement()); 100958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, static_cast<int>(access.index())); 101958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CHECK_EQ(0, static_cast<int>(access.depth())); 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK_EQ(false, access.immutable()); 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Immutable slot, constant context, depth = 0 => specialize. 107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* load = t.graph()->NewNode(t.javascript()->LoadContext(0, slot, true), 108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const_context, const_context, start); 109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Reduction r = t.spec()->Reduce(load); 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(r.Changed()); 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(r.replacement() != load); 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HeapObjectMatcher match(r.replacement()); 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(match.HasValue()); 115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CHECK_EQ(*expected, *match.Value()); 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(titzer): test with other kinds of contexts, e.g. a function context. 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(sigurds): test that loads below create context are not optimized 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ReduceJSStoreContext) { 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ContextSpecializationTester t; 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* start = t.graph()->NewNode(t.common()->Start(0)); 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch t.graph()->SetStart(start); 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make a context and initialize it a bit for this test. 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Context> native = t.factory()->NewNativeContext(); 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Context> subcontext1 = t.factory()->NewNativeContext(); 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Context> subcontext2 = t.factory()->NewNativeContext(); 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch subcontext2->set_previous(*subcontext1); 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch subcontext1->set_previous(*native); 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> expected = t.factory()->InternalizeUtf8String("gboy!"); 136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const int slot = Context::NATIVE_CONTEXT_INDEX; 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch native->set(slot, *expected); 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* const_context = t.jsgraph()->Constant(native); 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* deep_const_context = t.jsgraph()->Constant(subcontext2); 141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* param_context = t.graph()->NewNode(t.common()->Parameter(0), start); 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Mutable slot, constant context, depth = 0 => do nothing. 145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* load = 146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch t.graph()->NewNode(t.javascript()->StoreContext(0, 0), const_context, 147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const_context, const_context, start, start); 148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Reduction r = t.spec()->Reduce(load); 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!r.Changed()); 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Mutable slot, non-constant context, depth = 0 => do nothing. 154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* load = 155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch t.graph()->NewNode(t.javascript()->StoreContext(0, 0), param_context, 156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch param_context, const_context, start, start); 157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Reduction r = t.spec()->Reduce(load); 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!r.Changed()); 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Immutable slot, constant context, depth = 0 => do nothing. 163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* load = 164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch t.graph()->NewNode(t.javascript()->StoreContext(0, slot), const_context, 165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const_context, const_context, start, start); 166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Reduction r = t.spec()->Reduce(load); 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!r.Changed()); 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Mutable slot, constant context, depth > 0 => fold-in parent context. 172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* load = t.graph()->NewNode( 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch t.javascript()->StoreContext(2, Context::GLOBAL_EVAL_FUN_INDEX), 174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch deep_const_context, deep_const_context, const_context, start, start); 175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Reduction r = t.spec()->Reduce(load); 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(r.Changed()); 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* new_context_input = NodeProperties::GetValueInput(r.replacement(), 0); 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK_EQ(IrOpcode::kHeapConstant, new_context_input->opcode()); 179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HeapObjectMatcher match(new_context_input); 180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CHECK_EQ(*native, *match.Value()); 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ContextAccess access = OpParameter<ContextAccess>(r.replacement()); 182958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, static_cast<int>(access.index())); 183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CHECK_EQ(0, static_cast<int>(access.depth())); 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK_EQ(false, access.immutable()); 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(titzer): factor out common code with effects checking in typed lowering. 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CheckEffectInput(Node* effect, Node* use) { 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK_EQ(effect, NodeProperties::GetEffectInput(use)); 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(SpecializeToContext) { 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ContextSpecializationTester t; 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* start = t.graph()->NewNode(t.common()->Start(0)); 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch t.graph()->SetStart(start); 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make a context and initialize it a bit for this test. 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Context> native = t.factory()->NewNativeContext(); 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> expected = t.factory()->InternalizeUtf8String("gboy!"); 204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const int slot = Context::NATIVE_CONTEXT_INDEX; 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch native->set(slot, *expected); 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* const_context = t.jsgraph()->Constant(native); 208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* param_context = t.graph()->NewNode(t.common()->Parameter(0), start); 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 211958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that specialization replaces values and forwards effects 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // correctly, and folds values from constant and non-constant contexts 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* effect_in = start; 214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* load = t.graph()->NewNode(t.javascript()->LoadContext(0, slot, true), 215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const_context, const_context, effect_in); 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* value_use = 219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch t.graph()->NewNode(t.simplified()->ChangeTaggedToInt32(), load); 220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* other_load = 221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch t.graph()->NewNode(t.javascript()->LoadContext(0, slot, true), 222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch param_context, param_context, load); 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* effect_use = other_load; 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* other_use = 225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch t.graph()->NewNode(t.simplified()->ChangeTaggedToInt32(), other_load); 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* add = t.graph()->NewNode( 228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch t.javascript()->Add(LanguageMode::SLOPPY, BinaryOperationHints::Any()), 229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch value_use, other_use, param_context, t.jsgraph()->EmptyFrameState(), 230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch t.jsgraph()->EmptyFrameState(), other_load, start); 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* ret = 233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch t.graph()->NewNode(t.common()->Return(), add, effect_use, start); 234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* end = t.graph()->NewNode(t.common()->End(1), ret); 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch USE(end); 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch t.graph()->SetEnd(end); 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Double check the above graph is what we expect, or the test is broken. 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckEffectInput(effect_in, load); 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckEffectInput(load, effect_use); 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 242958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Perform the reduction on the entire graph. 243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch GraphReducer graph_reducer(t.main_zone(), t.graph()); 244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSContextSpecialization spec(&graph_reducer, t.jsgraph(), 245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MaybeHandle<Context>()); 246958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier graph_reducer.AddReducer(&spec); 247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier graph_reducer.ReduceGraph(); 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Effects should have been forwarded (not replaced with a value). 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckEffectInput(effect_in, effect_use); 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Use of {other_load} should not have been replaced. 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK_EQ(other_load, other_use->InputAt(0)); 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* replacement = value_use->InputAt(0); 256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HeapObjectMatcher match(replacement); 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(match.HasValue()); 258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CHECK_EQ(*expected, *match.Value()); 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(titzer): clean up above test and test more complicated effects. 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(SpecializeJSFunction_ToConstant1) { 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FunctionTester T( 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "(function() { var x = 1; function inc(a)" 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " { return a + x; } return inc; })()"); 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch T.CheckCall(1.0, 0.0, 0.0); 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch T.CheckCall(2.0, 1.0, 0.0); 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch T.CheckCall(2.1, 1.1, 0.0); 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(SpecializeJSFunction_ToConstant2) { 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FunctionTester T( 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "(function() { var x = 1.5; var y = 2.25; var z = 3.75;" 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " function f(a) { return a - x + y - z; } return f; })()"); 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch T.CheckCall(-3.0, 0.0, 0.0); 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch T.CheckCall(-2.0, 1.0, 0.0); 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch T.CheckCall(-1.9, 1.1, 0.0); 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(SpecializeJSFunction_ToConstant3) { 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FunctionTester T( 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "(function() { var x = -11.5; function inc()" 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " { return (function(a) { return a + x; }); }" 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " return inc(); })()"); 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch T.CheckCall(-11.5, 0.0, 0.0); 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch T.CheckCall(-10.5, 1.0, 0.0); 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch T.CheckCall(-10.4, 1.1, 0.0); 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(SpecializeJSFunction_ToConstant_uninit) { 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FunctionTester T( 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "(function() { if (false) { var x = 1; } function inc(a)" 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " { return x; } return inc; })()"); // x is undefined! 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(T.Call(T.Val(0.0), T.Val(0.0)).ToHandleChecked()->IsUndefined()); 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(T.Call(T.Val(2.0), T.Val(0.0)).ToHandleChecked()->IsUndefined()); 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(T.Call(T.Val(-2.1), T.Val(0.0)).ToHandleChecked()->IsUndefined()); 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FunctionTester T( 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "(function() { if (false) { var x = 1; } function inc(a)" 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " { return a + x; } return inc; })()"); // x is undefined! 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(T.Call(T.Val(0.0), T.Val(0.0)).ToHandleChecked()->IsNaN()); 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(T.Call(T.Val(2.0), T.Val(0.0)).ToHandleChecked()->IsNaN()); 316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(T.Call(T.Val(-2.1), T.Val(0.0)).ToHandleChecked()->IsNaN()); 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace compiler 321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 323