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 <iostream> | 5 #include <iostream> |
6 | 6 |
7 #include "src/compiler/bytecode-graph-builder.h" | 7 #include "src/compiler/bytecode-graph-builder.h" |
8 #include "src/compiler/common-operator.h" | 8 #include "src/compiler/common-operator.h" |
9 #include "src/compiler/graph-visualizer.h" | 9 #include "src/compiler/graph-visualizer.h" |
10 #include "src/compiler/instruction.h" | 10 #include "src/compiler/instruction.h" |
11 #include "src/compiler/instruction-selector.h" | 11 #include "src/compiler/instruction-selector.h" |
12 #include "src/compiler/js-graph.h" | 12 #include "src/compiler/js-graph.h" |
13 #include "src/compiler/js-operator.h" | 13 #include "src/compiler/js-operator.h" |
14 #include "src/compiler/linkage.h" | |
14 #include "src/interpreter/bytecode-array-builder.h" | 15 #include "src/interpreter/bytecode-array-builder.h" |
16 #include "src/interpreter/interpreter.h" | |
15 #include "src/parser.h" | 17 #include "src/parser.h" |
16 #include "test/unittests/compiler/compiler-test-utils.h" | 18 #include "test/unittests/compiler/compiler-test-utils.h" |
17 #include "test/unittests/compiler/graph-unittest.h" | 19 #include "test/unittests/compiler/graph-unittest.h" |
18 #include "test/unittests/compiler/node-test-utils.h" | 20 #include "test/unittests/compiler/node-test-utils.h" |
19 #include "test/unittests/test-utils.h" | 21 #include "test/unittests/test-utils.h" |
20 | 22 |
21 using ::testing::_; | 23 using ::testing::_; |
22 | 24 |
23 namespace v8 { | 25 namespace v8 { |
24 namespace internal { | 26 namespace internal { |
25 namespace compiler { | 27 namespace compiler { |
26 | 28 |
29 #define SPACE() | |
30 | |
31 #define REPEAT_2(SEP, ...) __VA_ARGS__ SEP() __VA_ARGS__ | |
32 #define REPEAT_4(SEP, ...) \ | |
33 REPEAT_2(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__) | |
34 #define REPEAT_8(SEP, ...) \ | |
35 REPEAT_4(SEP, __VA_ARGS__) SEP() REPEAT_4(SEP, __VA_ARGS__) | |
36 #define REPEAT_16(SEP, ...) \ | |
37 REPEAT_8(SEP, __VA_ARGS__) SEP() REPEAT_8(SEP, __VA_ARGS__) | |
38 #define REPEAT_32(SEP, ...) \ | |
39 REPEAT_16(SEP, __VA_ARGS__) SEP() REPEAT_16(SEP, __VA_ARGS__) | |
40 #define REPEAT_64(SEP, ...) \ | |
41 REPEAT_32(SEP, __VA_ARGS__) SEP() REPEAT_32(SEP, __VA_ARGS__) | |
42 #define REPEAT_128(SEP, ...) \ | |
43 REPEAT_64(SEP, __VA_ARGS__) SEP() REPEAT_64(SEP, __VA_ARGS__) | |
44 #define REPEAT_256(SEP, ...) \ | |
45 REPEAT_128(SEP, __VA_ARGS__) SEP() REPEAT_128(SEP, __VA_ARGS__) | |
46 | |
47 #define REPEAT_127(SEP, ...) \ | |
48 REPEAT_64(SEP, __VA_ARGS__) \ | |
49 SEP() \ | |
50 REPEAT_32(SEP, __VA_ARGS__) \ | |
51 SEP() \ | |
52 REPEAT_16(SEP, __VA_ARGS__) \ | |
53 SEP() \ | |
54 REPEAT_8(SEP, __VA_ARGS__) \ | |
55 SEP() \ | |
56 REPEAT_4(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__) SEP() __VA_ARGS__ | |
57 | |
58 static const char* kFunctionName = "f"; | |
59 | |
60 class GraphGeneratorHelper { | |
61 public: | |
62 GraphGeneratorHelper(Isolate* isolate, Zone* zone, const char* script, | |
63 const char* function_name = kFunctionName) | |
rmcilroy
2015/11/10 18:00:15
Do you think you'll ever need the function_name pa
mythria
2015/11/11 13:39:24
Done.
| |
64 : GraphGeneratorHelper(isolate, zone, script, | |
65 MaybeHandle<BytecodeArray>(), function_name) {} | |
66 | |
67 GraphGeneratorHelper(Isolate* isolate, Zone* zone, | |
68 MaybeHandle<BytecodeArray> bytecode, | |
69 const char* function_name = kFunctionName) | |
rmcilroy
2015/11/10 18:00:15
No need for the function_name argument here - it'l
mythria
2015/11/11 13:39:24
Done.
| |
70 : GraphGeneratorHelper(isolate, zone, nullptr, bytecode, function_name) {} | |
71 | |
72 Graph* GetCompletedGraph() { | |
73 ParseInfo parse_info = GetParseInfo(); | |
rmcilroy
2015/11/10 18:00:15
I'd just inline all of GetParseInfo() here and inc
mythria
2015/11/11 13:39:24
I did this more to avoid using a new to create Com
| |
74 CompilationInfo info(&parse_info); | |
75 if (!bytecode_.is_null()) { | |
76 info.shared_info()->set_function_data(*bytecode_.ToHandleChecked()); | |
77 } | |
78 | |
79 MachineOperatorBuilder* machine = new (zone_) MachineOperatorBuilder( | |
80 zone_, kMachPtr, InstructionSelector::SupportedMachineOperatorFlags()); | |
81 CommonOperatorBuilder* common = new (zone_) CommonOperatorBuilder(zone_); | |
82 JSOperatorBuilder* javascript = new (zone_) JSOperatorBuilder(zone_); | |
83 Graph* graph = new (zone_) Graph(zone_); | |
84 JSGraph* jsgraph = new (zone_) | |
85 JSGraph(isolate_, graph, common, javascript, nullptr, machine); | |
86 | |
87 BytecodeGraphBuilder graph_builder(zone_, &info, jsgraph); | |
88 graph_builder.CreateGraph(); | |
89 return graph; | |
90 } | |
91 | |
92 static Handle<String> GetName(Isolate* isolate, const char* name) { | |
93 Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(name); | |
94 return isolate->factory()->string_table()->LookupString(isolate, result); | |
95 } | |
96 | |
97 private: | |
98 Isolate* isolate_; | |
99 Zone* zone_; | |
100 const char* script_; | |
101 MaybeHandle<BytecodeArray> bytecode_; | |
102 const char* function_name_; | |
rmcilroy
2015/11/10 18:00:15
Fields go below private functions: https://google.
mythria
2015/11/11 13:39:24
Done.
| |
103 | |
104 GraphGeneratorHelper(Isolate* isolate, Zone* zone, const char* script, | |
105 MaybeHandle<BytecodeArray> bytecode, | |
106 const char* function_name) | |
107 : isolate_(isolate), | |
108 zone_(zone), | |
109 script_(script), | |
110 bytecode_(bytecode), | |
111 function_name_(function_name) { | |
112 i::FLAG_ignition = true; | |
113 i::FLAG_always_opt = false; | |
114 i::FLAG_vector_stores = true; | |
115 // Set ignition filter flag via SetFlagsFromString to avoid double-free | |
116 // (or potential leak with StrDup() based on ownership confusion). | |
117 ScopedVector<char> ignition_filter(64); | |
118 SNPrintF(ignition_filter, "--ignition-filter=%s", function_name_); | |
119 FlagList::SetFlagsFromString(ignition_filter.start(), | |
120 ignition_filter.length()); | |
121 // Ensure handler table is generated. | |
122 isolate_->interpreter()->Initialize(); | |
123 } | |
124 | |
125 ParseInfo GetParseInfo() { | |
126 if (script_) { | |
127 v8::Context::New(v8::Isolate::GetCurrent())->Enter(); | |
128 v8::Local<v8::Context> context = | |
129 v8::Isolate::GetCurrent()->GetCurrentContext(); | |
130 CompileRun(script_); | |
131 | |
132 Local<Function> api_function = | |
133 Local<Function>::Cast(context->Global() | |
134 ->Get(context, v8_str(function_name_)) | |
135 .ToLocalChecked()); | |
136 Handle<JSFunction> function = | |
137 Handle<JSFunction>::cast(v8::Utils::OpenHandle(*api_function)); | |
138 CHECK(function->shared()->HasBytecodeArray()); | |
139 | |
140 context->Exit(); | |
141 return ParseInfo(zone_, function); | |
142 } else { | |
rmcilroy
2015/11/10 18:00:15
DCHECK(!bytecode_.is_null());
mythria
2015/11/11 13:39:25
Done.
| |
143 Handle<String> name = | |
144 isolate_->factory()->NewStringFromAsciiChecked(function_name_); | |
145 std::string script_str("function " + std::string(function_name_) + | |
146 "() {}"); | |
147 Handle<String> script = | |
148 isolate_->factory()->NewStringFromAsciiChecked(script_str.c_str()); | |
149 Handle<SharedFunctionInfo> shared_info = | |
150 isolate_->factory()->NewSharedFunctionInfo(name, MaybeHandle<Code>()); | |
151 shared_info->set_script(*isolate_->factory()->NewScript(script)); | |
152 return ParseInfo(zone_, shared_info); | |
153 } | |
154 } | |
155 | |
156 static v8::Local<v8::String> v8_str(const char* string) { | |
157 v8::Local<v8::String> v8_string = | |
158 v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), string, | |
159 v8::NewStringType::kNormal) | |
160 .ToLocalChecked(); | |
161 return v8_string; | |
162 } | |
163 | |
164 static Local<Value> CompileRun(const char* source) { | |
165 v8::Local<v8::Context> context = | |
166 v8::Isolate::GetCurrent()->GetCurrentContext(); | |
167 v8::Local<v8::Script> compiled_script = | |
168 (v8::Script::Compile(context, v8_str(source)).ToLocalChecked()); | |
169 return compiled_script->Run(context).ToLocalChecked(); | |
170 } | |
171 }; | |
172 | |
173 | |
27 class BytecodeGraphBuilderTest : public TestWithIsolateAndZone { | 174 class BytecodeGraphBuilderTest : public TestWithIsolateAndZone { |
28 public: | 175 public: |
29 BytecodeGraphBuilderTest() : array_builder_(isolate(), zone()) {} | 176 BytecodeGraphBuilderTest() : array_builder_(isolate(), zone()) {} |
30 | 177 |
31 Graph* GetCompletedGraph(); | |
32 | |
33 Matcher<Node*> IsUndefinedConstant(); | 178 Matcher<Node*> IsUndefinedConstant(); |
34 Matcher<Node*> IsNullConstant(); | 179 Matcher<Node*> IsNullConstant(); |
35 Matcher<Node*> IsTheHoleConstant(); | 180 Matcher<Node*> IsTheHoleConstant(); |
36 Matcher<Node*> IsFalseConstant(); | 181 Matcher<Node*> IsFalseConstant(); |
37 Matcher<Node*> IsTrueConstant(); | 182 Matcher<Node*> IsTrueConstant(); |
183 Matcher<Node*> IsIntPtrConstant(int value); | |
184 Matcher<Node*> IsFeedbackVector(Node* effect, Node* control); | |
38 | 185 |
39 interpreter::BytecodeArrayBuilder* array_builder() { return &array_builder_; } | 186 interpreter::BytecodeArrayBuilder* array_builder() { return &array_builder_; } |
40 | 187 |
41 private: | 188 private: |
42 interpreter::BytecodeArrayBuilder array_builder_; | 189 interpreter::BytecodeArrayBuilder array_builder_; |
43 | 190 |
44 DISALLOW_COPY_AND_ASSIGN(BytecodeGraphBuilderTest); | 191 DISALLOW_COPY_AND_ASSIGN(BytecodeGraphBuilderTest); |
45 }; | 192 }; |
46 | 193 |
47 | 194 |
48 Graph* BytecodeGraphBuilderTest::GetCompletedGraph() { | |
49 MachineOperatorBuilder* machine = new (zone()) MachineOperatorBuilder( | |
50 zone(), kMachPtr, InstructionSelector::SupportedMachineOperatorFlags()); | |
51 CommonOperatorBuilder* common = new (zone()) CommonOperatorBuilder(zone()); | |
52 JSOperatorBuilder* javascript = new (zone()) JSOperatorBuilder(zone()); | |
53 Graph* graph = new (zone()) Graph(zone()); | |
54 JSGraph* jsgraph = new (zone()) | |
55 JSGraph(isolate(), graph, common, javascript, nullptr, machine); | |
56 | |
57 Handle<String> name = factory()->NewStringFromStaticChars("test"); | |
58 Handle<String> script = factory()->NewStringFromStaticChars("test() {}"); | |
59 Handle<SharedFunctionInfo> shared_info = | |
60 factory()->NewSharedFunctionInfo(name, MaybeHandle<Code>()); | |
61 shared_info->set_script(*factory()->NewScript(script)); | |
62 | |
63 ParseInfo parse_info(zone(), shared_info); | |
64 CompilationInfo info(&parse_info); | |
65 Handle<BytecodeArray> bytecode_array = array_builder()->ToBytecodeArray(); | |
66 info.shared_info()->set_function_data(*bytecode_array); | |
67 | |
68 BytecodeGraphBuilder graph_builder(zone(), &info, jsgraph); | |
69 graph_builder.CreateGraph(); | |
70 return graph; | |
71 } | |
72 | |
73 | |
74 Matcher<Node*> BytecodeGraphBuilderTest::IsUndefinedConstant() { | 195 Matcher<Node*> BytecodeGraphBuilderTest::IsUndefinedConstant() { |
75 return IsHeapConstant(factory()->undefined_value()); | 196 return IsHeapConstant(factory()->undefined_value()); |
76 } | 197 } |
77 | 198 |
78 | 199 |
79 Matcher<Node*> BytecodeGraphBuilderTest::IsNullConstant() { | 200 Matcher<Node*> BytecodeGraphBuilderTest::IsNullConstant() { |
80 return IsHeapConstant(factory()->null_value()); | 201 return IsHeapConstant(factory()->null_value()); |
81 } | 202 } |
82 | 203 |
83 | 204 |
84 Matcher<Node*> BytecodeGraphBuilderTest::IsTheHoleConstant() { | 205 Matcher<Node*> BytecodeGraphBuilderTest::IsTheHoleConstant() { |
85 return IsHeapConstant(factory()->the_hole_value()); | 206 return IsHeapConstant(factory()->the_hole_value()); |
86 } | 207 } |
87 | 208 |
88 | 209 |
89 Matcher<Node*> BytecodeGraphBuilderTest::IsFalseConstant() { | 210 Matcher<Node*> BytecodeGraphBuilderTest::IsFalseConstant() { |
90 return IsHeapConstant(factory()->false_value()); | 211 return IsHeapConstant(factory()->false_value()); |
91 } | 212 } |
92 | 213 |
93 | 214 |
94 Matcher<Node*> BytecodeGraphBuilderTest::IsTrueConstant() { | 215 Matcher<Node*> BytecodeGraphBuilderTest::IsTrueConstant() { |
95 return IsHeapConstant(factory()->true_value()); | 216 return IsHeapConstant(factory()->true_value()); |
96 } | 217 } |
97 | 218 |
98 | 219 |
220 Matcher<Node*> BytecodeGraphBuilderTest::IsIntPtrConstant(int value) { | |
221 if (kPointerSize == 8) { | |
222 return IsInt64Constant(value); | |
223 } else { | |
224 return IsInt32Constant(value); | |
225 } | |
226 } | |
227 | |
228 | |
229 Matcher<Node*> BytecodeGraphBuilderTest::IsFeedbackVector(Node* effect, | |
230 Node* control) { | |
231 int offset = SharedFunctionInfo::kFeedbackVectorOffset - kHeapObjectTag; | |
232 int offset1 = JSFunction::kSharedFunctionInfoOffset - kHeapObjectTag; | |
233 | |
234 return IsLoad(kMachAnyTagged, | |
235 IsLoad(kMachAnyTagged, | |
236 IsParameter(Linkage::kJSFunctionCallClosureParamIndex), | |
237 IsIntPtrConstant(offset1), effect, control), | |
238 IsIntPtrConstant(offset), effect, control); | |
239 } | |
240 | |
241 | |
99 TEST_F(BytecodeGraphBuilderTest, ReturnUndefined) { | 242 TEST_F(BytecodeGraphBuilderTest, ReturnUndefined) { |
100 array_builder()->set_locals_count(0); | 243 array_builder()->set_locals_count(0); |
101 array_builder()->set_context_count(0); | 244 array_builder()->set_context_count(0); |
102 array_builder()->set_parameter_count(1); | 245 array_builder()->set_parameter_count(1); |
103 array_builder()->LoadUndefined().Return(); | 246 array_builder()->LoadUndefined().Return(); |
104 | 247 |
105 Graph* graph = GetCompletedGraph(); | 248 GraphGeneratorHelper helper(isolate(), zone(), |
249 array_builder()->ToBytecodeArray()); | |
250 Graph* graph = helper.GetCompletedGraph(); | |
106 Node* end = graph->end(); | 251 Node* end = graph->end(); |
107 EXPECT_EQ(1, end->InputCount()); | 252 EXPECT_EQ(1, end->InputCount()); |
108 Node* ret = end->InputAt(0); | 253 Node* ret = end->InputAt(0); |
109 Node* effect = graph->start(); | 254 Node* effect = graph->start(); |
110 Node* control = graph->start(); | 255 Node* control = graph->start(); |
111 EXPECT_THAT(ret, IsReturn(IsUndefinedConstant(), effect, control)); | 256 EXPECT_THAT(ret, IsReturn(IsUndefinedConstant(), effect, control)); |
112 } | 257 } |
113 | 258 |
114 | 259 |
115 TEST_F(BytecodeGraphBuilderTest, ReturnNull) { | 260 TEST_F(BytecodeGraphBuilderTest, ReturnNull) { |
116 array_builder()->set_locals_count(0); | 261 array_builder()->set_locals_count(0); |
117 array_builder()->set_context_count(0); | 262 array_builder()->set_context_count(0); |
118 array_builder()->set_parameter_count(1); | 263 array_builder()->set_parameter_count(1); |
119 array_builder()->LoadNull().Return(); | 264 array_builder()->LoadNull().Return(); |
120 | 265 |
121 Graph* graph = GetCompletedGraph(); | 266 GraphGeneratorHelper helper(isolate(), zone(), |
267 array_builder()->ToBytecodeArray()); | |
268 Graph* graph = helper.GetCompletedGraph(); | |
122 Node* end = graph->end(); | 269 Node* end = graph->end(); |
123 EXPECT_EQ(1, end->InputCount()); | 270 EXPECT_EQ(1, end->InputCount()); |
124 Node* ret = end->InputAt(0); | 271 Node* ret = end->InputAt(0); |
125 EXPECT_THAT(ret, IsReturn(IsNullConstant(), graph->start(), graph->start())); | 272 EXPECT_THAT(ret, IsReturn(IsNullConstant(), graph->start(), graph->start())); |
126 } | 273 } |
127 | 274 |
128 | 275 |
129 TEST_F(BytecodeGraphBuilderTest, ReturnTheHole) { | 276 TEST_F(BytecodeGraphBuilderTest, ReturnTheHole) { |
130 array_builder()->set_locals_count(0); | 277 array_builder()->set_locals_count(0); |
131 array_builder()->set_context_count(0); | 278 array_builder()->set_context_count(0); |
132 array_builder()->set_parameter_count(1); | 279 array_builder()->set_parameter_count(1); |
133 array_builder()->LoadTheHole().Return(); | 280 array_builder()->LoadTheHole().Return(); |
134 | 281 |
135 Graph* graph = GetCompletedGraph(); | 282 GraphGeneratorHelper helper(isolate(), zone(), |
283 array_builder()->ToBytecodeArray()); | |
284 Graph* graph = helper.GetCompletedGraph(); | |
136 Node* end = graph->end(); | 285 Node* end = graph->end(); |
137 EXPECT_EQ(1, end->InputCount()); | 286 EXPECT_EQ(1, end->InputCount()); |
138 Node* ret = end->InputAt(0); | 287 Node* ret = end->InputAt(0); |
139 Node* effect = graph->start(); | 288 Node* effect = graph->start(); |
140 Node* control = graph->start(); | 289 Node* control = graph->start(); |
141 EXPECT_THAT(ret, IsReturn(IsTheHoleConstant(), effect, control)); | 290 EXPECT_THAT(ret, IsReturn(IsTheHoleConstant(), effect, control)); |
142 } | 291 } |
143 | 292 |
144 | 293 |
145 TEST_F(BytecodeGraphBuilderTest, ReturnTrue) { | 294 TEST_F(BytecodeGraphBuilderTest, ReturnTrue) { |
146 array_builder()->set_locals_count(0); | 295 array_builder()->set_locals_count(0); |
147 array_builder()->set_context_count(0); | 296 array_builder()->set_context_count(0); |
148 array_builder()->set_parameter_count(1); | 297 array_builder()->set_parameter_count(1); |
149 array_builder()->LoadTrue().Return(); | 298 array_builder()->LoadTrue().Return(); |
150 | 299 |
151 Graph* graph = GetCompletedGraph(); | 300 GraphGeneratorHelper helper(isolate(), zone(), |
301 array_builder()->ToBytecodeArray()); | |
302 Graph* graph = helper.GetCompletedGraph(); | |
152 Node* end = graph->end(); | 303 Node* end = graph->end(); |
153 EXPECT_EQ(1, end->InputCount()); | 304 EXPECT_EQ(1, end->InputCount()); |
154 Node* ret = end->InputAt(0); | 305 Node* ret = end->InputAt(0); |
155 Node* effect = graph->start(); | 306 Node* effect = graph->start(); |
156 Node* control = graph->start(); | 307 Node* control = graph->start(); |
157 EXPECT_THAT(ret, IsReturn(IsTrueConstant(), effect, control)); | 308 EXPECT_THAT(ret, IsReturn(IsTrueConstant(), effect, control)); |
158 } | 309 } |
159 | 310 |
160 | 311 |
161 TEST_F(BytecodeGraphBuilderTest, ReturnFalse) { | 312 TEST_F(BytecodeGraphBuilderTest, ReturnFalse) { |
162 array_builder()->set_locals_count(0); | 313 array_builder()->set_locals_count(0); |
163 array_builder()->set_context_count(0); | 314 array_builder()->set_context_count(0); |
164 array_builder()->set_parameter_count(1); | 315 array_builder()->set_parameter_count(1); |
165 array_builder()->LoadFalse().Return(); | 316 array_builder()->LoadFalse().Return(); |
166 | 317 |
167 Graph* graph = GetCompletedGraph(); | 318 GraphGeneratorHelper helper(isolate(), zone(), |
319 array_builder()->ToBytecodeArray()); | |
320 Graph* graph = helper.GetCompletedGraph(); | |
168 Node* end = graph->end(); | 321 Node* end = graph->end(); |
169 EXPECT_EQ(1, end->InputCount()); | 322 EXPECT_EQ(1, end->InputCount()); |
170 Node* ret = end->InputAt(0); | 323 Node* ret = end->InputAt(0); |
171 Node* effect = graph->start(); | 324 Node* effect = graph->start(); |
172 Node* control = graph->start(); | 325 Node* control = graph->start(); |
173 EXPECT_THAT(ret, IsReturn(IsFalseConstant(), effect, control)); | 326 EXPECT_THAT(ret, IsReturn(IsFalseConstant(), effect, control)); |
174 } | 327 } |
175 | 328 |
176 | 329 |
177 TEST_F(BytecodeGraphBuilderTest, ReturnInt8) { | 330 TEST_F(BytecodeGraphBuilderTest, ReturnInt8) { |
178 static const int kValue = 3; | 331 static const int kValue = 3; |
179 array_builder()->set_locals_count(0); | 332 array_builder()->set_locals_count(0); |
180 array_builder()->set_context_count(0); | 333 array_builder()->set_context_count(0); |
181 array_builder()->set_parameter_count(1); | 334 array_builder()->set_parameter_count(1); |
182 array_builder()->LoadLiteral(Smi::FromInt(kValue)).Return(); | 335 array_builder()->LoadLiteral(Smi::FromInt(kValue)).Return(); |
183 | 336 |
184 Graph* graph = GetCompletedGraph(); | 337 GraphGeneratorHelper helper(isolate(), zone(), |
338 array_builder()->ToBytecodeArray()); | |
339 Graph* graph = helper.GetCompletedGraph(); | |
185 Node* end = graph->end(); | 340 Node* end = graph->end(); |
186 EXPECT_EQ(1, end->InputCount()); | 341 EXPECT_EQ(1, end->InputCount()); |
187 Node* ret = end->InputAt(0); | 342 Node* ret = end->InputAt(0); |
188 Node* effect = graph->start(); | 343 Node* effect = graph->start(); |
189 Node* control = graph->start(); | 344 Node* control = graph->start(); |
190 EXPECT_THAT(ret, IsReturn(IsNumberConstant(kValue), effect, control)); | 345 EXPECT_THAT(ret, IsReturn(IsNumberConstant(kValue), effect, control)); |
191 } | 346 } |
192 | 347 |
193 | 348 |
194 TEST_F(BytecodeGraphBuilderTest, ReturnDouble) { | 349 TEST_F(BytecodeGraphBuilderTest, ReturnDouble) { |
195 const double kValue = 0.123456789; | 350 const double kValue = 0.123456789; |
196 array_builder()->set_locals_count(0); | 351 array_builder()->set_locals_count(0); |
197 array_builder()->set_context_count(0); | 352 array_builder()->set_context_count(0); |
198 array_builder()->set_parameter_count(1); | 353 array_builder()->set_parameter_count(1); |
199 array_builder()->LoadLiteral(factory()->NewHeapNumber(kValue)); | 354 array_builder()->LoadLiteral(factory()->NewHeapNumber(kValue)); |
200 array_builder()->Return(); | 355 array_builder()->Return(); |
201 | 356 |
202 Graph* graph = GetCompletedGraph(); | 357 GraphGeneratorHelper helper(isolate(), zone(), |
358 array_builder()->ToBytecodeArray()); | |
359 Graph* graph = helper.GetCompletedGraph(); | |
203 Node* end = graph->end(); | 360 Node* end = graph->end(); |
204 EXPECT_EQ(1, end->InputCount()); | 361 EXPECT_EQ(1, end->InputCount()); |
205 Node* ret = end->InputAt(0); | 362 Node* ret = end->InputAt(0); |
206 Node* effect = graph->start(); | 363 Node* effect = graph->start(); |
207 Node* control = graph->start(); | 364 Node* control = graph->start(); |
208 EXPECT_THAT(ret, IsReturn(IsNumberConstant(kValue), effect, control)); | 365 EXPECT_THAT(ret, IsReturn(IsNumberConstant(kValue), effect, control)); |
209 } | 366 } |
210 | 367 |
211 | 368 |
212 TEST_F(BytecodeGraphBuilderTest, SimpleExpressionWithParameters) { | 369 TEST_F(BytecodeGraphBuilderTest, SimpleExpressionWithParameters) { |
213 array_builder()->set_locals_count(1); | 370 array_builder()->set_locals_count(1); |
214 array_builder()->set_context_count(0); | 371 array_builder()->set_context_count(0); |
215 array_builder()->set_parameter_count(3); | 372 array_builder()->set_parameter_count(3); |
216 array_builder() | 373 array_builder() |
217 ->LoadAccumulatorWithRegister(array_builder()->Parameter(1)) | 374 ->LoadAccumulatorWithRegister(array_builder()->Parameter(1)) |
218 .BinaryOperation(Token::Value::ADD, array_builder()->Parameter(2), | 375 .BinaryOperation(Token::Value::ADD, array_builder()->Parameter(2), |
219 Strength::WEAK) | 376 Strength::WEAK) |
220 .StoreAccumulatorInRegister(interpreter::Register(0)) | 377 .StoreAccumulatorInRegister(interpreter::Register(0)) |
221 .Return(); | 378 .Return(); |
222 | 379 |
223 Graph* graph = GetCompletedGraph(); | 380 GraphGeneratorHelper helper(isolate(), zone(), |
381 array_builder()->ToBytecodeArray()); | |
382 Graph* graph = helper.GetCompletedGraph(); | |
224 Node* end = graph->end(); | 383 Node* end = graph->end(); |
225 EXPECT_EQ(1, end->InputCount()); | 384 EXPECT_EQ(1, end->InputCount()); |
226 Node* ret = end->InputAt(0); | 385 Node* ret = end->InputAt(0); |
227 // NB binary operation is <reg> <op> <acc>. The register represents | 386 // NB binary operation is <reg> <op> <acc>. The register represents |
228 // the left-hand side, which is why parameters appear in opposite | 387 // the left-hand side, which is why parameters appear in opposite |
229 // order to construction via the builder. | 388 // order to construction via the builder. |
230 EXPECT_THAT(ret, IsReturn(IsJSAdd(IsParameter(2), IsParameter(1)), _, _)); | 389 EXPECT_THAT(ret, IsReturn(IsJSAdd(IsParameter(2), IsParameter(1)), _, _)); |
231 } | 390 } |
232 | 391 |
233 | 392 |
234 TEST_F(BytecodeGraphBuilderTest, SimpleExpressionWithRegister) { | 393 TEST_F(BytecodeGraphBuilderTest, SimpleExpressionWithRegister) { |
235 static const int kLeft = -655371; | 394 static const int kLeft = -655371; |
236 static const int kRight = +2000000; | 395 static const int kRight = +2000000; |
237 array_builder()->set_locals_count(1); | 396 array_builder()->set_locals_count(1); |
238 array_builder()->set_context_count(0); | 397 array_builder()->set_context_count(0); |
239 array_builder()->set_parameter_count(1); | 398 array_builder()->set_parameter_count(1); |
240 array_builder() | 399 array_builder() |
241 ->LoadLiteral(Smi::FromInt(kLeft)) | 400 ->LoadLiteral(Smi::FromInt(kLeft)) |
242 .StoreAccumulatorInRegister(interpreter::Register(0)) | 401 .StoreAccumulatorInRegister(interpreter::Register(0)) |
243 .LoadLiteral(Smi::FromInt(kRight)) | 402 .LoadLiteral(Smi::FromInt(kRight)) |
244 .BinaryOperation(Token::Value::ADD, interpreter::Register(0), | 403 .BinaryOperation(Token::Value::ADD, interpreter::Register(0), |
245 Strength::WEAK) | 404 Strength::WEAK) |
246 .Return(); | 405 .Return(); |
247 | 406 |
248 Graph* graph = GetCompletedGraph(); | 407 GraphGeneratorHelper helper(isolate(), zone(), |
408 array_builder()->ToBytecodeArray()); | |
409 Graph* graph = helper.GetCompletedGraph(); | |
249 Node* end = graph->end(); | 410 Node* end = graph->end(); |
250 EXPECT_EQ(1, end->InputCount()); | 411 EXPECT_EQ(1, end->InputCount()); |
251 Node* ret = end->InputAt(0); | 412 Node* ret = end->InputAt(0); |
252 EXPECT_THAT( | 413 EXPECT_THAT( |
253 ret, IsReturn(IsJSAdd(IsNumberConstant(kLeft), IsNumberConstant(kRight)), | 414 ret, IsReturn(IsJSAdd(IsNumberConstant(kLeft), IsNumberConstant(kRight)), |
254 _, _)); | 415 _, _)); |
255 } | 416 } |
256 | 417 |
418 | |
419 TEST_F(BytecodeGraphBuilderTest, NamedLoadSloppy) { | |
420 const char* code_snippet = "function f(p1) {return p1.val;}; f({val:10});"; | |
421 GraphGeneratorHelper helper(isolate(), zone(), code_snippet); | |
422 Graph* graph = helper.GetCompletedGraph(); | |
423 | |
424 Node* ret = graph->end()->InputAt(0); | |
425 Node* start = graph->start(); | |
426 | |
427 Handle<Name> name = GraphGeneratorHelper::GetName(isolate(), "val"); | |
428 Matcher<Node*> feedback_vector_matcher = IsFeedbackVector(start, start); | |
429 Matcher<Node*> load_named_matcher = IsJSLoadNamed( | |
430 name, IsParameter(1), feedback_vector_matcher, start, start); | |
431 | |
432 EXPECT_THAT(ret, IsReturn(load_named_matcher, _, _)); | |
433 } | |
434 | |
435 | |
436 TEST_F(BytecodeGraphBuilderTest, NamedLoadStrict) { | |
437 const char* code_snippet = | |
438 "function f(p1) {'use strict'; return p1.val;}; f({val:10});"; | |
439 GraphGeneratorHelper helper(isolate(), zone(), code_snippet); | |
440 Graph* graph = helper.GetCompletedGraph(); | |
441 | |
442 Node* ret = graph->end()->InputAt(0); | |
443 Node* start = graph->start(); | |
444 | |
445 Handle<Name> name = GraphGeneratorHelper::GetName(isolate(), "val"); | |
446 Matcher<Node*> feedback_vector_matcher = IsFeedbackVector(start, start); | |
447 Matcher<Node*> load_named_matcher = IsJSLoadNamed( | |
448 name, IsParameter(1), feedback_vector_matcher, start, start); | |
449 | |
450 EXPECT_THAT(ret, IsReturn(load_named_matcher, _, _)); | |
451 } | |
452 | |
453 | |
454 TEST_F(BytecodeGraphBuilderTest, NamedLoadSloppyWide) { | |
455 const char code_snippet[] = "function f(p1) {var b; " | |
456 REPEAT_127(SPACE, " b = p1.name; ") | |
rmcilroy
2015/11/10 18:00:15
nit - for clarity maybe make this val_prev or some
mythria
2015/11/11 13:39:24
Done.
| |
457 "return p1.val;}; f({val:10, name:'abc'});"; | |
458 GraphGeneratorHelper helper(isolate(), zone(), code_snippet); | |
459 Graph* graph = helper.GetCompletedGraph(); | |
460 | |
461 Node* ret = graph->end()->InputAt(0); | |
462 Node* start = graph->start(); | |
463 | |
464 Handle<Name> name = GraphGeneratorHelper::GetName(isolate(), "val"); | |
465 Matcher<Node*> feedback_vector_matcher = IsFeedbackVector(start, start); | |
466 Matcher<Node*> effect = IsJSLoadNamed( | |
rmcilroy
2015/11/10 18:00:15
nit - call this preceeding_load or similar for cla
mythria
2015/11/11 13:39:24
Done.
| |
467 GraphGeneratorHelper::GetName(isolate(), "name"), _, _, _, _); | |
468 Matcher<Node*> load_named_matcher_wide = IsJSLoadNamed( | |
469 name, IsParameter(1), feedback_vector_matcher, effect, IsIfSuccess(_)); | |
470 | |
471 EXPECT_THAT(ret, IsReturn(load_named_matcher_wide, _, _)); | |
472 } | |
473 | |
474 | |
475 TEST_F(BytecodeGraphBuilderTest, NamedLoadStrictWide) { | |
476 const char code_snippet[] = "function f(p1) {'use strict'; var b;" | |
477 REPEAT_127(SPACE, " b = p1.name; ") | |
rmcilroy
2015/11/10 18:00:15
ditto
mythria
2015/11/11 13:39:24
Done.
| |
478 "return p1.val;}; f({val:10, name:'abc'});"; | |
479 GraphGeneratorHelper helper(isolate(), zone(), code_snippet); | |
480 Graph* graph = helper.GetCompletedGraph(); | |
481 | |
482 Node* ret = graph->end()->InputAt(0); | |
483 Node* start = graph->start(); | |
484 | |
485 Handle<Name> name = GraphGeneratorHelper::GetName(isolate(), "val"); | |
486 Matcher<Node*> feedback_vector_matcher = IsFeedbackVector(start, start); | |
487 Matcher<Node*> effect = IsJSLoadNamed( | |
rmcilroy
2015/11/10 18:00:15
ditto
mythria
2015/11/11 13:39:24
Done.
| |
488 GraphGeneratorHelper::GetName(isolate(), "name"), _, _, _, _); | |
489 Matcher<Node*> load_named_matcher_wide = IsJSLoadNamed( | |
490 name, IsParameter(1), feedback_vector_matcher, effect, IsIfSuccess(_)); | |
491 | |
492 EXPECT_THAT(ret, IsReturn(load_named_matcher_wide, _, _)); | |
493 } | |
494 | |
257 } // namespace compiler | 495 } // namespace compiler |
258 } // namespace internal | 496 } // namespace internal |
259 } // namespace v8 | 497 } // namespace v8 |
OLD | NEW |