js-create-lowering-unittest.cc revision 342c50ce1624b485728b9a4fc41d8bbf37eb46cf
1// Copyright 2016 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-create-lowering.h" 6#include "src/code-factory.h" 7#include "src/compiler/access-builder.h" 8#include "src/compiler/js-graph.h" 9#include "src/compiler/js-operator.h" 10#include "src/compiler/machine-operator.h" 11#include "src/compiler/node-properties.h" 12#include "src/compiler/operator-properties.h" 13#include "src/isolate-inl.h" 14#include "test/unittests/compiler/compiler-test-utils.h" 15#include "test/unittests/compiler/graph-unittest.h" 16#include "test/unittests/compiler/node-test-utils.h" 17#include "testing/gmock-support.h" 18 19using testing::_; 20using testing::BitEq; 21using testing::IsNaN; 22 23namespace v8 { 24namespace internal { 25namespace compiler { 26 27class JSCreateLoweringTest : public TypedGraphTest { 28 public: 29 JSCreateLoweringTest() 30 : TypedGraphTest(3), javascript_(zone()), deps_(isolate(), zone()) {} 31 ~JSCreateLoweringTest() override {} 32 33 protected: 34 Reduction Reduce(Node* node) { 35 MachineOperatorBuilder machine(zone()); 36 SimplifiedOperatorBuilder simplified(zone()); 37 JSGraph jsgraph(isolate(), graph(), common(), javascript(), &simplified, 38 &machine); 39 // TODO(titzer): mock the GraphReducer here for better unit testing. 40 GraphReducer graph_reducer(zone(), graph()); 41 JSCreateLowering reducer(&graph_reducer, &deps_, &jsgraph, 42 MaybeHandle<LiteralsArray>(), zone()); 43 return reducer.Reduce(node); 44 } 45 46 Node* FrameState(Handle<SharedFunctionInfo> shared, Node* outer_frame_state) { 47 Node* state_values = graph()->NewNode(common()->StateValues(0)); 48 return graph()->NewNode( 49 common()->FrameState( 50 BailoutId::None(), OutputFrameStateCombine::Ignore(), 51 common()->CreateFrameStateFunctionInfo( 52 FrameStateType::kJavaScriptFunction, 1, 0, shared)), 53 state_values, state_values, state_values, NumberConstant(0), 54 UndefinedConstant(), outer_frame_state); 55 } 56 57 JSOperatorBuilder* javascript() { return &javascript_; } 58 59 private: 60 JSOperatorBuilder javascript_; 61 CompilationDependencies deps_; 62}; 63 64TEST_F(JSCreateLoweringTest, JSCreate) { 65 Handle<JSFunction> function = isolate()->object_function(); 66 Node* const target = Parameter(Type::Constant(function, graph()->zone())); 67 Node* const context = Parameter(Type::Any()); 68 Node* const effect = graph()->start(); 69 Reduction r = Reduce(graph()->NewNode(javascript()->Create(), target, target, 70 context, EmptyFrameState(), effect)); 71 ASSERT_TRUE(r.Changed()); 72 EXPECT_THAT( 73 r.replacement(), 74 IsFinishRegion( 75 IsAllocate(IsNumberConstant(function->initial_map()->instance_size()), 76 IsBeginRegion(effect), _), 77 _)); 78} 79 80// ----------------------------------------------------------------------------- 81// JSCreateArguments 82 83TEST_F(JSCreateLoweringTest, JSCreateArgumentsViaStub) { 84 Node* const closure = Parameter(Type::Any()); 85 Node* const context = UndefinedConstant(); 86 Node* const effect = graph()->start(); 87 Node* const control = graph()->start(); 88 Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared()); 89 Node* const frame_state = FrameState(shared, graph()->start()); 90 Reduction r = Reduce(graph()->NewNode( 91 javascript()->CreateArguments(CreateArgumentsType::kUnmappedArguments), 92 closure, context, frame_state, effect, control)); 93 ASSERT_TRUE(r.Changed()); 94 EXPECT_THAT( 95 r.replacement(), 96 IsCall(_, IsHeapConstant( 97 CodeFactory::FastNewStrictArguments(isolate()).code()), 98 closure, context, frame_state, effect, control)); 99} 100 101TEST_F(JSCreateLoweringTest, JSCreateArgumentsRestParameterViaStub) { 102 Node* const closure = Parameter(Type::Any()); 103 Node* const context = UndefinedConstant(); 104 Node* const effect = graph()->start(); 105 Node* const control = graph()->start(); 106 Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared()); 107 Node* const frame_state = FrameState(shared, graph()->start()); 108 Reduction r = Reduce(graph()->NewNode( 109 javascript()->CreateArguments(CreateArgumentsType::kRestParameter), 110 closure, context, frame_state, effect, control)); 111 ASSERT_TRUE(r.Changed()); 112 EXPECT_THAT( 113 r.replacement(), 114 IsCall(_, IsHeapConstant( 115 CodeFactory::FastNewRestParameter(isolate()).code()), 116 closure, context, frame_state, effect, control)); 117} 118 119TEST_F(JSCreateLoweringTest, JSCreateArgumentsInlinedMapped) { 120 Node* const closure = Parameter(Type::Any()); 121 Node* const context = UndefinedConstant(); 122 Node* const effect = graph()->start(); 123 Node* const control = graph()->start(); 124 Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared()); 125 Node* const frame_state_outer = FrameState(shared, graph()->start()); 126 Node* const frame_state_inner = FrameState(shared, frame_state_outer); 127 Reduction r = Reduce(graph()->NewNode( 128 javascript()->CreateArguments(CreateArgumentsType::kMappedArguments), 129 closure, context, frame_state_inner, effect, control)); 130 ASSERT_TRUE(r.Changed()); 131 EXPECT_THAT(r.replacement(), 132 IsFinishRegion( 133 IsAllocate(IsNumberConstant(JSSloppyArgumentsObject::kSize), 134 _, control), 135 _)); 136} 137 138TEST_F(JSCreateLoweringTest, JSCreateArgumentsInlinedUnmapped) { 139 Node* const closure = Parameter(Type::Any()); 140 Node* const context = UndefinedConstant(); 141 Node* const effect = graph()->start(); 142 Node* const control = graph()->start(); 143 Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared()); 144 Node* const frame_state_outer = FrameState(shared, graph()->start()); 145 Node* const frame_state_inner = FrameState(shared, frame_state_outer); 146 Reduction r = Reduce(graph()->NewNode( 147 javascript()->CreateArguments(CreateArgumentsType::kUnmappedArguments), 148 closure, context, frame_state_inner, effect, control)); 149 ASSERT_TRUE(r.Changed()); 150 EXPECT_THAT(r.replacement(), 151 IsFinishRegion( 152 IsAllocate(IsNumberConstant(JSStrictArgumentsObject::kSize), 153 _, control), 154 _)); 155} 156 157TEST_F(JSCreateLoweringTest, JSCreateArgumentsInlinedRestArray) { 158 Node* const closure = Parameter(Type::Any()); 159 Node* const context = UndefinedConstant(); 160 Node* const effect = graph()->start(); 161 Node* const control = graph()->start(); 162 Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared()); 163 Node* const frame_state_outer = FrameState(shared, graph()->start()); 164 Node* const frame_state_inner = FrameState(shared, frame_state_outer); 165 Reduction r = Reduce(graph()->NewNode( 166 javascript()->CreateArguments(CreateArgumentsType::kRestParameter), 167 closure, context, frame_state_inner, effect, control)); 168 ASSERT_TRUE(r.Changed()); 169 EXPECT_THAT(r.replacement(), 170 IsFinishRegion( 171 IsAllocate(IsNumberConstant(JSArray::kSize), _, control), _)); 172} 173 174// ----------------------------------------------------------------------------- 175// JSCreateFunctionContext 176 177TEST_F(JSCreateLoweringTest, JSCreateFunctionContextViaInlinedAllocation) { 178 Node* const closure = Parameter(Type::Any()); 179 Node* const context = Parameter(Type::Any()); 180 Node* const effect = graph()->start(); 181 Node* const control = graph()->start(); 182 Reduction const r = 183 Reduce(graph()->NewNode(javascript()->CreateFunctionContext(8), closure, 184 context, effect, control)); 185 ASSERT_TRUE(r.Changed()); 186 EXPECT_THAT(r.replacement(), 187 IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor( 188 8 + Context::MIN_CONTEXT_SLOTS)), 189 IsBeginRegion(_), control), 190 _)); 191} 192 193// ----------------------------------------------------------------------------- 194// JSCreateWithContext 195 196TEST_F(JSCreateLoweringTest, JSCreateWithContext) { 197 Node* const object = Parameter(Type::Receiver()); 198 Node* const closure = Parameter(Type::Function()); 199 Node* const context = Parameter(Type::Any()); 200 Node* const effect = graph()->start(); 201 Node* const control = graph()->start(); 202 Reduction r = 203 Reduce(graph()->NewNode(javascript()->CreateWithContext(), object, 204 closure, context, effect, control)); 205 ASSERT_TRUE(r.Changed()); 206 EXPECT_THAT(r.replacement(), 207 IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor( 208 Context::MIN_CONTEXT_SLOTS)), 209 IsBeginRegion(_), control), 210 _)); 211} 212 213// ----------------------------------------------------------------------------- 214// JSCreateCatchContext 215 216TEST_F(JSCreateLoweringTest, JSCreateCatchContext) { 217 Handle<String> name = factory()->length_string(); 218 Node* const exception = Parameter(Type::Receiver()); 219 Node* const closure = Parameter(Type::Function()); 220 Node* const context = Parameter(Type::Any()); 221 Node* const effect = graph()->start(); 222 Node* const control = graph()->start(); 223 Reduction r = 224 Reduce(graph()->NewNode(javascript()->CreateCatchContext(name), exception, 225 closure, context, effect, control)); 226 ASSERT_TRUE(r.Changed()); 227 EXPECT_THAT(r.replacement(), 228 IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor( 229 Context::MIN_CONTEXT_SLOTS + 1)), 230 IsBeginRegion(_), control), 231 _)); 232} 233 234} // namespace compiler 235} // namespace internal 236} // namespace v8 237