Chromium Code Reviews| 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 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 162 DumpFunction(lib, "A", "foo"); | 162 DumpFunction(lib, "A", "foo"); |
| 163 DumpFunction(lib, "A", "bar"); | 163 DumpFunction(lib, "A", "bar"); |
| 164 DumpFunction(lib, "A", "baz"); | 164 DumpFunction(lib, "A", "baz"); |
| 165 DumpFunction(lib, "B", "bam"); | 165 DumpFunction(lib, "B", "bam"); |
| 166 } | 166 } |
| 167 | 167 |
| 168 | 168 |
| 169 const char* saved_vars = NULL; | 169 const char* saved_vars = NULL; |
| 170 | 170 |
| 171 | 171 |
| 172 char* SkipIndex(const char* input) { | |
| 173 char* output_buffer = new char[strlen(input)]; | |
| 174 char* output = output_buffer; | |
| 175 | |
| 176 while (input[0] != '\0') { | |
| 177 const char* index_pos = strstr(input, "index="); | |
| 178 if (index_pos == NULL) { | |
| 179 while (input[0] != '\0') { | |
| 180 *output++ = *input++; | |
| 181 } | |
| 182 break; | |
| 183 } | |
| 184 | |
| 185 // Copy prefix until "index=" | |
| 186 while (input < index_pos) { | |
| 187 *output++ = *input++; | |
| 188 } | |
| 189 | |
| 190 // Skip until space. | |
| 191 input += strcspn(input, " "); | |
| 192 // Skip until next non-space. | |
| 193 input += strspn(input, " "); | |
| 194 } | |
| 195 | |
| 196 output[0] = '\0'; | |
| 197 return output_buffer; | |
| 198 } | |
| 199 | |
| 200 | |
| 172 // Saves the var descriptors for all frames on the stack as a string. | 201 // Saves the var descriptors for all frames on the stack as a string. |
| 173 static void SaveVars(Dart_IsolateId isolate_id, | 202 static void SaveVars(Dart_IsolateId isolate_id, |
| 174 intptr_t bp_id, | 203 intptr_t bp_id, |
| 175 const Dart_CodeLocation& loc) { | 204 const Dart_CodeLocation& loc) { |
| 176 DebuggerStackTrace* stack = | 205 DebuggerStackTrace* stack = |
| 177 Isolate::Current()->debugger()->StackTrace(); | 206 Isolate::Current()->debugger()->StackTrace(); |
| 178 intptr_t num_frames = stack->Length(); | 207 intptr_t num_frames = stack->Length(); |
| 179 const int kBufferLen = 2048; | 208 const int kBufferLen = 2048; |
| 180 char* buffer = new char[kBufferLen]; | 209 char* buffer = new char[kBufferLen]; |
| 181 char* pos = buffer; | 210 char* pos = buffer; |
| 182 LocalVarDescriptors& var_desc = LocalVarDescriptors::Handle(); | 211 LocalVarDescriptors& var_desc = LocalVarDescriptors::Handle(); |
| 183 for (intptr_t i = 0; i < num_frames; i++) { | 212 for (intptr_t i = 0; i < num_frames; i++) { |
| 184 ActivationFrame* frame = stack->FrameAt(i); | 213 ActivationFrame* frame = stack->FrameAt(i); |
| 185 var_desc = frame->code().var_descriptors(); | 214 var_desc = frame->code().var_descriptors(); |
| 215 const char* var_str = var_desc.ToCString(); | |
| 216 char* edited_var_str = SkipIndex(var_str); | |
| 186 pos += OS::SNPrint(pos, (kBufferLen - (pos - buffer)), | 217 pos += OS::SNPrint(pos, (kBufferLen - (pos - buffer)), |
| 187 "%s\n%s", | 218 "%s\n%s", |
| 188 frame->function().ToQualifiedCString(), | 219 frame->function().ToQualifiedCString(), |
| 189 var_desc.ToCString()); | 220 (edited_var_str != NULL ? edited_var_str :var_str)); |
|
turnidge
2014/05/01 18:40:49
oops, this works but should be fixed up. will fix
| |
| 221 delete [] edited_var_str; | |
| 190 } | 222 } |
| 191 pos[0] = '\0'; | 223 pos[0] = '\0'; |
| 192 saved_vars = buffer; | 224 saved_vars = buffer; |
| 193 } | 225 } |
| 194 | 226 |
| 195 | 227 |
| 196 // Uses the debugger to pause the program and capture the variable | 228 // Uses the debugger to pause the program and capture the variable |
| 197 // descriptors for all frames on the stack. | 229 // descriptors for all frames on the stack. |
| 198 static const char* CaptureVarsAtLine(Dart_Handle lib, | 230 static const char* CaptureVarsAtLine(Dart_Handle lib, |
| 199 const char* entry, | 231 const char* entry, |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 220 "int main() {\n" | 252 "int main() {\n" |
| 221 " var value = 11;\n" | 253 " var value = 11;\n" |
| 222 " int f(var param) {\n" | 254 " int f(var param) {\n" |
| 223 " return param + value;\n" // line 4 | 255 " return param + value;\n" // line 4 |
| 224 " }\n" | 256 " }\n" |
| 225 " return f(22);\n" | 257 " return f(22);\n" |
| 226 "}\n"; | 258 "}\n"; |
| 227 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 259 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); |
| 228 EXPECT_VALID(lib); | 260 EXPECT_VALID(lib); |
| 229 EXPECT_STREQ( | 261 EXPECT_STREQ( |
| 230 // function f uses one ctx var at (0,0); doesn't save ctx. | 262 // function f uses one ctx var at (0); doesn't save ctx. |
| 231 "::.main_f\n" | 263 "::.main_f\n" |
| 232 " 0 ContextVar level=0 index=0 begin=14 end=28 name=value\n" | 264 " 0 ContextVar level=0 begin=14 end=28 name=value\n" |
| 233 " 1 StackVar scope=1 index=2 begin=16 end=28 name=param\n" | 265 " 1 StackVar scope=1 begin=16 end=28 name=param\n" |
| 234 | 266 |
| 235 // Closure call saves current context. | 267 // Closure call saves current context. |
| 236 "(dynamic, dynamic) => int.call\n" | 268 "(dynamic, dynamic) => int.call\n" |
| 237 " 0 StackVar scope=1 index=3 begin=0 end=0 name=this\n" | 269 " 0 StackVar scope=1 begin=0 end=0 name=this\n" |
| 238 " 1 SavedCurrentCtx scope=0 index=-3 begin=0 end=0" | 270 " 1 SavedCurrentCtx scope=0 begin=0 end=0" |
| 239 " name=:saved_current_context_var\n" | 271 " name=:saved_current_context_var\n" |
| 240 | 272 |
| 241 // function main uses one ctx var at (1,0); saves caller ctx. | 273 // function main uses one ctx var at (1); saves caller ctx. |
| 242 "::.main\n" | 274 "::.main\n" |
| 243 " 0 ContextLevel level=1 scope=1 begin=2 end=37\n" | 275 " 0 ContextLevel level=1 scope=1 begin=2 end=37\n" |
| 244 " 1 SavedEntryCtx scope=0 index=-4 begin=0 end=0" | 276 " 1 SavedEntryCtx scope=0 begin=0 end=0" |
| 245 " name=:saved_entry_context_var\n" | 277 " name=:saved_entry_context_var\n" |
| 246 " 2 ContextVar level=1 index=0 begin=7 end=37 name=value\n" | 278 " 2 ContextVar level=1 begin=7 end=37 name=value\n" |
| 247 " 3 StackVar scope=2 index=-3 begin=12 end=37 name=f\n", | 279 " 3 StackVar scope=2 begin=12 end=37 name=f\n", |
| 248 CaptureVarsAtLine(lib, "main", 4)); | 280 CaptureVarsAtLine(lib, "main", 4)); |
| 249 } | 281 } |
| 250 | 282 |
| 251 | 283 |
| 252 TEST_CASE(Parser_AllocateVariables_NestedCapturedVar) { | 284 TEST_CASE(Parser_AllocateVariables_NestedCapturedVar) { |
| 253 const char* kScriptChars = | 285 const char* kScriptChars = |
| 254 "int a() {\n" | 286 "int a() {\n" |
| 255 " int b() {\n" | 287 " int b() {\n" |
| 256 " var value = 11;\n" | 288 " var value = 11;\n" |
| 257 " int c() {\n" | 289 " int c() {\n" |
| 258 " return value;\n" // line 5 | 290 " return value;\n" // line 5 |
| 259 " }\n" | 291 " }\n" |
| 260 " return c();\n" | 292 " return c();\n" |
| 261 " }\n" | 293 " }\n" |
| 262 " return b();\n" | 294 " return b();\n" |
| 263 "}\n"; | 295 "}\n"; |
| 264 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 296 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); |
| 265 EXPECT_VALID(lib); | 297 EXPECT_VALID(lib); |
| 266 EXPECT_STREQ( | 298 EXPECT_STREQ( |
| 267 // Innermost function uses captured variable 'value' from middle | 299 // Innermost function uses captured variable 'value' from middle |
| 268 // function. | 300 // function. |
| 269 "::.a_b_c\n" | 301 "::.a_b_c\n" |
| 270 " 0 ContextVar level=0 index=0 begin=20 end=30 name=value\n" | 302 " 0 ContextVar level=0 begin=20 end=30 name=value\n" |
| 271 | 303 |
| 272 // Closure call saves current context. | 304 // Closure call saves current context. |
| 273 "(dynamic) => int.call\n" | 305 "(dynamic) => int.call\n" |
| 274 " 0 StackVar scope=1 index=2 begin=0 end=0 name=this\n" | 306 " 0 StackVar scope=1 begin=0 end=0 name=this\n" |
| 275 " 1 SavedCurrentCtx scope=0 index=-3 begin=0 end=0" | 307 " 1 SavedCurrentCtx scope=0 begin=0 end=0" |
| 276 " name=:saved_current_context_var\n" | 308 " name=:saved_current_context_var\n" |
| 277 | 309 |
| 278 // Middle function saves the entry context. Notice that this | 310 // Middle function saves the entry context. Notice that this |
| 279 // happens here and not in the outermost function. We always | 311 // happens here and not in the outermost function. We always |
| 280 // save the entry context at the last possible moment. | 312 // save the entry context at the last possible moment. |
| 281 "::.a_b\n" | 313 "::.a_b\n" |
| 282 " 0 ContextLevel level=1 scope=1 begin=8 end=38\n" | 314 " 0 ContextLevel level=1 scope=1 begin=8 end=38\n" |
| 283 " 1 SavedEntryCtx scope=0 index=-4 begin=0 end=0" | 315 " 1 SavedEntryCtx scope=0 begin=0 end=0" |
| 284 " name=:saved_entry_context_var\n" | 316 " name=:saved_entry_context_var\n" |
| 285 " 2 ContextVar level=1 index=0 begin=13 end=38 name=value\n" | 317 " 2 ContextVar level=1 begin=13 end=38 name=value\n" |
| 286 " 3 StackVar scope=2 index=-3 begin=18 end=38 name=c\n" | 318 " 3 StackVar scope=2 begin=18 end=38 name=c\n" |
| 287 | 319 |
| 288 // Closure call saves current context. | 320 // Closure call saves current context. |
| 289 "(dynamic) => int.call\n" | 321 "(dynamic) => int.call\n" |
| 290 " 0 StackVar scope=1 index=2 begin=0 end=0 name=this\n" | 322 " 0 StackVar scope=1 begin=0 end=0 name=this\n" |
| 291 " 1 SavedCurrentCtx scope=0 index=-3 begin=0 end=0" | 323 " 1 SavedCurrentCtx scope=0 begin=0 end=0" |
| 292 " name=:saved_current_context_var\n" | 324 " name=:saved_current_context_var\n" |
| 293 | 325 |
| 294 // Outermost function neglects to save the entry context. We | 326 // Outermost function neglects to save the entry context. We |
| 295 // don't save the entry context if the function has no captured | 327 // don't save the entry context if the function has no captured |
| 296 // variables. | 328 // variables. |
| 297 "::.a\n" | 329 "::.a\n" |
| 298 " 0 StackVar scope=2 index=-3 begin=6 end=46 name=b\n", | 330 " 0 StackVar scope=2 begin=6 end=46 name=b\n", |
| 299 CaptureVarsAtLine(lib, "a", 5)); | 331 CaptureVarsAtLine(lib, "a", 5)); |
| 300 } | 332 } |
| 301 | 333 |
| 302 | 334 |
| 303 TEST_CASE(Parser_AllocateVariables_TwoChains) { | 335 TEST_CASE(Parser_AllocateVariables_TwoChains) { |
| 304 const char* kScriptChars = | 336 const char* kScriptChars = |
| 305 "int a() {\n" | 337 "int a() {\n" |
| 306 " var value1 = 11;\n" | 338 " var value1 = 11;\n" |
| 307 " int b() {\n" | 339 " int b() {\n" |
| 308 " int aa() {\n" | 340 " int aa() {\n" |
| 309 " var value2 = 12;\n" | 341 " var value2 = 12;\n" |
| 310 " int bb() {\n" | 342 " int bb() {\n" |
| 311 " return value2;\n" // line 7 | 343 " return value2;\n" // line 7 |
| 312 " }\n" | 344 " }\n" |
| 313 " return bb();\n" | 345 " return bb();\n" |
| 314 " }\n" | 346 " }\n" |
| 315 " return value1 + aa();\n" | 347 " return value1 + aa();\n" |
| 316 " }\n" | 348 " }\n" |
| 317 " return b();\n" | 349 " return b();\n" |
| 318 "}\n"; | 350 "}\n"; |
| 319 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 351 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); |
| 320 EXPECT_VALID(lib); | 352 EXPECT_VALID(lib); |
| 321 EXPECT_STREQ( | 353 EXPECT_STREQ( |
| 322 // bb captures only value2 from aa. No others. | 354 // bb captures only value2 from aa. No others. |
| 323 "::.a_b_aa_bb\n" | 355 "::.a_b_aa_bb\n" |
| 324 " 0 ContextVar level=0 index=0 begin=32 end=42 name=value2\n" | 356 " 0 ContextVar level=0 begin=32 end=42 name=value2\n" |
| 325 | 357 |
| 326 // Closure call saves current context. | 358 // Closure call saves current context. |
| 327 "(dynamic) => int.call\n" | 359 "(dynamic) => int.call\n" |
| 328 " 0 StackVar scope=1 index=2 begin=0 end=0 name=this\n" | 360 " 0 StackVar scope=1 begin=0 end=0 name=this\n" |
| 329 " 1 SavedCurrentCtx scope=0 index=-3 begin=0 end=0" | 361 " 1 SavedCurrentCtx scope=0 begin=0 end=0" |
| 330 " name=:saved_current_context_var\n" | 362 " name=:saved_current_context_var\n" |
| 331 | 363 |
| 332 // aa shares value2. Notice that we save the entry ctx instead | 364 // aa shares value2. Notice that we save the entry ctx instead |
| 333 // of chaining from b. This keeps us from holding onto closures | 365 // of chaining from b. This keeps us from holding onto closures |
| 334 // that we would never access. | 366 // that we would never access. |
| 335 "::.a_b_aa\n" | 367 "::.a_b_aa\n" |
| 336 " 0 ContextLevel level=1 scope=1 begin=20 end=50\n" | 368 " 0 ContextLevel level=1 scope=1 begin=20 end=50\n" |
| 337 " 1 SavedEntryCtx scope=0 index=-4 begin=0 end=0" | 369 " 1 SavedEntryCtx scope=0 begin=0 end=0" |
| 338 " name=:saved_entry_context_var\n" | 370 " name=:saved_entry_context_var\n" |
| 339 " 2 ContextVar level=1 index=0 begin=25 end=50 name=value2\n" | 371 " 2 ContextVar level=1 begin=25 end=50 name=value2\n" |
| 340 " 3 StackVar scope=2 index=-3 begin=30 end=50 name=bb\n" | 372 " 3 StackVar scope=2 begin=30 end=50 name=bb\n" |
| 341 | 373 |
| 342 // Closure call saves current context. | 374 // Closure call saves current context. |
| 343 "(dynamic) => int.call\n" | 375 "(dynamic) => int.call\n" |
| 344 " 0 StackVar scope=1 index=2 begin=0 end=0 name=this\n" | 376 " 0 StackVar scope=1 begin=0 end=0 name=this\n" |
| 345 " 1 SavedCurrentCtx scope=0 index=-3 begin=0 end=0" | 377 " 1 SavedCurrentCtx scope=0 begin=0 end=0" |
| 346 " name=:saved_current_context_var\n" | 378 " name=:saved_current_context_var\n" |
| 347 | 379 |
| 348 // b captures value1 from a. | 380 // b captures value1 from a. |
| 349 "::.a_b\n" | 381 "::.a_b\n" |
| 350 " 0 ContextVar level=0 index=0 begin=14 end=60 name=value1\n" | 382 " 0 ContextVar level=0 begin=14 end=60 name=value1\n" |
| 351 " 1 StackVar scope=2 index=-3 begin=18 end=60 name=aa\n" | 383 " 1 StackVar scope=2 begin=18 end=60 name=aa\n" |
| 352 | 384 |
| 353 // Closure call saves current context. | 385 // Closure call saves current context. |
| 354 "(dynamic) => int.call\n" | 386 "(dynamic) => int.call\n" |
| 355 " 0 StackVar scope=1 index=2 begin=0 end=0 name=this\n" | 387 " 0 StackVar scope=1 begin=0 end=0 name=this\n" |
| 356 " 1 SavedCurrentCtx scope=0 index=-3 begin=0 end=0" | 388 " 1 SavedCurrentCtx scope=0 begin=0 end=0" |
| 357 " name=:saved_current_context_var\n" | 389 " name=:saved_current_context_var\n" |
| 358 | 390 |
| 359 // a shares value1, saves entry ctx. | 391 // a shares value1, saves entry ctx. |
| 360 "::.a\n" | 392 "::.a\n" |
| 361 " 0 ContextLevel level=1 scope=1 begin=2 end=68\n" | 393 " 0 ContextLevel level=1 scope=1 begin=2 end=68\n" |
| 362 " 1 SavedEntryCtx scope=0 index=-4 begin=0 end=0" | 394 " 1 SavedEntryCtx scope=0 begin=0 end=0" |
| 363 " name=:saved_entry_context_var\n" | 395 " name=:saved_entry_context_var\n" |
| 364 " 2 ContextVar level=1 index=0 begin=7 end=68 name=value1\n" | 396 " 2 ContextVar level=1 begin=7 end=68 name=value1\n" |
| 365 " 3 StackVar scope=2 index=-3 begin=12 end=68 name=b\n", | 397 " 3 StackVar scope=2 begin=12 end=68 name=b\n", |
| 366 CaptureVarsAtLine(lib, "a", 7)); | 398 CaptureVarsAtLine(lib, "a", 7)); |
| 367 } | 399 } |
| 368 | 400 |
| 369 | 401 |
| 370 TEST_CASE(Parser_AllocateVariables_Issue7681) { | 402 TEST_CASE(Parser_AllocateVariables_Issue7681) { |
| 371 // This is a distilled version of the program from Issue 7681. | 403 // This is a distilled version of the program from Issue 7681. |
| 372 // | 404 // |
| 373 // When we create the closure at line 11, we need to make sure to | 405 // When we create the closure at line 11, we need to make sure to |
| 374 // save the entry context instead of chaining to the parent context. | 406 // save the entry context instead of chaining to the parent context. |
| 375 // | 407 // |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 392 " };\n" | 424 " };\n" |
| 393 " };\n" | 425 " };\n" |
| 394 " x.onX(new Y());\n" | 426 " x.onX(new Y());\n" |
| 395 "}\n"; | 427 "}\n"; |
| 396 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 428 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); |
| 397 EXPECT_VALID(lib); | 429 EXPECT_VALID(lib); |
| 398 EXPECT_STREQ( | 430 EXPECT_STREQ( |
| 399 // This frame saves the entry context instead of chaining. Good. | 431 // This frame saves the entry context instead of chaining. Good. |
| 400 "::.doIt_<anonymous closure>\n" | 432 "::.doIt_<anonymous closure>\n" |
| 401 " 0 ContextLevel level=1 scope=1 begin=41 end=62\n" | 433 " 0 ContextLevel level=1 scope=1 begin=41 end=62\n" |
| 402 " 1 ContextVar level=1 index=0 begin=42 end=62 name=y\n" | 434 " 1 ContextVar level=1 begin=42 end=62 name=y\n" |
| 403 " 2 SavedEntryCtx scope=0 index=-3 begin=0 end=0" | 435 " 2 SavedEntryCtx scope=0 begin=0 end=0" |
| 404 " name=:saved_entry_context_var\n" | 436 " name=:saved_entry_context_var\n" |
| 405 | 437 |
| 406 // Closure call saves current context. | 438 // Closure call saves current context. |
| 407 "(dynamic, dynamic) => dynamic.call\n" | 439 "(dynamic, dynamic) => dynamic.call\n" |
| 408 " 0 StackVar scope=1 index=3 begin=0 end=0 name=this\n" | 440 " 0 StackVar scope=1 begin=0 end=0 name=this\n" |
| 409 " 1 SavedCurrentCtx scope=0 index=-3 begin=0 end=0" | 441 " 1 SavedCurrentCtx scope=0 begin=0 end=0" |
| 410 " name=:saved_current_context_var\n" | 442 " name=:saved_current_context_var\n" |
| 411 | 443 |
| 412 "X.onX\n" | 444 "X.onX\n" |
| 413 " 0 StackVar scope=1 index=3 begin=0 end=0 name=this\n" | 445 " 0 StackVar scope=1 begin=0 end=0 name=this\n" |
| 414 | 446 |
| 415 // No context is saved here since no vars are captured. | 447 // No context is saved here since no vars are captured. |
| 416 "::.doIt\n" | 448 "::.doIt\n" |
| 417 " 0 StackVar scope=2 index=-3 begin=29 end=77 name=x\n", | 449 " 0 StackVar scope=2 begin=29 end=77 name=x\n", |
| 418 CaptureVarsAtLine(lib, "doIt", 12)); | 450 CaptureVarsAtLine(lib, "doIt", 12)); |
| 419 } | 451 } |
| 420 | 452 |
| 421 | 453 |
| 422 TEST_CASE(Parser_AllocateVariables_CaptureLoopVar) { | 454 TEST_CASE(Parser_AllocateVariables_CaptureLoopVar) { |
| 423 const char* kScriptChars = | 455 const char* kScriptChars = |
| 424 "int outer() {\n" | 456 "int outer() {\n" |
| 425 " for(int i = 0; i < 1; i++) {\n" | 457 " for(int i = 0; i < 1; i++) {\n" |
| 426 " var value = 11 + i;\n" | 458 " var value = 11 + i;\n" |
| 427 " int inner() {\n" | 459 " int inner() {\n" |
| 428 " return value;\n" // line 5 | 460 " return value;\n" // line 5 |
| 429 " }\n" | 461 " }\n" |
| 430 " return inner();\n" | 462 " return inner();\n" |
| 431 " }\n" | 463 " }\n" |
| 432 "}\n"; | 464 "}\n"; |
| 433 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 465 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); |
| 434 EXPECT_VALID(lib); | 466 EXPECT_VALID(lib); |
| 435 EXPECT_STREQ( | 467 EXPECT_STREQ( |
| 436 // inner function captures variable value. That's fine. | 468 // inner function captures variable value. That's fine. |
| 437 "::.outer_inner\n" | 469 "::.outer_inner\n" |
| 438 " 0 ContextVar level=0 index=0 begin=32 end=42 name=value\n" | 470 " 0 ContextVar level=0 begin=32 end=42 name=value\n" |
| 439 | 471 |
| 440 // Closure call saves current context. | 472 // Closure call saves current context. |
| 441 "(dynamic) => int.call\n" | 473 "(dynamic) => int.call\n" |
| 442 " 0 StackVar scope=1 index=2 begin=0 end=0 name=this\n" | 474 " 0 StackVar scope=1 begin=0 end=0 name=this\n" |
| 443 " 1 SavedCurrentCtx scope=0 index=-3 begin=0 end=0" | 475 " 1 SavedCurrentCtx scope=0 begin=0 end=0" |
| 444 " name=:saved_current_context_var\n" | 476 " name=:saved_current_context_var\n" |
| 445 | 477 |
| 446 // Notice that the outer function neglects to save the entry | 478 // Notice that the outer function neglects to save the entry |
| 447 // context. This is a bug. | 479 // context. This is a bug. |
| 448 // | 480 // |
| 449 // TODO(turnidge): Fix this very soon and update this test. | 481 // TODO(turnidge): Fix this very soon and update this test. |
| 450 // | 482 // |
| 451 // https://code.google.com/p/dart/issues/detail?id=18561 | 483 // https://code.google.com/p/dart/issues/detail?id=18561 |
| 452 "::.outer\n" | 484 "::.outer\n" |
| 453 " 0 StackVar scope=3 index=-3 begin=9 end=50 name=i\n" | 485 " 0 StackVar scope=3 begin=9 end=50 name=i\n" |
| 454 " 1 ContextLevel level=1 scope=4 begin=20 end=50\n" | 486 " 1 ContextLevel level=1 scope=4 begin=20 end=50\n" |
| 455 " 2 ContextVar level=1 index=0 begin=23 end=50 name=value\n" | 487 " 2 ContextVar level=1 begin=23 end=50 name=value\n" |
| 456 " 3 StackVar scope=4 index=-4 begin=30 end=50 name=inner\n", | 488 " 3 StackVar scope=4 begin=30 end=50 name=inner\n", |
| 457 CaptureVarsAtLine(lib, "outer", 5)); | 489 CaptureVarsAtLine(lib, "outer", 5)); |
| 458 } | 490 } |
| 459 | 491 |
| 460 } // namespace dart | 492 } // namespace dart |
| OLD | NEW |