| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/compiler.h" | 5 #include "vm/compiler.h" |
| 6 #include "vm/dart_api_impl.h" | 6 #include "vm/dart_api_impl.h" |
| 7 #include "vm/dart_entry.h" | 7 #include "vm/dart_entry.h" |
| 8 #include "vm/flow_graph_builder.h" | 8 #include "vm/flow_graph_builder.h" |
| 9 #include "vm/intermediate_language.h" | 9 #include "vm/intermediate_language.h" |
| 10 #include "vm/unit_test.h" | 10 #include "vm/unit_test.h" |
| 11 | 11 |
| 12 namespace dart { | 12 namespace dart { |
| 13 | 13 |
| 14 #ifndef PRODUCT | 14 #ifndef PRODUCT |
| 15 | 15 |
| 16 #define DUMP_ASSERT(condition) \ | 16 #define DUMP_ASSERT(condition) \ |
| 17 if (!(condition)) { \ | 17 if (!(condition)) { \ |
| 18 dart::Expect(__FILE__, __LINE__).Fail("expected: %s", #condition); \ | 18 dart::Expect(__FILE__, __LINE__).Fail("expected: %s", #condition); \ |
| 19 THR_Print(">>> BEGIN source position table for `%s`\n", graph_name_); \ | 19 THR_Print(">>> BEGIN source position table for `%s`\n", graph_name_); \ |
| 20 Dump(); \ | 20 Dump(); \ |
| 21 THR_Print("<<< END source position table for `%s`\n", graph_name_); \ | 21 THR_Print("<<< END source position table for `%s`\n", graph_name_); \ |
| 22 OS::Abort(); \ | 22 OS::Abort(); \ |
| 23 } | 23 } |
| 24 | 24 |
| 25 class SourcePositionTest : public ValueObject { | 25 class SourcePositionTest : public ValueObject { |
| 26 public: | 26 public: |
| 27 SourcePositionTest(Thread* thread, | 27 SourcePositionTest(Thread* thread, const char* script) |
| 28 const char* script) | |
| 29 : thread_(thread), | 28 : thread_(thread), |
| 30 isolate_(thread->isolate()), | 29 isolate_(thread->isolate()), |
| 31 script_(script), | 30 script_(script), |
| 32 root_lib_(Library::Handle()), | 31 root_lib_(Library::Handle()), |
| 33 root_script_(Script::Handle()), | 32 root_script_(Script::Handle()), |
| 34 graph_(NULL), | 33 graph_(NULL), |
| 35 blocks_(NULL) { | 34 blocks_(NULL) { |
| 36 EXPECT(thread_ != NULL); | 35 EXPECT(thread_ != NULL); |
| 37 EXPECT(isolate_ != NULL); | 36 EXPECT(isolate_ != NULL); |
| 38 EXPECT(script_ != NULL); | 37 EXPECT(script_ != NULL); |
| 39 Dart_Handle lib = TestCase::LoadTestScript(script, NULL); | 38 Dart_Handle lib = TestCase::LoadTestScript(script, NULL); |
| 40 EXPECT_VALID(lib); | 39 EXPECT_VALID(lib); |
| 41 root_lib_ ^= Api::UnwrapHandle(lib); | 40 root_lib_ ^= Api::UnwrapHandle(lib); |
| 42 EXPECT(!root_lib_.IsNull()); | 41 EXPECT(!root_lib_.IsNull()); |
| 43 root_script_ ^= root_lib_.LookupScript( | 42 root_script_ ^= |
| 44 String::Handle(String::New(USER_TEST_URI))); | 43 root_lib_.LookupScript(String::Handle(String::New(USER_TEST_URI))); |
| 45 EXPECT(!root_script_.IsNull()); | 44 EXPECT(!root_script_.IsNull()); |
| 46 } | 45 } |
| 47 | 46 |
| 48 void BuildGraphFor(const char* function_name) { | 47 void BuildGraphFor(const char* function_name) { |
| 49 graph_ = NULL; | 48 graph_ = NULL; |
| 50 blocks_ = NULL; | 49 blocks_ = NULL; |
| 51 graph_name_ = NULL; | 50 graph_name_ = NULL; |
| 52 | 51 |
| 53 // Only support unoptimized code for now. | 52 // Only support unoptimized code for now. |
| 54 const bool optimized = false; | 53 const bool optimized = false; |
| 55 | 54 |
| 56 const Function& function = | 55 const Function& function = |
| 57 Function::Handle(GetFunction(root_lib_, function_name)); | 56 Function::Handle(GetFunction(root_lib_, function_name)); |
| 58 ZoneGrowableArray<const ICData*>* ic_data_array = | 57 ZoneGrowableArray<const ICData*>* ic_data_array = |
| 59 new ZoneGrowableArray<const ICData*>(); | 58 new ZoneGrowableArray<const ICData*>(); |
| 60 ParsedFunction* parsed_function = new ParsedFunction( | 59 ParsedFunction* parsed_function = |
| 61 thread_, Function::ZoneHandle(function.raw())); | 60 new ParsedFunction(thread_, Function::ZoneHandle(function.raw())); |
| 62 Parser::ParseFunction(parsed_function); | 61 Parser::ParseFunction(parsed_function); |
| 63 parsed_function->AllocateVariables(); | 62 parsed_function->AllocateVariables(); |
| 64 FlowGraphBuilder builder( | 63 FlowGraphBuilder builder(*parsed_function, *ic_data_array, NULL, |
| 65 *parsed_function, | 64 Compiler::kNoOSRDeoptId); |
| 66 *ic_data_array, | |
| 67 NULL, | |
| 68 Compiler::kNoOSRDeoptId); | |
| 69 graph_ = builder.BuildGraph(); | 65 graph_ = builder.BuildGraph(); |
| 70 EXPECT(graph_ != NULL); | 66 EXPECT(graph_ != NULL); |
| 71 blocks_ = graph_->CodegenBlockOrder(optimized); | 67 blocks_ = graph_->CodegenBlockOrder(optimized); |
| 72 EXPECT(blocks_ != NULL); | 68 EXPECT(blocks_ != NULL); |
| 73 graph_name_ = function_name; | 69 graph_name_ = function_name; |
| 74 EXPECT(graph_name_ != NULL); | 70 EXPECT(graph_name_ != NULL); |
| 75 } | 71 } |
| 76 | 72 |
| 77 // Expect to find an instance call at |line| and |column|. | 73 // Expect to find an instance call at |line| and |column|. |
| 78 void InstanceCallAt(intptr_t line, | 74 void InstanceCallAt(intptr_t line, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 91 } | 87 } |
| 92 } else { | 88 } else { |
| 93 count++; | 89 count++; |
| 94 } | 90 } |
| 95 } | 91 } |
| 96 } | 92 } |
| 97 DUMP_ASSERT(count > 0); | 93 DUMP_ASSERT(count > 0); |
| 98 } | 94 } |
| 99 | 95 |
| 100 // Expect to find an instance call at |line| and |column|. | 96 // Expect to find an instance call at |line| and |column|. |
| 101 void InstanceCallAt(const char* needle, | 97 void InstanceCallAt(const char* needle, intptr_t line, intptr_t column = -1) { |
| 102 intptr_t line, | |
| 103 intptr_t column = -1) { | |
| 104 ZoneGrowableArray<Instruction*>* instructions = | 98 ZoneGrowableArray<Instruction*>* instructions = |
| 105 FindInstructionsAt(line, column); | 99 FindInstructionsAt(line, column); |
| 106 intptr_t count = 0; | 100 intptr_t count = 0; |
| 107 for (intptr_t i = 0; i < instructions->length(); i++) { | 101 for (intptr_t i = 0; i < instructions->length(); i++) { |
| 108 Instruction* instr = instructions->At(i); | 102 Instruction* instr = instructions->At(i); |
| 109 EXPECT(instr != NULL); | 103 EXPECT(instr != NULL); |
| 110 if (instr->IsInstanceCall()) { | 104 if (instr->IsInstanceCall()) { |
| 111 const char* haystack = instr->ToCString(); | 105 const char* haystack = instr->ToCString(); |
| 112 if (strstr(haystack, needle) != NULL) { | 106 if (strstr(haystack, needle) != NULL) { |
| 113 count++; | 107 count++; |
| 114 } | 108 } |
| 115 } | 109 } |
| 116 } | 110 } |
| 117 DUMP_ASSERT(count > 0); | 111 DUMP_ASSERT(count > 0); |
| 118 } | 112 } |
| 119 | 113 |
| 120 // Expect to find at least one static call at |line| and |column|. The | 114 // Expect to find at least one static call at |line| and |column|. The |
| 121 // static call will have |needle| in its |ToCString| representation. | 115 // static call will have |needle| in its |ToCString| representation. |
| 122 void StaticCallAt(const char* needle, | 116 void StaticCallAt(const char* needle, intptr_t line, intptr_t column = -1) { |
| 123 intptr_t line, | |
| 124 intptr_t column = -1) { | |
| 125 ZoneGrowableArray<Instruction*>* instructions = | 117 ZoneGrowableArray<Instruction*>* instructions = |
| 126 FindInstructionsAt(line, column); | 118 FindInstructionsAt(line, column); |
| 127 intptr_t count = 0; | 119 intptr_t count = 0; |
| 128 for (intptr_t i = 0; i < instructions->length(); i++) { | 120 for (intptr_t i = 0; i < instructions->length(); i++) { |
| 129 Instruction* instr = instructions->At(i); | 121 Instruction* instr = instructions->At(i); |
| 130 EXPECT(instr != NULL); | 122 EXPECT(instr != NULL); |
| 131 if (instr->IsStaticCall()) { | 123 if (instr->IsStaticCall()) { |
| 132 const char* haystack = instr->ToCString(); | 124 const char* haystack = instr->ToCString(); |
| 133 if (strstr(haystack, needle) != NULL) { | 125 if (strstr(haystack, needle) != NULL) { |
| 134 count++; | 126 count++; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 synthetic = true; | 181 synthetic = true; |
| 190 token_pos = token_pos.FromSynthetic(); | 182 token_pos = token_pos.FromSynthetic(); |
| 191 } | 183 } |
| 192 if (token_pos.IsClassifying()) { | 184 if (token_pos.IsClassifying()) { |
| 193 const char* token_pos_string = token_pos.ToCString(); | 185 const char* token_pos_string = token_pos.ToCString(); |
| 194 THR_Print("%12s -- %s\n", token_pos_string, instr->ToCString()); | 186 THR_Print("%12s -- %s\n", token_pos_string, instr->ToCString()); |
| 195 return; | 187 return; |
| 196 } | 188 } |
| 197 intptr_t token_line = -1; | 189 intptr_t token_line = -1; |
| 198 intptr_t token_column = -1; | 190 intptr_t token_column = -1; |
| 199 root_script_.GetTokenLocation(token_pos, | 191 root_script_.GetTokenLocation(token_pos, &token_line, &token_column, NULL); |
| 200 &token_line, | |
| 201 &token_column, | |
| 202 NULL); | |
| 203 if (synthetic) { | 192 if (synthetic) { |
| 204 THR_Print(" *%02d:%02d -- %s\n", | 193 THR_Print(" *%02d:%02d -- %s\n", static_cast<int>(token_line), |
| 205 static_cast<int>(token_line), | 194 static_cast<int>(token_column), instr->ToCString()); |
| 206 static_cast<int>(token_column), | |
| 207 instr->ToCString()); | |
| 208 } else { | 195 } else { |
| 209 THR_Print(" %02d:%02d -- %s\n", | 196 THR_Print(" %02d:%02d -- %s\n", static_cast<int>(token_line), |
| 210 static_cast<int>(token_line), | 197 static_cast<int>(token_column), instr->ToCString()); |
| 211 static_cast<int>(token_column), | |
| 212 instr->ToCString()); | |
| 213 } | 198 } |
| 214 } | 199 } |
| 215 | 200 |
| 216 Instruction* FindFirstInstructionAt(intptr_t line, intptr_t column) { | 201 Instruction* FindFirstInstructionAt(intptr_t line, intptr_t column) { |
| 217 ZoneGrowableArray<Instruction*>* instructions = | 202 ZoneGrowableArray<Instruction*>* instructions = |
| 218 FindInstructionsAt(line, column); | 203 FindInstructionsAt(line, column); |
| 219 if (instructions->length() == 0) { | 204 if (instructions->length() == 0) { |
| 220 return NULL; | 205 return NULL; |
| 221 } | 206 } |
| 222 return instructions->At(0); | 207 return instructions->At(0); |
| 223 } | 208 } |
| 224 | 209 |
| 225 ZoneGrowableArray<Instruction*>* FindInstructionsAt( | 210 ZoneGrowableArray<Instruction*>* FindInstructionsAt(intptr_t line, |
| 226 intptr_t line, intptr_t column) { | 211 intptr_t column) { |
| 227 ZoneGrowableArray<Instruction*>* instructions = | 212 ZoneGrowableArray<Instruction*>* instructions = |
| 228 new ZoneGrowableArray<Instruction*>(); | 213 new ZoneGrowableArray<Instruction*>(); |
| 229 for (intptr_t i = 0; i < blocks_->length(); i++) { | 214 for (intptr_t i = 0; i < blocks_->length(); i++) { |
| 230 BlockEntryInstr* entry = (*blocks_)[i]; | 215 BlockEntryInstr* entry = (*blocks_)[i]; |
| 231 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { | 216 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { |
| 232 Instruction* instr = it.Current(); | 217 Instruction* instr = it.Current(); |
| 233 TokenPosition token_pos = instr->token_pos(); | 218 TokenPosition token_pos = instr->token_pos(); |
| 234 if (token_pos.IsSynthetic()) { | 219 if (token_pos.IsSynthetic()) { |
| 235 token_pos = token_pos.FromSynthetic(); | 220 token_pos = token_pos.FromSynthetic(); |
| 236 } | 221 } |
| 237 if (!token_pos.IsReal()) { | 222 if (!token_pos.IsReal()) { |
| 238 continue; | 223 continue; |
| 239 } | 224 } |
| 240 intptr_t token_line = -1; | 225 intptr_t token_line = -1; |
| 241 intptr_t token_column = -1; | 226 intptr_t token_column = -1; |
| 242 root_script_.GetTokenLocation(token_pos, | 227 root_script_.GetTokenLocation(token_pos, &token_line, &token_column, |
| 243 &token_line, | |
| 244 &token_column, | |
| 245 NULL); | 228 NULL); |
| 246 if (token_line == line) { | 229 if (token_line == line) { |
| 247 if ((column < 0) || (column == token_column)) { | 230 if ((column < 0) || (column == token_column)) { |
| 248 instructions->Add(instr); | 231 instructions->Add(instr); |
| 249 } | 232 } |
| 250 } | 233 } |
| 251 } | 234 } |
| 252 } | 235 } |
| 253 return instructions; | 236 return instructions; |
| 254 } | 237 } |
| 255 | 238 |
| 256 ZoneGrowableArray<Instruction*>* FindInstructionsAt(intptr_t token_pos) { | 239 ZoneGrowableArray<Instruction*>* FindInstructionsAt(intptr_t token_pos) { |
| 257 ZoneGrowableArray<Instruction*>* instructions = | 240 ZoneGrowableArray<Instruction*>* instructions = |
| 258 new ZoneGrowableArray<Instruction*>(); | 241 new ZoneGrowableArray<Instruction*>(); |
| 259 for (intptr_t i = 0; i < blocks_->length(); i++) { | 242 for (intptr_t i = 0; i < blocks_->length(); i++) { |
| 260 BlockEntryInstr* entry = (*blocks_)[i]; | 243 BlockEntryInstr* entry = (*blocks_)[i]; |
| 261 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { | 244 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { |
| 262 Instruction* instr = it.Current(); | 245 Instruction* instr = it.Current(); |
| 263 if (instr->token_pos().value() == token_pos) { | 246 if (instr->token_pos().value() == token_pos) { |
| 264 instructions->Add(instr); | 247 instructions->Add(instr); |
| 265 } | 248 } |
| 266 } | 249 } |
| 267 } | 250 } |
| 268 return instructions; | 251 return instructions; |
| 269 } | 252 } |
| 270 | 253 |
| 271 RawFunction* GetFunction(const Library& lib, const char* name) { | 254 RawFunction* GetFunction(const Library& lib, const char* name) { |
| 272 const Function& result = Function::Handle(lib.LookupFunctionAllowPrivate( | 255 const Function& result = Function::Handle( |
| 273 String::Handle(String::New(name)))); | 256 lib.LookupFunctionAllowPrivate(String::Handle(String::New(name)))); |
| 274 EXPECT(!result.IsNull()); | 257 EXPECT(!result.IsNull()); |
| 275 return result.raw(); | 258 return result.raw(); |
| 276 } | 259 } |
| 277 | 260 |
| 278 RawFunction* GetFunction(const Class& cls, const char* name) { | 261 RawFunction* GetFunction(const Class& cls, const char* name) { |
| 279 const Function& result = Function::Handle(cls.LookupFunctionAllowPrivate( | 262 const Function& result = Function::Handle( |
| 280 String::Handle(String::New(name)))); | 263 cls.LookupFunctionAllowPrivate(String::Handle(String::New(name)))); |
| 281 EXPECT(!result.IsNull()); | 264 EXPECT(!result.IsNull()); |
| 282 return result.raw(); | 265 return result.raw(); |
| 283 } | 266 } |
| 284 | 267 |
| 285 RawClass* GetClass(const Library& lib, const char* name) { | 268 RawClass* GetClass(const Library& lib, const char* name) { |
| 286 const Class& cls = Class::Handle( | 269 const Class& cls = Class::Handle( |
| 287 lib.LookupClass(String::Handle(Symbols::New(thread_, name)))); | 270 lib.LookupClass(String::Handle(Symbols::New(thread_, name)))); |
| 288 EXPECT(!cls.IsNull()); // No ambiguity error expected. | 271 EXPECT(!cls.IsNull()); // No ambiguity error expected. |
| 289 return cls.raw(); | 272 return cls.raw(); |
| 290 } | 273 } |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 649 SourcePositionTest spt(thread, kScript); | 632 SourcePositionTest spt(thread, kScript); |
| 650 spt.BuildGraphFor("main"); | 633 spt.BuildGraphFor("main"); |
| 651 | 634 |
| 652 spt.FuzzyInstructionMatchAt("DebugStepCheck", 3, 5); | 635 spt.FuzzyInstructionMatchAt("DebugStepCheck", 3, 5); |
| 653 spt.FuzzyInstructionMatchAt("CheckStackOverflow", 3, 5); | 636 spt.FuzzyInstructionMatchAt("CheckStackOverflow", 3, 5); |
| 654 spt.FuzzyInstructionMatchAt("Constant(#Field", 4, 11); | 637 spt.FuzzyInstructionMatchAt("Constant(#Field", 4, 11); |
| 655 spt.FuzzyInstructionMatchAt("LoadStaticField", 4, 11); | 638 spt.FuzzyInstructionMatchAt("LoadStaticField", 4, 11); |
| 656 spt.FuzzyInstructionMatchAt("StoreLocal(:switch_expr", 4, 11); | 639 spt.FuzzyInstructionMatchAt("StoreLocal(:switch_expr", 4, 11); |
| 657 | 640 |
| 658 spt.FuzzyInstructionMatchAt("Constant(#1", 5, 10); | 641 spt.FuzzyInstructionMatchAt("Constant(#1", 5, 10); |
| 659 spt.FuzzyInstructionMatchAt("LoadLocal(:switch_expr", 5, 5); // 'c' | 642 spt.FuzzyInstructionMatchAt("LoadLocal(:switch_expr", 5, 5); // 'c' |
| 660 spt.InstanceCallAt(5, 10, Token::kEQ); // '1' | 643 spt.InstanceCallAt(5, 10, Token::kEQ); // '1' |
| 661 | 644 |
| 662 spt.FuzzyInstructionMatchAt("Constant(#3", 5, 20); // '3' | 645 spt.FuzzyInstructionMatchAt("Constant(#3", 5, 20); // '3' |
| 663 spt.FuzzyInstructionMatchAt("DebugStepCheck", 5, 13); | 646 spt.FuzzyInstructionMatchAt("DebugStepCheck", 5, 13); |
| 664 spt.FuzzyInstructionMatchAt("Return", 5, 13); | 647 spt.FuzzyInstructionMatchAt("Return", 5, 13); |
| 665 | 648 |
| 666 spt.FuzzyInstructionMatchAt("Constant(#2", 6, 10); | 649 spt.FuzzyInstructionMatchAt("Constant(#2", 6, 10); |
| 667 spt.FuzzyInstructionMatchAt("LoadLocal(:switch_expr", 6, 5); // 'c' | 650 spt.FuzzyInstructionMatchAt("LoadLocal(:switch_expr", 6, 5); // 'c' |
| 668 spt.InstanceCallAt(6, 10, Token::kEQ); // '2' | 651 spt.InstanceCallAt(6, 10, Token::kEQ); // '2' |
| 669 | 652 |
| 670 spt.FuzzyInstructionMatchAt("Constant(#4", 6, 20); // '4' | 653 spt.FuzzyInstructionMatchAt("Constant(#4", 6, 20); // '4' |
| 671 spt.FuzzyInstructionMatchAt("DebugStepCheck", 6, 13); | 654 spt.FuzzyInstructionMatchAt("DebugStepCheck", 6, 13); |
| 672 spt.FuzzyInstructionMatchAt("Return", 6, 13); | 655 spt.FuzzyInstructionMatchAt("Return", 6, 13); |
| 673 | 656 |
| 674 spt.FuzzyInstructionMatchAt("Constant(#5", 7, 21); // '5' | 657 spt.FuzzyInstructionMatchAt("Constant(#5", 7, 21); // '5' |
| 675 spt.FuzzyInstructionMatchAt("DebugStepCheck", 7, 14); | 658 spt.FuzzyInstructionMatchAt("DebugStepCheck", 7, 14); |
| 676 spt.FuzzyInstructionMatchAt("Return", 7, 14); | 659 spt.FuzzyInstructionMatchAt("Return", 7, 14); |
| 677 | 660 |
| 678 spt.EnsureSourcePositions(); | 661 spt.EnsureSourcePositions(); |
| 679 } | 662 } |
| 680 | 663 |
| 681 | 664 |
| 682 TEST_CASE(SourcePosition_TryCatchFinally) { | 665 TEST_CASE(SourcePosition_TryCatchFinally) { |
| 683 const char* kScript = | 666 const char* kScript = |
| 684 "var x = 5;\n" | 667 "var x = 5;\n" |
| 685 "var y = 5;\n" | 668 "var y = 5;\n" |
| 686 "main() {\n" | 669 "main() {\n" |
| 687 " try {\n" | 670 " try {\n" |
| 688 " throw 'A';\n" | 671 " throw 'A';\n" |
| 689 " } catch (e) {\n" | 672 " } catch (e) {\n" |
| 690 " print(e);\n" | 673 " print(e);\n" |
| 691 " return 77;\n" | 674 " return 77;\n" |
| 692 " } finally {\n" | 675 " } finally {\n" |
| 693 " return 99;\n" | 676 " return 99;\n" |
| 694 " }\n" | 677 " }\n" |
| 695 "}\n"; | 678 "}\n"; |
| 696 | 679 |
| 697 SourcePositionTest spt(thread, kScript); | 680 SourcePositionTest spt(thread, kScript); |
| 698 spt.BuildGraphFor("main"); | 681 spt.BuildGraphFor("main"); |
| 699 | 682 |
| 700 spt.FuzzyInstructionMatchAt("DebugStepCheck", 3, 5); | 683 spt.FuzzyInstructionMatchAt("DebugStepCheck", 3, 5); |
| 701 spt.FuzzyInstructionMatchAt("CheckStackOverflow", 3, 5); | 684 spt.FuzzyInstructionMatchAt("CheckStackOverflow", 3, 5); |
| 702 | 685 |
| 703 spt.FuzzyInstructionMatchAt("LoadLocal(:current_context", 4, 3); // 't' | 686 spt.FuzzyInstructionMatchAt("LoadLocal(:current_context", 4, 3); // 't' |
| 704 spt.FuzzyInstructionMatchAt("StoreLocal(:saved_try_context", 4, 3); | 687 spt.FuzzyInstructionMatchAt("StoreLocal(:saved_try_context", 4, 3); |
| 705 | 688 |
| 706 spt.FuzzyInstructionMatchAt("Constant(#A", 5, 11); // 'A' | 689 spt.FuzzyInstructionMatchAt("Constant(#A", 5, 11); // 'A' |
| 707 spt.FuzzyInstructionMatchAt("Throw", 5, 5); // 't' | 690 spt.FuzzyInstructionMatchAt("Throw", 5, 5); // 't' |
| 708 | 691 |
| 709 spt.FuzzyInstructionMatchAt("LoadLocal(:saved_try_context", 6, 5); // 'c' | 692 spt.FuzzyInstructionMatchAt("LoadLocal(:saved_try_context", 6, 5); // 'c' |
| 710 spt.FuzzyInstructionMatchAt("StoreLocal(:current_context", 6, 5); // 'c' | 693 spt.FuzzyInstructionMatchAt("StoreLocal(:current_context", 6, 5); // 'c' |
| 711 spt.FuzzyInstructionMatchAt("LoadLocal(:exception_var", 6, 5); // 'c' | 694 spt.FuzzyInstructionMatchAt("LoadLocal(:exception_var", 6, 5); // 'c' |
| 712 spt.FuzzyInstructionMatchAt("StoreLocal(e", 6, 5); // 'c' | 695 spt.FuzzyInstructionMatchAt("StoreLocal(e", 6, 5); // 'c' |
| 713 | 696 |
| 714 spt.FuzzyInstructionMatchAt("LoadLocal(e", 7, 11); // 'e' | 697 spt.FuzzyInstructionMatchAt("LoadLocal(e", 7, 11); // 'e' |
| 715 | 698 |
| 716 spt.FuzzyInstructionMatchAt("StaticCall", 7, 5); // 'p' | 699 spt.FuzzyInstructionMatchAt("StaticCall", 7, 5); // 'p' |
| 717 | 700 |
| 718 spt.FuzzyInstructionMatchAt("Constant(#77", 8, 12); // '7' | 701 spt.FuzzyInstructionMatchAt("Constant(#77", 8, 12); // '7' |
| 719 spt.FuzzyInstructionMatchAt("StoreLocal(:finally_ret_val", 8, 5); // 'r' | 702 spt.FuzzyInstructionMatchAt("StoreLocal(:finally_ret_val", 8, 5); // 'r' |
| 720 | 703 |
| 721 spt.FuzzyInstructionMatchAt("Constant(#99", 10, 12); // '9' | 704 spt.FuzzyInstructionMatchAt("Constant(#99", 10, 12); // '9' |
| 722 spt.FuzzyInstructionMatchAt("Return", 10, 5); // 'r' | 705 spt.FuzzyInstructionMatchAt("Return", 10, 5); // 'r' |
| 723 | 706 |
| 724 spt.FuzzyInstructionMatchAt("LoadLocal(:saved_try_context", 9, 13); // '{' | 707 spt.FuzzyInstructionMatchAt("LoadLocal(:saved_try_context", 9, 13); // '{' |
| 725 spt.FuzzyInstructionMatchAt("StoreLocal(:current_context", 9, 13); // '{' | 708 spt.FuzzyInstructionMatchAt("StoreLocal(:current_context", 9, 13); // '{' |
| 726 | 709 |
| 727 spt.FuzzyInstructionMatchAt("Constant(#99", 10, 12); // '9' | 710 spt.FuzzyInstructionMatchAt("Constant(#99", 10, 12); // '9' |
| 728 spt.FuzzyInstructionMatchAt("Return", 10, 5); // 'r' | 711 spt.FuzzyInstructionMatchAt("Return", 10, 5); // 'r' |
| 729 | 712 |
| 730 spt.EnsureSourcePositions(); | 713 spt.EnsureSourcePositions(); |
| 731 } | 714 } |
| 732 | 715 |
| 733 | 716 |
| 734 TEST_CASE(SourcePosition_InstanceFields) { | 717 TEST_CASE(SourcePosition_InstanceFields) { |
| 735 const char* kScript = | 718 const char* kScript = |
| 736 "class A {\n" | 719 "class A {\n" |
| 737 " var x;\n" | 720 " var x;\n" |
| 738 " var y;\n" | 721 " var y;\n" |
| 739 "}\n" | 722 "}\n" |
| 740 "main() {\n" | 723 "main() {\n" |
| 741 " var z = new A();\n" | 724 " var z = new A();\n" |
| 742 " z.x = 99;\n" | 725 " z.x = 99;\n" |
| 743 " z.y = z.x;\n" | 726 " z.y = z.x;\n" |
| 744 " return z.y;\n" | 727 " return z.y;\n" |
| 745 "}\n"; | 728 "}\n"; |
| 746 | 729 |
| 747 SourcePositionTest spt(thread, kScript); | 730 SourcePositionTest spt(thread, kScript); |
| 748 spt.BuildGraphFor("main"); | 731 spt.BuildGraphFor("main"); |
| 749 spt.FuzzyInstructionMatchAt("AllocateObject(A)", 6, 15); // 'A' | 732 spt.FuzzyInstructionMatchAt("AllocateObject(A)", 6, 15); // 'A' |
| 750 spt.FuzzyInstructionMatchAt("StaticCall", 6, 15); // 'A' | 733 spt.FuzzyInstructionMatchAt("StaticCall", 6, 15); // 'A' |
| 751 spt.FuzzyInstructionMatchAt("StoreLocal(z", 6, 9); // '=' | 734 spt.FuzzyInstructionMatchAt("StoreLocal(z", 6, 9); // '=' |
| 752 spt.InstanceCallAt("set:x", 7, 5); // 'x' | 735 spt.InstanceCallAt("set:x", 7, 5); // 'x' |
| 753 spt.InstanceCallAt("get:x", 8, 11); // 'x' | 736 spt.InstanceCallAt("get:x", 8, 11); // 'x' |
| 754 spt.InstanceCallAt("set:y", 8, 5); // 'y' | 737 spt.InstanceCallAt("set:y", 8, 5); // 'y' |
| 755 | 738 |
| 756 spt.InstanceCallAt("get:y", 9, 12); // 'y' | 739 spt.InstanceCallAt("get:y", 9, 12); // 'y' |
| 757 spt.FuzzyInstructionMatchAt("DebugStepCheck", 9, 3); | 740 spt.FuzzyInstructionMatchAt("DebugStepCheck", 9, 3); |
| 758 spt.FuzzyInstructionMatchAt("Return", 9, 3); | 741 spt.FuzzyInstructionMatchAt("Return", 9, 3); |
| 759 | 742 |
| 760 spt.EnsureSourcePositions(); | 743 spt.EnsureSourcePositions(); |
| 761 } | 744 } |
| 762 | 745 |
| 763 | 746 |
| 764 TEST_CASE(SourcePosition_Async) { | 747 TEST_CASE(SourcePosition_Async) { |
| 765 const char* kScript = | 748 const char* kScript = |
| 766 "import 'dart:async';\n" | 749 "import 'dart:async';\n" |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 801 EXPECT(TokenPosition(9).ToSynthetic().IsSynthetic()); | 784 EXPECT(TokenPosition(9).ToSynthetic().IsSynthetic()); |
| 802 EXPECT(!TokenPosition(-1).FromSynthetic().IsSynthetic()); | 785 EXPECT(!TokenPosition(-1).FromSynthetic().IsSynthetic()); |
| 803 EXPECT(!TokenPosition::kNoSource.IsSynthetic()); | 786 EXPECT(!TokenPosition::kNoSource.IsSynthetic()); |
| 804 EXPECT(!TokenPosition::kLast.IsSynthetic()); | 787 EXPECT(!TokenPosition::kLast.IsSynthetic()); |
| 805 EXPECT(SyntheticRoundTripTest(TokenPosition(0))); | 788 EXPECT(SyntheticRoundTripTest(TokenPosition(0))); |
| 806 EXPECT(SyntheticRoundTripTest(TokenPosition::kMaxSource)); | 789 EXPECT(SyntheticRoundTripTest(TokenPosition::kMaxSource)); |
| 807 EXPECT(SyntheticRoundTripTest(TokenPosition::kMinSource)); | 790 EXPECT(SyntheticRoundTripTest(TokenPosition::kMinSource)); |
| 808 } | 791 } |
| 809 | 792 |
| 810 } // namespace dart | 793 } // namespace dart |
| 811 | |
| OLD | NEW |