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