Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: test/unittests/compiler/bytecode-graph-builder-unittest.cc

Issue 1419373007: [Interpreter] Adds implementation of bytecode graph builder for LoadICSloppy/Strict (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Added unittests and addressed review comments Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
59 class GraphGeneratorHelper {
60 public:
61 const char* kFunctionName = "f";
62
63 GraphGeneratorHelper(Isolate* isolate, Zone* zone)
64 : isolate_(isolate), zone_(zone) {
65 i::FLAG_ignition = true;
66 i::FLAG_always_opt = false;
67 i::FLAG_vector_stores = true;
68 // Set ignition filter flag via SetFlagsFromString to avoid double-free
69 // (or potential leak with StrDup() based on ownership confusion).
70 ScopedVector<char> ignition_filter(64);
71 SNPrintF(ignition_filter, "--ignition-filter=%s", kFunctionName);
72 FlagList::SetFlagsFromString(ignition_filter.start(),
73 ignition_filter.length());
74 // Ensure handler table is generated.
75 isolate_->interpreter()->Initialize();
76 v8::Context::New(v8::Isolate::GetCurrent())->Enter();
77 }
78
79 Graph* MakeGraph(const char* script, const char* function_name) {
80 v8::Local<v8::Context> context =
81 v8::Isolate::GetCurrent()->GetCurrentContext();
82 v8::Local<v8::String> v8_function_name =
83 v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), function_name,
84 v8::NewStringType::kNormal)
85 .ToLocalChecked();
86
87 CompileRun(script);
88
89 Local<Function> api_function = Local<Function>::Cast(
90 context->Global()->Get(context, v8_function_name).ToLocalChecked());
91 Handle<JSFunction> function =
92 Handle<JSFunction>::cast(v8::Utils::OpenHandle(*api_function));
93 CHECK(function->shared()->HasBytecodeArray());
94
95 ParseInfo parse_info(zone_, function);
96 CompilationInfo compilation_info(&parse_info);
97
98 MachineOperatorBuilder* machine = new (zone_) MachineOperatorBuilder(
99 zone_, kMachPtr, InstructionSelector::SupportedMachineOperatorFlags());
100 CommonOperatorBuilder* common = new (zone_) CommonOperatorBuilder(zone_);
101 JSOperatorBuilder* javascript = new (zone_) JSOperatorBuilder(zone_);
102 Graph* graph = new (zone_) Graph(zone_);
103 JSGraph* jsgraph = new (zone_)
104 JSGraph(isolate_, graph, common, javascript, nullptr, machine);
105
106 BytecodeGraphBuilder graph_builder(zone_, &compilation_info, jsgraph);
107 graph_builder.CreateGraph();
108 return graph;
109 }
110
111 Graph* MakeGraphForFunctionBody(const char* body) {
112 ScopedVector<char> program(3072);
113 SNPrintF(program, "function %s() { %s }\n%s();", kFunctionName, body,
114 kFunctionName);
115 return MakeGraph(program.start(), kFunctionName);
116 }
117
118 Graph* MakeGraphForFunction(const char* function) {
119 ScopedVector<char> program(3072);
120 SNPrintF(program, "%s\n%s();", function, kFunctionName);
121 return MakeGraph(program.start(), kFunctionName);
122 }
123
124 Graph* MakeGraphForScript(const char* script) {
125 ScopedVector<char> program(3072);
126 SNPrintF(program, "%s", script);
127 return MakeGraph(program.start(), kFunctionName);
128 }
129
130 private:
131 Isolate* isolate_;
132 Zone* zone_;
133
134 static Local<Value> CompileRun(const char* script) {
135 v8::Local<v8::String> v8_script =
136 v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), script,
137 v8::NewStringType::kNormal)
138 .ToLocalChecked();
139 v8::Local<v8::Context> context =
140 v8::Isolate::GetCurrent()->GetCurrentContext();
141 v8::Local<v8::Script> compiled_script =
142 (v8::Script::Compile(context, v8_script).ToLocalChecked());
143 return compiled_script->Run(context).ToLocalChecked();
144 }
145 };
146
147
27 class BytecodeGraphBuilderTest : public TestWithIsolateAndZone { 148 class BytecodeGraphBuilderTest : public TestWithIsolateAndZone {
28 public: 149 public:
29 BytecodeGraphBuilderTest() : array_builder_(isolate(), zone()) {} 150 BytecodeGraphBuilderTest() : array_builder_(isolate(), zone()) {}
30 151
31 Graph* GetCompletedGraph(); 152 Graph* GetCompletedGraph();
32 153
33 Matcher<Node*> IsUndefinedConstant(); 154 Matcher<Node*> IsUndefinedConstant();
34 Matcher<Node*> IsNullConstant(); 155 Matcher<Node*> IsNullConstant();
35 Matcher<Node*> IsTheHoleConstant(); 156 Matcher<Node*> IsTheHoleConstant();
36 Matcher<Node*> IsFalseConstant(); 157 Matcher<Node*> IsFalseConstant();
37 Matcher<Node*> IsTrueConstant(); 158 Matcher<Node*> IsTrueConstant();
159 Matcher<Node*> IsIntPtrConstant(bool is32, int value);
160 Matcher<Node*> IsFeedbackVector(Node* effect, Node* control);
38 161
39 interpreter::BytecodeArrayBuilder* array_builder() { return &array_builder_; } 162 interpreter::BytecodeArrayBuilder* array_builder() { return &array_builder_; }
40 163
41 private: 164 private:
42 interpreter::BytecodeArrayBuilder array_builder_; 165 interpreter::BytecodeArrayBuilder array_builder_;
43 166
44 DISALLOW_COPY_AND_ASSIGN(BytecodeGraphBuilderTest); 167 DISALLOW_COPY_AND_ASSIGN(BytecodeGraphBuilderTest);
45 }; 168 };
46 169
47 170
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 Matcher<Node*> BytecodeGraphBuilderTest::IsFalseConstant() { 212 Matcher<Node*> BytecodeGraphBuilderTest::IsFalseConstant() {
90 return IsHeapConstant(factory()->false_value()); 213 return IsHeapConstant(factory()->false_value());
91 } 214 }
92 215
93 216
94 Matcher<Node*> BytecodeGraphBuilderTest::IsTrueConstant() { 217 Matcher<Node*> BytecodeGraphBuilderTest::IsTrueConstant() {
95 return IsHeapConstant(factory()->true_value()); 218 return IsHeapConstant(factory()->true_value());
96 } 219 }
97 220
98 221
222 Matcher<Node*> BytecodeGraphBuilderTest::IsIntPtrConstant(bool is32,
rmcilroy 2015/11/09 15:23:00 Don't pass is32 as a parameter, do in interpreter-
mythria 2015/11/10 09:55:35 Done.
223 int value) {
224 if (is32) {
225 return IsInt32Constant(value);
226 } else {
227 return IsInt64Constant(value);
228 }
229 }
230
231
232 Matcher<Node*> BytecodeGraphBuilderTest::IsFeedbackVector(Node* effect,
233 Node* control) {
234 int offset = SharedFunctionInfo::kFeedbackVectorOffset - kHeapObjectTag;
235 int offset1 = JSFunction::kSharedFunctionInfoOffset - kHeapObjectTag;
236 bool is32 = (kMachPtr == kRepWord32);
237
238 return IsLoad(kMachAnyTagged,
239 IsLoad(kMachAnyTagged,
240 IsParameter(Linkage::kJSFunctionCallClosureParamIndex),
241 IsIntPtrConstant(is32, offset1), effect, control),
242 IsIntPtrConstant(is32, offset), effect, control);
243 }
244
245
99 TEST_F(BytecodeGraphBuilderTest, ReturnUndefined) { 246 TEST_F(BytecodeGraphBuilderTest, ReturnUndefined) {
100 array_builder()->set_locals_count(0); 247 array_builder()->set_locals_count(0);
101 array_builder()->set_context_count(0); 248 array_builder()->set_context_count(0);
102 array_builder()->set_parameter_count(1); 249 array_builder()->set_parameter_count(1);
103 array_builder()->LoadUndefined().Return(); 250 array_builder()->LoadUndefined().Return();
104 251
105 Graph* graph = GetCompletedGraph(); 252 Graph* graph = GetCompletedGraph();
106 Node* end = graph->end(); 253 Node* end = graph->end();
107 EXPECT_EQ(1, end->InputCount()); 254 EXPECT_EQ(1, end->InputCount());
108 Node* ret = end->InputAt(0); 255 Node* ret = end->InputAt(0);
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 394
248 Graph* graph = GetCompletedGraph(); 395 Graph* graph = GetCompletedGraph();
249 Node* end = graph->end(); 396 Node* end = graph->end();
250 EXPECT_EQ(1, end->InputCount()); 397 EXPECT_EQ(1, end->InputCount());
251 Node* ret = end->InputAt(0); 398 Node* ret = end->InputAt(0);
252 EXPECT_THAT( 399 EXPECT_THAT(
253 ret, IsReturn(IsJSAdd(IsNumberConstant(kLeft), IsNumberConstant(kRight)), 400 ret, IsReturn(IsJSAdd(IsNumberConstant(kLeft), IsNumberConstant(kRight)),
254 _, _)); 401 _, _));
255 } 402 }
256 403
404
405 TEST_F(BytecodeGraphBuilderTest, NamedLoadSloppy) {
406 GraphGeneratorHelper helper(isolate(), zone());
407 const char* code_snippet =
408 "function f(p1) { return p1.val; }; f( { val : 10 });";
rmcilroy 2015/11/09 15:23:00 nit - /f( {/f({/ (throughout CL)
mythria 2015/11/10 09:55:35 Done.
409 Graph* graph = helper.MakeGraphForScript(code_snippet);
410
411 FeedbackVectorSpec feedback_spec(zone());
412 FeedbackVectorSlot slot = feedback_spec.AddLoadICSlot();
413 int slot_id = slot.ToInt();
rmcilroy 2015/11/09 15:23:00 You shouldn't need the slot ids now you aren't mat
mythria 2015/11/10 09:55:35 Done.
414
415 Node* end = graph->end();
416 Node* ret = end->InputAt(0);
rmcilroy 2015/11/09 15:23:00 nit - Node* ret = graph->end()->InputAt(0)
mythria 2015/11/10 09:55:35 Done.
417 Node* effect = graph->start();
418 Node* control = graph->start();
419 EXPECT_THAT(
420 ret,
421 IsReturn(
422 IsNamedLoad(IsNamedAccess(LanguageMode::SLOPPY,
423 factory()->NewStringFromStaticChars("val"),
424 slot_id),
425 IsParameter(1), IsFeedbackVector(effect, control), effect,
426 control),
427 _, _));
428 }
429
430
431 TEST_F(BytecodeGraphBuilderTest, NamedLoadStrict) {
432 GraphGeneratorHelper helper(isolate(), zone());
433 const char* code_snippet =
434 "function f(p1) { 'use strict'; return p1.val; }; f( { val : 10 });";
435 Graph* graph = helper.MakeGraphForScript(code_snippet);
436
437 FeedbackVectorSpec feedback_spec(zone());
438 FeedbackVectorSlot slot = feedback_spec.AddLoadICSlot();
439 int slot_id = slot.ToInt();
440
441 Node* end = graph->end();
442 Node* ret = end->InputAt(0);
443 Node* effect = graph->start();
444 Node* control = graph->start();
445 EXPECT_THAT(
446 ret,
447 IsReturn(
448 IsNamedLoad(IsNamedAccess(LanguageMode::STRICT,
449 factory()->NewStringFromStaticChars("val"),
450 slot_id),
451 IsParameter(1), IsFeedbackVector(effect, control), effect,
452 control),
453 _, _));
454 }
455
456
457 TEST_F(BytecodeGraphBuilderTest, NamedLoadSloppyWide) {
458 GraphGeneratorHelper helper(isolate(), zone());
459 const char code_snippet[] = "function f(p1) { var b; " REPEAT_127(
rmcilroy 2015/11/09 15:23:00 nit - could you space this so that the REPEAT_127
mythria 2015/11/10 09:55:35 Done.
460 SPACE, " b = p1.name; ") "return p1.val; }; f( { val : 10 });";
461 Graph* graph = helper.MakeGraphForScript(code_snippet);
462
463 FeedbackVectorSpec feedback_spec(zone());
464 FeedbackVectorSlot slot = feedback_spec.AddLoadICSlot();
465 int slot_id = slot.ToInt() + 127 * 2;
466
467 Node* end = graph->end();
468 Node* ret = end->InputAt(0);
469 Node* effect = graph->start();
470 Node* control = graph->start();
471 // TODO(mythria): Add effect and control for IsNamedLoad. They are no longer
472 // graph->start().
473 EXPECT_THAT(
474 ret,
475 IsReturn(
476 IsNamedLoad(IsNamedAccess(LanguageMode::SLOPPY,
477 factory()->NewStringFromStaticChars("val"),
478 slot_id),
479 IsParameter(1), IsFeedbackVector(effect, control), _, _),
480 _, _));
481 }
482
483
484 TEST_F(BytecodeGraphBuilderTest, NamedLoadStrictWide) {
485 GraphGeneratorHelper helper(isolate(), zone());
486 const char code_snippet[] =
487 "function f(p1) { 'use strict'; var b; "
488 REPEAT_127(SPACE, " b = p1.name; ")
489 "return p1.val; }; f( { val : 10 });";
490 Graph* graph = helper.MakeGraphForScript(code_snippet);
491
492 FeedbackVectorSpec feedback_spec(zone());
493 FeedbackVectorSlot slot = feedback_spec.AddLoadICSlot();
494 int slot_id = slot.ToInt() + 127 * 2;
495
496 Node* end = graph->end();
497 Node* ret = end->InputAt(0);
498 Node* effect = graph->start();
499 Node* control = graph->start();
500 // TODO(mythria): Add effect and control for IsNamedLoad. They are no longer
501 // graph->start().
502 EXPECT_THAT(
503 ret,
504 IsReturn(
505 IsNamedLoad(IsNamedAccess(LanguageMode::STRICT,
506 factory()->NewStringFromStaticChars("val"),
507 slot_id),
508 IsParameter(1), IsFeedbackVector(effect, control), _, _),
509 _, _));
510 }
511
257 } // namespace compiler 512 } // namespace compiler
258 } // namespace internal 513 } // namespace internal
259 } // namespace v8 514 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698