| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 | 5 |
| 6 #include "vm/ast_printer.h" | 6 #include "vm/ast_printer.h" |
| 7 #include "vm/class_finalizer.h" | 7 #include "vm/class_finalizer.h" |
| 8 #include "vm/debugger.h" | 8 #include "vm/debugger.h" |
| 9 #include "vm/longjump.h" | 9 #include "vm/longjump.h" |
| 10 #include "vm/object.h" | 10 #include "vm/object.h" |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 DumpFunction(lib, "A", "foo"); | 172 DumpFunction(lib, "A", "foo"); |
| 173 DumpFunction(lib, "A", "bar"); | 173 DumpFunction(lib, "A", "bar"); |
| 174 DumpFunction(lib, "A", "baz"); | 174 DumpFunction(lib, "A", "baz"); |
| 175 DumpFunction(lib, "B", "bam"); | 175 DumpFunction(lib, "B", "bam"); |
| 176 } | 176 } |
| 177 | 177 |
| 178 | 178 |
| 179 #ifndef PRODUCT | 179 #ifndef PRODUCT |
| 180 | 180 |
| 181 | 181 |
| 182 static const char* saved_vars = NULL; | 182 static char* saved_vars = NULL; |
| 183 | 183 |
| 184 | 184 |
| 185 static char* SkipIndex(const char* input) { | 185 static char* SkipIndex(const char* input) { |
| 186 char* output_buffer = new char[strlen(input)]; | 186 char* output_buffer = new char[strlen(input)]; |
| 187 char* output = output_buffer; | 187 char* output = output_buffer; |
| 188 | 188 |
| 189 while (input[0] != '\0') { | 189 while (input[0] != '\0') { |
| 190 const char* index_pos = strstr(input, "index="); | 190 const char* index_pos = strstr(input, "index="); |
| 191 if (index_pos == NULL) { | 191 if (index_pos == NULL) { |
| 192 while (input[0] != '\0') { | 192 while (input[0] != '\0') { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 211 } | 211 } |
| 212 | 212 |
| 213 | 213 |
| 214 // Saves the var descriptors for all frames on the stack as a string. | 214 // Saves the var descriptors for all frames on the stack as a string. |
| 215 static void SaveVars(Dart_IsolateId isolate_id, | 215 static void SaveVars(Dart_IsolateId isolate_id, |
| 216 intptr_t bp_id, | 216 intptr_t bp_id, |
| 217 const Dart_CodeLocation& loc) { | 217 const Dart_CodeLocation& loc) { |
| 218 DebuggerStackTrace* stack = Isolate::Current()->debugger()->StackTrace(); | 218 DebuggerStackTrace* stack = Isolate::Current()->debugger()->StackTrace(); |
| 219 intptr_t num_frames = stack->Length(); | 219 intptr_t num_frames = stack->Length(); |
| 220 const int kBufferLen = 2048; | 220 const int kBufferLen = 2048; |
| 221 char* buffer = new char[kBufferLen]; | 221 char* buffer = reinterpret_cast<char*>(malloc(kBufferLen)); |
| 222 char* pos = buffer; | 222 char* pos = buffer; |
| 223 LocalVarDescriptors& var_desc = LocalVarDescriptors::Handle(); | 223 LocalVarDescriptors& var_desc = LocalVarDescriptors::Handle(); |
| 224 for (intptr_t i = 0; i < num_frames; i++) { | 224 for (intptr_t i = 0; i < num_frames; i++) { |
| 225 ActivationFrame* frame = stack->FrameAt(i); | 225 ActivationFrame* frame = stack->FrameAt(i); |
| 226 var_desc = frame->code().GetLocalVarDescriptors(); | 226 var_desc = frame->code().GetLocalVarDescriptors(); |
| 227 const char* var_str = SkipIndex(var_desc.ToCString()); | 227 const char* var_str = SkipIndex(var_desc.ToCString()); |
| 228 const char* function_str = | 228 const char* function_str = |
| 229 String::Handle(frame->function().QualifiedUserVisibleName()) | 229 String::Handle(frame->function().QualifiedUserVisibleName()) |
| 230 .ToCString(); | 230 .ToCString(); |
| 231 pos += OS::SNPrint(pos, (kBufferLen - (pos - buffer)), "%s\n%s", | 231 pos += OS::SNPrint(pos, (kBufferLen - (pos - buffer)), "%s\n%s", |
| 232 function_str, var_str); | 232 function_str, var_str); |
| 233 delete[] var_str; | 233 delete[] var_str; |
| 234 } | 234 } |
| 235 pos[0] = '\0'; | 235 pos[0] = '\0'; |
| 236 if (saved_vars != NULL) { |
| 237 free(saved_vars); |
| 238 } |
| 236 saved_vars = buffer; | 239 saved_vars = buffer; |
| 237 } | 240 } |
| 238 | 241 |
| 239 | 242 |
| 240 // Uses the debugger to pause the program and capture the variable | 243 // Uses the debugger to pause the program and capture the variable |
| 241 // descriptors for all frames on the stack. | 244 // descriptors for all frames on the stack. |
| 242 static const char* CaptureVarsAtLine(Dart_Handle lib, | 245 static char* CaptureVarsAtLine(Dart_Handle lib, const char* entry, int line) { |
| 243 const char* entry, | |
| 244 int line) { | |
| 245 EXPECT(ClassFinalizer::ProcessPendingClasses()); | 246 EXPECT(ClassFinalizer::ProcessPendingClasses()); |
| 246 bool saved_flag = FLAG_show_invisible_frames; | 247 bool saved_flag = FLAG_show_invisible_frames; |
| 247 FLAG_show_invisible_frames = true; | 248 FLAG_show_invisible_frames = true; |
| 248 Dart_SetPausedEventHandler(SaveVars); | 249 Dart_SetPausedEventHandler(SaveVars); |
| 249 EXPECT_VALID(Dart_SetBreakpoint(NewString(TestCase::url()), line)); | 250 EXPECT_VALID(Dart_SetBreakpoint(NewString(TestCase::url()), line)); |
| 250 saved_vars = NULL; | 251 saved_vars = NULL; |
| 251 EXPECT_VALID(Dart_Invoke(lib, NewString(entry), 0, NULL)); | 252 EXPECT_VALID(Dart_Invoke(lib, NewString(entry), 0, NULL)); |
| 252 const char* tmp = saved_vars; | 253 char* tmp = saved_vars; |
| 253 saved_vars = NULL; | 254 saved_vars = NULL; |
| 254 FLAG_show_invisible_frames = saved_flag; | 255 FLAG_show_invisible_frames = saved_flag; |
| 255 return tmp; | 256 return tmp; |
| 256 } | 257 } |
| 257 | 258 |
| 258 | 259 |
| 259 TEST_CASE(Parser_AllocateVariables_CapturedVar) { | 260 TEST_CASE(Parser_AllocateVariables_CapturedVar) { |
| 260 const char* kScriptChars = | 261 const char* kScriptChars = |
| 261 "int main() {\n" | 262 "int main() {\n" |
| 262 " var value = 11;\n" | 263 " var value = 11;\n" |
| 263 " int f(var param) {\n" | 264 " int f(var param) {\n" |
| 264 " return param + value;\n" // line 4 | 265 " return param + value;\n" // line 4 |
| 265 " }\n" | 266 " }\n" |
| 266 " return f(22);\n" | 267 " return f(22);\n" |
| 267 "}\n"; | 268 "}\n"; |
| 268 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 269 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); |
| 269 EXPECT_VALID(lib); | 270 EXPECT_VALID(lib); |
| 271 char* vars = CaptureVarsAtLine(lib, "main", 4); |
| 270 EXPECT_STREQ( | 272 EXPECT_STREQ( |
| 271 // function f uses one ctx var at (0); doesn't save ctx. | 273 // function f uses one ctx var at (0); doesn't save ctx. |
| 272 "main.f\n" | 274 "main.f\n" |
| 273 " 0 ContextVar level=0 begin=14 end=28 name=value\n" | 275 " 0 ContextVar level=0 begin=14 end=28 name=value\n" |
| 274 " 1 StackVar scope=1 begin=16 end=28 name=param\n" | 276 " 1 StackVar scope=1 begin=16 end=28 name=param\n" |
| 275 " 2 CurrentCtx scope=0 begin=0 end=0" | 277 " 2 CurrentCtx scope=0 begin=0 end=0" |
| 276 " name=:current_context_var\n" | 278 " name=:current_context_var\n" |
| 277 | 279 |
| 278 // Closure call saves current context. | 280 // Closure call saves current context. |
| 279 "_Closure.call\n" | 281 "_Closure.call\n" |
| 280 " 0 StackVar scope=1 begin=0 end=4 name=this\n" | 282 " 0 StackVar scope=1 begin=0 end=4 name=this\n" |
| 281 " 1 CurrentCtx scope=0 begin=0 end=0" | 283 " 1 CurrentCtx scope=0 begin=0 end=0" |
| 282 " name=:current_context_var\n" | 284 " name=:current_context_var\n" |
| 283 | 285 |
| 284 // function main uses one ctx var at (1); saves caller ctx. | 286 // function main uses one ctx var at (1); saves caller ctx. |
| 285 "main\n" | 287 "main\n" |
| 286 " 0 CurrentCtx scope=0 begin=0 end=0" | 288 " 0 CurrentCtx scope=0 begin=0 end=0" |
| 287 " name=:current_context_var\n" | 289 " name=:current_context_var\n" |
| 288 " 1 ContextLevel level=1 scope=2 begin=4 end=37\n" | 290 " 1 ContextLevel level=1 scope=2 begin=4 end=37\n" |
| 289 " 2 ContextVar level=1 begin=10 end=37 name=value\n" | 291 " 2 ContextVar level=1 begin=10 end=37 name=value\n" |
| 290 " 3 StackVar scope=2 begin=12 end=37 name=f\n", | 292 " 3 StackVar scope=2 begin=12 end=37 name=f\n", |
| 291 CaptureVarsAtLine(lib, "main", 4)); | 293 vars); |
| 294 free(vars); |
| 292 } | 295 } |
| 293 | 296 |
| 294 | 297 |
| 295 TEST_CASE(Parser_AllocateVariables_NestedCapturedVar) { | 298 TEST_CASE(Parser_AllocateVariables_NestedCapturedVar) { |
| 296 const char* kScriptChars = | 299 const char* kScriptChars = |
| 297 "int a() {\n" | 300 "int a() {\n" |
| 298 " int b() {\n" | 301 " int b() {\n" |
| 299 " var value = 11;\n" | 302 " var value = 11;\n" |
| 300 " int c() {\n" | 303 " int c() {\n" |
| 301 " return value;\n" // line 5 | 304 " return value;\n" // line 5 |
| 302 " }\n" | 305 " }\n" |
| 303 " return c();\n" | 306 " return c();\n" |
| 304 " }\n" | 307 " }\n" |
| 305 " return b();\n" | 308 " return b();\n" |
| 306 "}\n"; | 309 "}\n"; |
| 307 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 310 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); |
| 308 EXPECT_VALID(lib); | 311 EXPECT_VALID(lib); |
| 312 char* vars = CaptureVarsAtLine(lib, "a", 5); |
| 309 EXPECT_STREQ( | 313 EXPECT_STREQ( |
| 310 // Innermost function uses captured variable 'value' from middle | 314 // Innermost function uses captured variable 'value' from middle |
| 311 // function. | 315 // function. |
| 312 "a.b.c\n" | 316 "a.b.c\n" |
| 313 " 0 ContextVar level=0 begin=20 end=30 name=value\n" | 317 " 0 ContextVar level=0 begin=20 end=30 name=value\n" |
| 314 " 1 CurrentCtx scope=0 begin=0 end=0" | 318 " 1 CurrentCtx scope=0 begin=0 end=0" |
| 315 " name=:current_context_var\n" | 319 " name=:current_context_var\n" |
| 316 | 320 |
| 317 // Closure call saves current context. | 321 // Closure call saves current context. |
| 318 "_Closure.call\n" | 322 "_Closure.call\n" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 336 " 1 CurrentCtx scope=0 begin=0 end=0" | 340 " 1 CurrentCtx scope=0 begin=0 end=0" |
| 337 " name=:current_context_var\n" | 341 " name=:current_context_var\n" |
| 338 | 342 |
| 339 // Outermost function neglects to save the entry context. We | 343 // Outermost function neglects to save the entry context. We |
| 340 // don't save the entry context if the function has no captured | 344 // don't save the entry context if the function has no captured |
| 341 // variables. | 345 // variables. |
| 342 "a\n" | 346 "a\n" |
| 343 " 0 CurrentCtx scope=0 begin=0 end=0" | 347 " 0 CurrentCtx scope=0 begin=0 end=0" |
| 344 " name=:current_context_var\n" | 348 " name=:current_context_var\n" |
| 345 " 1 StackVar scope=2 begin=6 end=46 name=b\n", | 349 " 1 StackVar scope=2 begin=6 end=46 name=b\n", |
| 346 CaptureVarsAtLine(lib, "a", 5)); | 350 vars); |
| 351 free(vars); |
| 347 } | 352 } |
| 348 | 353 |
| 349 | 354 |
| 350 TEST_CASE(Parser_AllocateVariables_TwoChains) { | 355 TEST_CASE(Parser_AllocateVariables_TwoChains) { |
| 351 const char* kScriptChars = | 356 const char* kScriptChars = |
| 352 "int a() {\n" | 357 "int a() {\n" |
| 353 " var value1 = 11;\n" | 358 " var value1 = 11;\n" |
| 354 " int b() {\n" | 359 " int b() {\n" |
| 355 " int aa() {\n" | 360 " int aa() {\n" |
| 356 " var value2 = 12;\n" | 361 " var value2 = 12;\n" |
| 357 " int bb() {\n" | 362 " int bb() {\n" |
| 358 " return value2;\n" // line 7 | 363 " return value2;\n" // line 7 |
| 359 " }\n" | 364 " }\n" |
| 360 " return bb();\n" | 365 " return bb();\n" |
| 361 " }\n" | 366 " }\n" |
| 362 " return value1 + aa();\n" | 367 " return value1 + aa();\n" |
| 363 " }\n" | 368 " }\n" |
| 364 " return b();\n" | 369 " return b();\n" |
| 365 "}\n"; | 370 "}\n"; |
| 366 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 371 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); |
| 367 EXPECT_VALID(lib); | 372 EXPECT_VALID(lib); |
| 368 | 373 |
| 374 char* vars = CaptureVarsAtLine(lib, "a", 7); |
| 369 EXPECT_STREQ( | 375 EXPECT_STREQ( |
| 370 // bb captures only value2 from aa. No others. | 376 // bb captures only value2 from aa. No others. |
| 371 "a.b.aa.bb\n" | 377 "a.b.aa.bb\n" |
| 372 " 0 ContextVar level=0 begin=33 end=43 name=value2\n" | 378 " 0 ContextVar level=0 begin=33 end=43 name=value2\n" |
| 373 " 1 CurrentCtx scope=0 begin=0 end=0" | 379 " 1 CurrentCtx scope=0 begin=0 end=0" |
| 374 " name=:current_context_var\n" | 380 " name=:current_context_var\n" |
| 375 | 381 |
| 376 // Closure call saves current context. | 382 // Closure call saves current context. |
| 377 "_Closure.call\n" | 383 "_Closure.call\n" |
| 378 " 0 StackVar scope=1 begin=0 end=4 name=this\n" | 384 " 0 StackVar scope=1 begin=0 end=4 name=this\n" |
| (...skipping 29 matching lines...) Expand all Loading... |
| 408 " 1 CurrentCtx scope=0 begin=0 end=0" | 414 " 1 CurrentCtx scope=0 begin=0 end=0" |
| 409 " name=:current_context_var\n" | 415 " name=:current_context_var\n" |
| 410 | 416 |
| 411 // a shares value1, saves entry ctx. | 417 // a shares value1, saves entry ctx. |
| 412 "a\n" | 418 "a\n" |
| 413 " 0 CurrentCtx scope=0 begin=0 end=0" | 419 " 0 CurrentCtx scope=0 begin=0 end=0" |
| 414 " name=:current_context_var\n" | 420 " name=:current_context_var\n" |
| 415 " 1 ContextLevel level=1 scope=2 begin=4 end=70\n" | 421 " 1 ContextLevel level=1 scope=2 begin=4 end=70\n" |
| 416 " 2 ContextVar level=1 begin=10 end=70 name=value1\n" | 422 " 2 ContextVar level=1 begin=10 end=70 name=value1\n" |
| 417 " 3 StackVar scope=2 begin=12 end=70 name=b\n", | 423 " 3 StackVar scope=2 begin=12 end=70 name=b\n", |
| 418 CaptureVarsAtLine(lib, "a", 7)); | 424 vars); |
| 425 free(vars); |
| 419 } | 426 } |
| 420 | 427 |
| 421 | 428 |
| 422 TEST_CASE(Parser_AllocateVariables_Issue7681) { | 429 TEST_CASE(Parser_AllocateVariables_Issue7681) { |
| 423 // This is a distilled version of the program from Issue 7681. | 430 // This is a distilled version of the program from Issue 7681. |
| 424 // | 431 // |
| 425 // When we create the closure at line 11, we need to make sure to | 432 // When we create the closure at line 11, we need to make sure to |
| 426 // save the entry context instead of chaining to the parent context. | 433 // save the entry context instead of chaining to the parent context. |
| 427 // | 434 // |
| 428 // This test is somewhat redundant with CapturedVarChain but | 435 // This test is somewhat redundant with CapturedVarChain but |
| (...skipping 11 matching lines...) Expand all Loading... |
| 440 " var x = new X();\n" | 447 " var x = new X();\n" |
| 441 " x.onX = (y) {\n" | 448 " x.onX = (y) {\n" |
| 442 " y.onY = () {\n" // line 12 | 449 " y.onY = () {\n" // line 12 |
| 443 " return y;\n" | 450 " return y;\n" |
| 444 " };\n" | 451 " };\n" |
| 445 " };\n" | 452 " };\n" |
| 446 " x.onX(new Y());\n" | 453 " x.onX(new Y());\n" |
| 447 "}\n"; | 454 "}\n"; |
| 448 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 455 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); |
| 449 EXPECT_VALID(lib); | 456 EXPECT_VALID(lib); |
| 457 char* vars = CaptureVarsAtLine(lib, "doIt", 12); |
| 450 EXPECT_STREQ( | 458 EXPECT_STREQ( |
| 451 // This frame saves the entry context instead of chaining. Good. | 459 // This frame saves the entry context instead of chaining. Good. |
| 452 "doIt.<anonymous closure>\n" | 460 "doIt.<anonymous closure>\n" |
| 453 " 0 ContextLevel level=1 scope=1 begin=41 end=62\n" | 461 " 0 ContextLevel level=1 scope=1 begin=41 end=62\n" |
| 454 " 1 ContextVar level=1 begin=42 end=62 name=y\n" | 462 " 1 ContextVar level=1 begin=42 end=62 name=y\n" |
| 455 " 2 CurrentCtx scope=0 begin=0 end=0" | 463 " 2 CurrentCtx scope=0 begin=0 end=0" |
| 456 " name=:current_context_var\n" | 464 " name=:current_context_var\n" |
| 457 | 465 |
| 458 // Closure call saves current context. | 466 // Closure call saves current context. |
| 459 "_Closure.call\n" | 467 "_Closure.call\n" |
| 460 " 0 StackVar scope=1 begin=0 end=4 name=this\n" | 468 " 0 StackVar scope=1 begin=0 end=4 name=this\n" |
| 461 " 1 CurrentCtx scope=0 begin=0 end=0" | 469 " 1 CurrentCtx scope=0 begin=0 end=0" |
| 462 " name=:current_context_var\n" | 470 " name=:current_context_var\n" |
| 463 | 471 |
| 464 "X.onX\n" | 472 "X.onX\n" |
| 465 " 0 StackVar scope=1 begin=0 end=0 name=this\n" | 473 " 0 StackVar scope=1 begin=0 end=0 name=this\n" |
| 466 " 1 CurrentCtx scope=0 begin=0 end=0" | 474 " 1 CurrentCtx scope=0 begin=0 end=0" |
| 467 " name=:current_context_var\n" | 475 " name=:current_context_var\n" |
| 468 | 476 |
| 469 // No context is saved here since no vars are captured. | 477 // No context is saved here since no vars are captured. |
| 470 "doIt\n" | 478 "doIt\n" |
| 471 " 0 CurrentCtx scope=0 begin=0 end=0" | 479 " 0 CurrentCtx scope=0 begin=0 end=0" |
| 472 " name=:current_context_var\n" | 480 " name=:current_context_var\n" |
| 473 " 1 StackVar scope=2 begin=35 end=77 name=x\n", | 481 " 1 StackVar scope=2 begin=35 end=77 name=x\n", |
| 474 CaptureVarsAtLine(lib, "doIt", 12)); | 482 vars); |
| 483 free(vars); |
| 475 } | 484 } |
| 476 | 485 |
| 477 | 486 |
| 478 TEST_CASE(Parser_AllocateVariables_CaptureLoopVar) { | 487 TEST_CASE(Parser_AllocateVariables_CaptureLoopVar) { |
| 479 // This test verifies that... | 488 // This test verifies that... |
| 480 // | 489 // |
| 481 // https://code.google.com/p/dart/issues/detail?id=18561 | 490 // https://code.google.com/p/dart/issues/detail?id=18561 |
| 482 // | 491 // |
| 483 // ...stays fixed. | 492 // ...stays fixed. |
| 484 const char* kScriptChars = | 493 const char* kScriptChars = |
| 485 "int outer() {\n" | 494 "int outer() {\n" |
| 486 " for(int i = 0; i < 1; i++) {\n" | 495 " for(int i = 0; i < 1; i++) {\n" |
| 487 " var value = 11 + i;\n" | 496 " var value = 11 + i;\n" |
| 488 " int inner() {\n" | 497 " int inner() {\n" |
| 489 " return value;\n" // line 5 | 498 " return value;\n" // line 5 |
| 490 " }\n" | 499 " }\n" |
| 491 " return inner();\n" | 500 " return inner();\n" |
| 492 " }\n" | 501 " }\n" |
| 493 "}\n"; | 502 "}\n"; |
| 494 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 503 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); |
| 495 EXPECT_VALID(lib); | 504 EXPECT_VALID(lib); |
| 505 char* vars = CaptureVarsAtLine(lib, "outer", 5); |
| 496 EXPECT_STREQ( | 506 EXPECT_STREQ( |
| 497 // inner function captures variable value. That's fine. | 507 // inner function captures variable value. That's fine. |
| 498 "outer.inner\n" | 508 "outer.inner\n" |
| 499 " 0 ContextVar level=0 begin=32 end=42 name=value\n" | 509 " 0 ContextVar level=0 begin=32 end=42 name=value\n" |
| 500 " 1 CurrentCtx scope=0 begin=0 end=0" | 510 " 1 CurrentCtx scope=0 begin=0 end=0" |
| 501 " name=:current_context_var\n" | 511 " name=:current_context_var\n" |
| 502 | 512 |
| 503 // Closure call saves current context. | 513 // Closure call saves current context. |
| 504 "_Closure.call\n" | 514 "_Closure.call\n" |
| 505 " 0 StackVar scope=1 begin=0 end=4 name=this\n" | 515 " 0 StackVar scope=1 begin=0 end=4 name=this\n" |
| 506 " 1 CurrentCtx scope=0 begin=0 end=0" | 516 " 1 CurrentCtx scope=0 begin=0 end=0" |
| 507 " name=:current_context_var\n" | 517 " name=:current_context_var\n" |
| 508 | 518 |
| 509 // The outer function saves the entry context, even though the | 519 // The outer function saves the entry context, even though the |
| 510 // captured variable is in a loop. Good. | 520 // captured variable is in a loop. Good. |
| 511 "outer\n" | 521 "outer\n" |
| 512 " 0 CurrentCtx scope=0 begin=0 end=0" | 522 " 0 CurrentCtx scope=0 begin=0 end=0" |
| 513 " name=:current_context_var\n" | 523 " name=:current_context_var\n" |
| 514 " 1 StackVar scope=3 begin=12 end=50 name=i\n" | 524 " 1 StackVar scope=3 begin=12 end=50 name=i\n" |
| 515 " 2 ContextLevel level=1 scope=4 begin=20 end=50\n" | 525 " 2 ContextLevel level=1 scope=4 begin=20 end=50\n" |
| 516 " 3 ContextVar level=1 begin=28 end=50 name=value\n" | 526 " 3 ContextVar level=1 begin=28 end=50 name=value\n" |
| 517 " 4 StackVar scope=4 begin=30 end=50 name=inner\n", | 527 " 4 StackVar scope=4 begin=30 end=50 name=inner\n", |
| 518 CaptureVarsAtLine(lib, "outer", 5)); | 528 vars); |
| 529 free(vars); |
| 519 } | 530 } |
| 520 | 531 |
| 521 TEST_CASE(Parser_AllocateVariables_MiddleChain) { | 532 TEST_CASE(Parser_AllocateVariables_MiddleChain) { |
| 522 const char* kScriptChars = | 533 const char* kScriptChars = |
| 523 "a() {\n" | 534 "a() {\n" |
| 524 " int x = 11;\n" | 535 " int x = 11;\n" |
| 525 " b() {\n" | 536 " b() {\n" |
| 526 " for (int i = 0; i < 1; i++) {\n" | 537 " for (int i = 0; i < 1; i++) {\n" |
| 527 " int d() {\n" | 538 " int d() {\n" |
| 528 " return i;\n" | 539 " return i;\n" |
| 529 " }\n" | 540 " }\n" |
| 530 " }\n" | 541 " }\n" |
| 531 " int c() {\n" | 542 " int c() {\n" |
| 532 " return x + 1;\n" // line 10 | 543 " return x + 1;\n" // line 10 |
| 533 " }\n" | 544 " }\n" |
| 534 " return c();\n" | 545 " return c();\n" |
| 535 " }\n" | 546 " }\n" |
| 536 " return b();\n" | 547 " return b();\n" |
| 537 "}\n"; | 548 "}\n"; |
| 538 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 549 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); |
| 539 EXPECT_VALID(lib); | 550 EXPECT_VALID(lib); |
| 551 char* vars = CaptureVarsAtLine(lib, "a", 10); |
| 540 EXPECT_STREQ( | 552 EXPECT_STREQ( |
| 541 "a.b.c\n" | 553 "a.b.c\n" |
| 542 " 0 ContextVar level=0 begin=50 end=62 name=x\n" | 554 " 0 ContextVar level=0 begin=50 end=62 name=x\n" |
| 543 " 1 CurrentCtx scope=0 begin=0 end=0" | 555 " 1 CurrentCtx scope=0 begin=0 end=0" |
| 544 " name=:current_context_var\n" | 556 " name=:current_context_var\n" |
| 545 "_Closure.call\n" | 557 "_Closure.call\n" |
| 546 " 0 StackVar scope=1 begin=0 end=4 name=this\n" | 558 " 0 StackVar scope=1 begin=0 end=4 name=this\n" |
| 547 " 1 CurrentCtx scope=0 begin=0 end=0" | 559 " 1 CurrentCtx scope=0 begin=0 end=0" |
| 548 " name=:current_context_var\n" | 560 " name=:current_context_var\n" |
| 549 | 561 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 561 " 0 StackVar scope=1 begin=0 end=4 name=this\n" | 573 " 0 StackVar scope=1 begin=0 end=4 name=this\n" |
| 562 " 1 CurrentCtx scope=0 begin=0 end=0" | 574 " 1 CurrentCtx scope=0 begin=0 end=0" |
| 563 " name=:current_context_var\n" | 575 " name=:current_context_var\n" |
| 564 | 576 |
| 565 "a\n" | 577 "a\n" |
| 566 " 0 CurrentCtx scope=0 begin=0 end=0" | 578 " 0 CurrentCtx scope=0 begin=0 end=0" |
| 567 " name=:current_context_var\n" | 579 " name=:current_context_var\n" |
| 568 " 1 ContextLevel level=1 scope=2 begin=3 end=79\n" | 580 " 1 ContextLevel level=1 scope=2 begin=3 end=79\n" |
| 569 " 2 ContextVar level=1 begin=9 end=79 name=x\n" | 581 " 2 ContextVar level=1 begin=9 end=79 name=x\n" |
| 570 " 3 StackVar scope=2 begin=11 end=79 name=b\n", | 582 " 3 StackVar scope=2 begin=11 end=79 name=b\n", |
| 571 CaptureVarsAtLine(lib, "a", 10)); | 583 vars); |
| 584 free(vars); |
| 572 } | 585 } |
| 573 | 586 |
| 574 #endif // !PRODUCT | 587 #endif // !PRODUCT |
| 575 | 588 |
| 576 } // namespace dart | 589 } // namespace dart |
| OLD | NEW |