| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | |
| 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. | |
| 4 | |
| 5 library dart2js.ir_tracer; | |
| 6 | |
| 7 import 'dart:async' show EventSink; | |
| 8 | |
| 9 import '../tracer.dart'; | |
| 10 import 'cps_ir_nodes.dart' as cps_ir; | |
| 11 | |
| 12 /** | |
| 13 * If true, show LetCont expressions in output. | |
| 14 */ | |
| 15 const bool IR_TRACE_LET_CONT = false; | |
| 16 | |
| 17 class IRTracer extends TracerUtil implements cps_ir.Visitor { | |
| 18 EventSink<String> output; | |
| 19 | |
| 20 IRTracer(this.output); | |
| 21 | |
| 22 visit(cps_ir.Node node) => node.accept(this); | |
| 23 | |
| 24 void traceGraph(String name, cps_ir.FunctionDefinition node) { | |
| 25 tag("cfg", () { | |
| 26 printProperty("name", name); | |
| 27 | |
| 28 names = new Names(); | |
| 29 BlockCollector builder = new BlockCollector(names); | |
| 30 builder.visit(node); | |
| 31 | |
| 32 for (Block block in builder.entries) { | |
| 33 printBlock(block, entryPoint: node); | |
| 34 } | |
| 35 for (Block block in builder.cont2block.values) { | |
| 36 printBlock(block); | |
| 37 } | |
| 38 names = null; | |
| 39 }); | |
| 40 } | |
| 41 | |
| 42 // Temporary field used during tree walk | |
| 43 Names names; | |
| 44 | |
| 45 visitFunctionDefinition(cps_ir.FunctionDefinition node) { | |
| 46 unexpectedNode(node); | |
| 47 } | |
| 48 | |
| 49 // Bodies and initializers are not visited. They contain continuations which | |
| 50 // are found by a BlockCollector, then those continuations are processed by | |
| 51 // this visitor. | |
| 52 unexpectedNode(cps_ir.Node node) { | |
| 53 throw 'The IR tracer reached an unexpected IR instruction: $node'; | |
| 54 } | |
| 55 | |
| 56 int countUses(cps_ir.Definition definition) { | |
| 57 int count = 0; | |
| 58 cps_ir.Reference ref = definition.firstRef; | |
| 59 while (ref != null) { | |
| 60 ++count; | |
| 61 ref = ref.next; | |
| 62 } | |
| 63 return count; | |
| 64 } | |
| 65 | |
| 66 /// If [entryPoint] is given, this block is an entry point. | |
| 67 printBlock(Block block, {cps_ir.FunctionDefinition entryPoint}) { | |
| 68 tag("block", () { | |
| 69 printProperty("name", block.name); | |
| 70 printProperty("from_bci", -1); | |
| 71 printProperty("to_bci", -1); | |
| 72 printProperty("predecessors", block.pred.map((n) => n.name)); | |
| 73 printProperty("successors", block.succ.map((n) => n.name)); | |
| 74 printEmptyProperty("xhandlers"); | |
| 75 printEmptyProperty("flags"); | |
| 76 tag("states", () { | |
| 77 tag("locals", () { | |
| 78 printProperty("size", 0); | |
| 79 printProperty("method", "None"); | |
| 80 }); | |
| 81 }); | |
| 82 tag("HIR", () { | |
| 83 String formatParameter(cps_ir.Parameter param) { | |
| 84 return '${names.name(param)} ${param.type}'; | |
| 85 } | |
| 86 | |
| 87 if (entryPoint != null) { | |
| 88 String thisParam = entryPoint.receiverParameter != null | |
| 89 ? formatParameter(entryPoint.receiverParameter) | |
| 90 : 'no receiver'; | |
| 91 String interceptorParam = entryPoint.interceptorParameter != null | |
| 92 ? formatParameter(entryPoint.interceptorParameter) | |
| 93 : 'no interceptor'; | |
| 94 String params = entryPoint.parameters.map(formatParameter).join(', '); | |
| 95 printStmt('x0', 'Entry ($interceptorParam) ($thisParam) ($params)'); | |
| 96 } | |
| 97 String params = block.parameters.map(formatParameter).join(', '); | |
| 98 printStmt('x0', 'Parameters ($params)'); | |
| 99 visit(block.body); | |
| 100 }); | |
| 101 }); | |
| 102 } | |
| 103 | |
| 104 void printStmt(String resultVar, String contents) { | |
| 105 int bci = 0; | |
| 106 int uses = 0; | |
| 107 addIndent(); | |
| 108 add("$bci $uses $resultVar $contents <|@\n"); | |
| 109 } | |
| 110 | |
| 111 visitLetPrim(cps_ir.LetPrim node) { | |
| 112 String id = names.name(node.primitive); | |
| 113 String primitive = visit(node.primitive); | |
| 114 printStmt(id, "LetPrim $id = $primitive [type=${node.primitive.type}]"); | |
| 115 visit(node.body); | |
| 116 } | |
| 117 | |
| 118 visitLetCont(cps_ir.LetCont node) { | |
| 119 if (IR_TRACE_LET_CONT) { | |
| 120 String dummy = names.name(node); | |
| 121 | |
| 122 String nameContinuation(cps_ir.Continuation cont) { | |
| 123 String name = names.name(cont); | |
| 124 return cont.isRecursive ? '$name*' : name; | |
| 125 } | |
| 126 | |
| 127 String ids = node.continuations.map(nameContinuation).join(', '); | |
| 128 printStmt(dummy, "LetCont $ids"); | |
| 129 } | |
| 130 visit(node.body); | |
| 131 } | |
| 132 | |
| 133 visitLetHandler(cps_ir.LetHandler node) { | |
| 134 if (IR_TRACE_LET_CONT) { | |
| 135 String dummy = names.name(node); | |
| 136 String id = names.name(node.handler); | |
| 137 printStmt(dummy, "LetHandler $id = <$id>"); | |
| 138 } | |
| 139 visit(node.body); | |
| 140 } | |
| 141 | |
| 142 visitLetMutable(cps_ir.LetMutable node) { | |
| 143 String id = names.name(node.variable); | |
| 144 printStmt(id, "LetMutable $id = ${formatReference(node.valueRef)}"); | |
| 145 visit(node.body); | |
| 146 } | |
| 147 | |
| 148 visitInvokeStatic(cps_ir.InvokeStatic node) { | |
| 149 String callName = node.selector.name; | |
| 150 String args = node.argumentRefs.map(formatReference).join(', '); | |
| 151 return "InvokeStatic $callName ($args)"; | |
| 152 } | |
| 153 | |
| 154 visitInvokeMethod(cps_ir.InvokeMethod node) { | |
| 155 String receiver = formatReference(node.receiverRef); | |
| 156 String callName = node.selector.name; | |
| 157 String args = node.argumentRefs.map(formatReference).join(', '); | |
| 158 return "InvokeMethod $receiver $callName ($args)"; | |
| 159 } | |
| 160 | |
| 161 visitInvokeMethodDirectly(cps_ir.InvokeMethodDirectly node) { | |
| 162 String receiver = formatReference(node.receiverRef); | |
| 163 String callName = node.selector.name; | |
| 164 String args = node.argumentRefs.map(formatReference).join(', '); | |
| 165 return "InvokeMethodDirectly $receiver $callName ($args)"; | |
| 166 } | |
| 167 | |
| 168 visitInvokeConstructor(cps_ir.InvokeConstructor node) { | |
| 169 String className = node.target.enclosingClass.name; | |
| 170 String callName; | |
| 171 if (node.target.name.isEmpty) { | |
| 172 callName = '${className}'; | |
| 173 } else { | |
| 174 callName = '${className}.${node.target.name}'; | |
| 175 } | |
| 176 String args = node.argumentRefs.map(formatReference).join(', '); | |
| 177 return "InvokeConstructor $callName ($args)"; | |
| 178 } | |
| 179 | |
| 180 visitThrow(cps_ir.Throw node) { | |
| 181 String dummy = names.name(node); | |
| 182 String value = formatReference(node.valueRef); | |
| 183 printStmt(dummy, "Throw $value"); | |
| 184 } | |
| 185 | |
| 186 visitRethrow(cps_ir.Rethrow node) { | |
| 187 String dummy = names.name(node); | |
| 188 printStmt(dummy, "Rethrow"); | |
| 189 } | |
| 190 | |
| 191 visitUnreachable(cps_ir.Unreachable node) { | |
| 192 String dummy = names.name(node); | |
| 193 printStmt(dummy, 'Unreachable'); | |
| 194 } | |
| 195 | |
| 196 visitLiteralList(cps_ir.LiteralList node) { | |
| 197 String values = node.valueRefs.map(formatReference).join(', '); | |
| 198 return "LiteralList ($values)"; | |
| 199 } | |
| 200 | |
| 201 visitTypeCast(cps_ir.TypeCast node) { | |
| 202 String value = formatReference(node.valueRef); | |
| 203 String args = node.typeArgumentRefs.map(formatReference).join(', '); | |
| 204 return "TypeCast ($value ${node.dartType} ($args))"; | |
| 205 } | |
| 206 | |
| 207 visitInvokeContinuation(cps_ir.InvokeContinuation node) { | |
| 208 String dummy = names.name(node); | |
| 209 String kont = formatReference(node.continuationRef); | |
| 210 String args = node.argumentRefs.map(formatReference).join(', '); | |
| 211 printStmt(dummy, "InvokeContinuation $kont ($args)"); | |
| 212 } | |
| 213 | |
| 214 visitBranch(cps_ir.Branch node) { | |
| 215 String dummy = names.name(node); | |
| 216 String condition = formatReference(node.conditionRef); | |
| 217 String trueCont = formatReference(node.trueContinuationRef); | |
| 218 String falseCont = formatReference(node.falseContinuationRef); | |
| 219 String strict = node.isStrictCheck ? "Strict" : "NonStrict"; | |
| 220 printStmt(dummy, "Branch $condition ($trueCont, $falseCont) $strict"); | |
| 221 } | |
| 222 | |
| 223 visitAwait(cps_ir.Await node) { | |
| 224 String value = formatReference(node.inputRef); | |
| 225 return 'Await $value'; | |
| 226 } | |
| 227 | |
| 228 visitYield(cps_ir.Yield node) { | |
| 229 String name = node.hasStar ? 'YieldStar' : 'Yield'; | |
| 230 String value = formatReference(node.inputRef); | |
| 231 return '$name $value'; | |
| 232 } | |
| 233 | |
| 234 visitSetMutable(cps_ir.SetMutable node) { | |
| 235 String variable = names.name(node.variable); | |
| 236 String value = formatReference(node.valueRef); | |
| 237 return 'SetMutable $variable := $value'; | |
| 238 } | |
| 239 | |
| 240 String formatReference(cps_ir.Reference ref) { | |
| 241 if (ref == null) return 'null'; | |
| 242 cps_ir.Definition target = ref.definition; | |
| 243 if (target is cps_ir.Continuation && target.isReturnContinuation) { | |
| 244 return "return"; // Do not generate a name for the return continuation | |
| 245 } else { | |
| 246 return names.name(ref.definition); | |
| 247 } | |
| 248 } | |
| 249 | |
| 250 visitConstant(cps_ir.Constant node) { | |
| 251 return "Constant ${node.value.toStructuredText()}"; | |
| 252 } | |
| 253 | |
| 254 visitParameter(cps_ir.Parameter node) { | |
| 255 return "Parameter ${names.name(node)}"; | |
| 256 } | |
| 257 | |
| 258 visitMutableVariable(cps_ir.MutableVariable node) { | |
| 259 return "MutableVariable ${names.name(node)}"; | |
| 260 } | |
| 261 | |
| 262 visitContinuation(cps_ir.Continuation node) { | |
| 263 return "Continuation ${names.name(node)}"; | |
| 264 } | |
| 265 | |
| 266 visitSetField(cps_ir.SetField node) { | |
| 267 String object = formatReference(node.objectRef); | |
| 268 String field = node.field.name; | |
| 269 String value = formatReference(node.valueRef); | |
| 270 return 'SetField $object.$field = $value'; | |
| 271 } | |
| 272 | |
| 273 visitGetField(cps_ir.GetField node) { | |
| 274 String object = formatReference(node.objectRef); | |
| 275 String field = node.field.name; | |
| 276 String finalFlag = node.isFinal ? 'final' : 'non-final'; | |
| 277 return 'GetField $object.$field $finalFlag'; | |
| 278 } | |
| 279 | |
| 280 visitGetStatic(cps_ir.GetStatic node) { | |
| 281 String element = node.element.name; | |
| 282 String finalFlag = node.isFinal ? 'final' : 'non-final'; | |
| 283 return 'GetStatic $element $finalFlag'; | |
| 284 } | |
| 285 | |
| 286 visitSetStatic(cps_ir.SetStatic node) { | |
| 287 String element = node.element.name; | |
| 288 String value = formatReference(node.valueRef); | |
| 289 return 'SetStatic $element = $value'; | |
| 290 } | |
| 291 | |
| 292 visitGetLazyStatic(cps_ir.GetLazyStatic node) { | |
| 293 String element = node.element.name; | |
| 294 String finalFlag = node.isFinal ? 'final' : 'non-final'; | |
| 295 return "GetLazyStatic $element $finalFlag"; | |
| 296 } | |
| 297 | |
| 298 visitCreateBox(cps_ir.CreateBox node) { | |
| 299 return 'CreateBox'; | |
| 300 } | |
| 301 | |
| 302 visitCreateInstance(cps_ir.CreateInstance node) { | |
| 303 String className = node.classElement.name; | |
| 304 String arguments = node.argumentRefs.map(formatReference).join(', '); | |
| 305 String typeInformation = formatReference(node.typeInformationRef); | |
| 306 return 'CreateInstance $className ($arguments) <$typeInformation>'; | |
| 307 } | |
| 308 | |
| 309 visitInterceptor(cps_ir.Interceptor node) { | |
| 310 return 'Interceptor(${formatReference(node.inputRef)}, ' | |
| 311 '${node.interceptedClasses})'; | |
| 312 } | |
| 313 | |
| 314 visitGetMutable(cps_ir.GetMutable node) { | |
| 315 String variable = names.name(node.variable); | |
| 316 return 'GetMutable $variable'; | |
| 317 } | |
| 318 | |
| 319 visitReadTypeVariable(cps_ir.ReadTypeVariable node) { | |
| 320 return "ReadTypeVariable ${node.variable.element} " | |
| 321 "${formatReference(node.targetRef)}"; | |
| 322 } | |
| 323 | |
| 324 visitReifyRuntimeType(cps_ir.ReifyRuntimeType node) { | |
| 325 return "ReifyRuntimeType ${formatReference(node.valueRef)}"; | |
| 326 } | |
| 327 | |
| 328 visitTypeExpression(cps_ir.TypeExpression node) { | |
| 329 return "TypeExpression ${node.kindAsString} ${node.dartType}" | |
| 330 "${node.argumentRefs.map(formatReference).join(', ')}"; | |
| 331 } | |
| 332 | |
| 333 visitCreateInvocationMirror(cps_ir.CreateInvocationMirror node) { | |
| 334 String args = node.argumentRefs.map(formatReference).join(', '); | |
| 335 return "CreateInvocationMirror(${node.selector.name}, $args)"; | |
| 336 } | |
| 337 | |
| 338 visitTypeTest(cps_ir.TypeTest node) { | |
| 339 String value = formatReference(node.valueRef); | |
| 340 String args = node.typeArgumentRefs.map(formatReference).join(', '); | |
| 341 return "TypeTest ($value ${node.dartType} ($args))"; | |
| 342 } | |
| 343 | |
| 344 visitTypeTestViaFlag(cps_ir.TypeTestViaFlag node) { | |
| 345 String interceptor = formatReference(node.interceptorRef); | |
| 346 return "TypeTestViaFlag ($interceptor ${node.dartType})"; | |
| 347 } | |
| 348 | |
| 349 visitApplyBuiltinOperator(cps_ir.ApplyBuiltinOperator node) { | |
| 350 String operator = node.operator.toString(); | |
| 351 String args = node.argumentRefs.map(formatReference).join(', '); | |
| 352 return 'ApplyBuiltinOperator $operator ($args)'; | |
| 353 } | |
| 354 | |
| 355 visitApplyBuiltinMethod(cps_ir.ApplyBuiltinMethod node) { | |
| 356 String method = node.method.toString(); | |
| 357 String receiver = formatReference(node.receiverRef); | |
| 358 String args = node.argumentRefs.map(formatReference).join(', '); | |
| 359 return 'ApplyBuiltinMethod $method $receiver ($args)'; | |
| 360 } | |
| 361 | |
| 362 visitForeignCode(cps_ir.ForeignCode node) { | |
| 363 String id = names.name(node); | |
| 364 String arguments = node.argumentRefs.map(formatReference).join(', '); | |
| 365 printStmt( | |
| 366 id, "ForeignCode ${node.type} ${node.codeTemplate.source} $arguments"); | |
| 367 } | |
| 368 | |
| 369 visitGetLength(cps_ir.GetLength node) { | |
| 370 String object = formatReference(node.objectRef); | |
| 371 String finalFlag = node.isFinal ? 'final' : 'non-final'; | |
| 372 return 'GetLength $object $finalFlag'; | |
| 373 } | |
| 374 | |
| 375 visitGetIndex(cps_ir.GetIndex node) { | |
| 376 String object = formatReference(node.objectRef); | |
| 377 String index = formatReference(node.indexRef); | |
| 378 return 'GetIndex $object $index'; | |
| 379 } | |
| 380 | |
| 381 visitSetIndex(cps_ir.SetIndex node) { | |
| 382 String object = formatReference(node.objectRef); | |
| 383 String index = formatReference(node.indexRef); | |
| 384 String value = formatReference(node.valueRef); | |
| 385 return 'SetIndex $object $index $value'; | |
| 386 } | |
| 387 | |
| 388 visitRefinement(cps_ir.Refinement node) { | |
| 389 String value = formatReference(node.value); | |
| 390 return 'Refinement $value ${node.refineType}'; | |
| 391 } | |
| 392 | |
| 393 visitBoundsCheck(cps_ir.BoundsCheck node) { | |
| 394 String object = formatReference(node.objectRef); | |
| 395 String index = | |
| 396 node.indexRef == null ? 'no-index' : formatReference(node.indexRef); | |
| 397 String length = | |
| 398 node.lengthRef == null ? 'no-length' : formatReference(node.lengthRef); | |
| 399 return 'BoundsCheck $object $index $length ${node.checkString}'; | |
| 400 } | |
| 401 | |
| 402 visitReceiverCheck(cps_ir.ReceiverCheck node) { | |
| 403 String value = formatReference(node.valueRef); | |
| 404 String condition = formatReference(node.conditionRef); | |
| 405 return 'ReceiverCheck $value $condition ${node.selector} ' | |
| 406 '${node.flagString}'; | |
| 407 } | |
| 408 } | |
| 409 | |
| 410 /** | |
| 411 * Invents (and remembers) names for Continuations, Parameters, etc. | |
| 412 * The names must match the conventions used by IR Hydra, e.g. | |
| 413 * Continuations and Functions must have names of form B### since they | |
| 414 * are visualized as basic blocks. | |
| 415 */ | |
| 416 class Names { | |
| 417 final Map<Object, String> names = {}; | |
| 418 final Map<String, int> counters = {'r': 0, 'B': 0, 'v': 0, 'x': 0, 'c': 0}; | |
| 419 | |
| 420 String prefix(x) { | |
| 421 if (x is cps_ir.Parameter) return 'r'; | |
| 422 if (x is cps_ir.Continuation || x is cps_ir.FunctionDefinition) return 'B'; | |
| 423 if (x is cps_ir.Primitive) return 'v'; | |
| 424 if (x is cps_ir.MutableVariable) return 'c'; | |
| 425 return 'x'; | |
| 426 } | |
| 427 | |
| 428 String name(x) { | |
| 429 String nam = names[x]; | |
| 430 if (nam == null) { | |
| 431 String pref = prefix(x); | |
| 432 int id = counters[pref]++; | |
| 433 nam = names[x] = '${pref}${id}'; | |
| 434 } | |
| 435 return nam; | |
| 436 } | |
| 437 } | |
| 438 | |
| 439 /** | |
| 440 * A vertex in the graph visualization, used in place of basic blocks. | |
| 441 */ | |
| 442 class Block { | |
| 443 String name; | |
| 444 final List<cps_ir.Parameter> parameters; | |
| 445 final cps_ir.Expression body; | |
| 446 final List<Block> succ = <Block>[]; | |
| 447 final List<Block> pred = <Block>[]; | |
| 448 | |
| 449 Block(this.name, this.parameters, this.body); | |
| 450 | |
| 451 void addEdgeTo(Block successor) { | |
| 452 succ.add(successor); | |
| 453 successor.pred.add(this); | |
| 454 } | |
| 455 } | |
| 456 | |
| 457 class BlockCollector implements cps_ir.Visitor { | |
| 458 final Map<cps_ir.Continuation, Block> cont2block = | |
| 459 <cps_ir.Continuation, Block>{}; | |
| 460 final Set<Block> entries = new Set<Block>(); | |
| 461 Block currentBlock; | |
| 462 | |
| 463 Names names; | |
| 464 BlockCollector(this.names); | |
| 465 | |
| 466 Block getBlock(cps_ir.Continuation c) { | |
| 467 Block block = cont2block[c]; | |
| 468 if (block == null) { | |
| 469 block = new Block(names.name(c), c.parameters, c.body); | |
| 470 cont2block[c] = block; | |
| 471 } | |
| 472 return block; | |
| 473 } | |
| 474 | |
| 475 visit(cps_ir.Node node) => node.accept(this); | |
| 476 | |
| 477 visitFunctionDefinition(cps_ir.FunctionDefinition node) { | |
| 478 currentBlock = new Block(names.name(node), [], node.body); | |
| 479 entries.add(currentBlock); | |
| 480 visit(node.body); | |
| 481 } | |
| 482 | |
| 483 visitLetPrim(cps_ir.LetPrim exp) { | |
| 484 visit(exp.body); | |
| 485 } | |
| 486 | |
| 487 visitLetCont(cps_ir.LetCont exp) { | |
| 488 exp.continuations.forEach(visit); | |
| 489 visit(exp.body); | |
| 490 } | |
| 491 | |
| 492 visitLetHandler(cps_ir.LetHandler exp) { | |
| 493 visit(exp.handler); | |
| 494 visit(exp.body); | |
| 495 } | |
| 496 | |
| 497 visitLetMutable(cps_ir.LetMutable exp) { | |
| 498 visit(exp.body); | |
| 499 } | |
| 500 | |
| 501 void addEdgeToContinuation(cps_ir.Reference continuation) { | |
| 502 cps_ir.Definition target = continuation.definition; | |
| 503 if (target is cps_ir.Continuation && !target.isReturnContinuation) { | |
| 504 currentBlock.addEdgeTo(getBlock(target)); | |
| 505 } | |
| 506 } | |
| 507 | |
| 508 visitInvokeContinuation(cps_ir.InvokeContinuation exp) { | |
| 509 addEdgeToContinuation(exp.continuationRef); | |
| 510 } | |
| 511 | |
| 512 visitInvokeStatic(cps_ir.InvokeStatic node) { | |
| 513 unexpectedNode(node); | |
| 514 } | |
| 515 | |
| 516 visitInvokeMethod(cps_ir.InvokeMethod node) { | |
| 517 unexpectedNode(node); | |
| 518 } | |
| 519 | |
| 520 visitInvokeMethodDirectly(cps_ir.InvokeMethodDirectly node) { | |
| 521 unexpectedNode(node); | |
| 522 } | |
| 523 | |
| 524 visitInvokeConstructor(cps_ir.InvokeConstructor node) { | |
| 525 unexpectedNode(node); | |
| 526 } | |
| 527 | |
| 528 visitThrow(cps_ir.Throw exp) {} | |
| 529 | |
| 530 visitRethrow(cps_ir.Rethrow exp) {} | |
| 531 | |
| 532 visitUnreachable(cps_ir.Unreachable node) {} | |
| 533 | |
| 534 visitGetLazyStatic(cps_ir.GetLazyStatic node) { | |
| 535 unexpectedNode(node); | |
| 536 } | |
| 537 | |
| 538 visitBranch(cps_ir.Branch exp) { | |
| 539 cps_ir.Continuation trueTarget = exp.trueContinuation; | |
| 540 if (!trueTarget.isReturnContinuation) { | |
| 541 currentBlock.addEdgeTo(getBlock(trueTarget)); | |
| 542 } | |
| 543 cps_ir.Continuation falseTarget = exp.falseContinuation; | |
| 544 if (!falseTarget.isReturnContinuation) { | |
| 545 currentBlock.addEdgeTo(getBlock(falseTarget)); | |
| 546 } | |
| 547 } | |
| 548 | |
| 549 visitTypeCast(cps_ir.TypeCast node) { | |
| 550 unexpectedNode(node); | |
| 551 } | |
| 552 | |
| 553 visitContinuation(cps_ir.Continuation c) { | |
| 554 var old_node = currentBlock; | |
| 555 currentBlock = getBlock(c); | |
| 556 visit(c.body); | |
| 557 currentBlock = old_node; | |
| 558 } | |
| 559 | |
| 560 // Primitives and conditions are not visited when searching for blocks. | |
| 561 unexpectedNode(cps_ir.Node node) { | |
| 562 throw "The IR tracer's block collector reached an unexpected IR " | |
| 563 "instruction: $node"; | |
| 564 } | |
| 565 | |
| 566 visitLiteralList(cps_ir.LiteralList node) { | |
| 567 unexpectedNode(node); | |
| 568 } | |
| 569 | |
| 570 visitConstant(cps_ir.Constant node) { | |
| 571 unexpectedNode(node); | |
| 572 } | |
| 573 | |
| 574 visitGetMutable(cps_ir.GetMutable node) { | |
| 575 unexpectedNode(node); | |
| 576 } | |
| 577 | |
| 578 visitParameter(cps_ir.Parameter node) { | |
| 579 unexpectedNode(node); | |
| 580 } | |
| 581 | |
| 582 visitMutableVariable(cps_ir.MutableVariable node) { | |
| 583 unexpectedNode(node); | |
| 584 } | |
| 585 | |
| 586 visitGetField(cps_ir.GetField node) { | |
| 587 unexpectedNode(node); | |
| 588 } | |
| 589 | |
| 590 visitGetStatic(cps_ir.GetStatic node) { | |
| 591 unexpectedNode(node); | |
| 592 } | |
| 593 | |
| 594 visitCreateBox(cps_ir.CreateBox node) { | |
| 595 unexpectedNode(node); | |
| 596 } | |
| 597 | |
| 598 visitCreateInstance(cps_ir.CreateInstance node) { | |
| 599 unexpectedNode(node); | |
| 600 } | |
| 601 | |
| 602 visitInterceptor(cps_ir.Interceptor node) { | |
| 603 unexpectedNode(node); | |
| 604 } | |
| 605 | |
| 606 visitReadTypeVariable(cps_ir.ReadTypeVariable node) { | |
| 607 unexpectedNode(node); | |
| 608 } | |
| 609 | |
| 610 visitReifyRuntimeType(cps_ir.ReifyRuntimeType node) { | |
| 611 unexpectedNode(node); | |
| 612 } | |
| 613 | |
| 614 visitTypeExpression(cps_ir.TypeExpression node) { | |
| 615 unexpectedNode(node); | |
| 616 } | |
| 617 | |
| 618 visitCreateInvocationMirror(cps_ir.CreateInvocationMirror node) { | |
| 619 unexpectedNode(node); | |
| 620 } | |
| 621 | |
| 622 visitTypeTest(cps_ir.TypeTest node) { | |
| 623 unexpectedNode(node); | |
| 624 } | |
| 625 | |
| 626 visitTypeTestViaFlag(cps_ir.TypeTestViaFlag node) { | |
| 627 unexpectedNode(node); | |
| 628 } | |
| 629 | |
| 630 visitApplyBuiltinOperator(cps_ir.ApplyBuiltinOperator node) { | |
| 631 unexpectedNode(node); | |
| 632 } | |
| 633 | |
| 634 visitApplyBuiltinMethod(cps_ir.ApplyBuiltinMethod node) { | |
| 635 unexpectedNode(node); | |
| 636 } | |
| 637 | |
| 638 visitGetLength(cps_ir.GetLength node) { | |
| 639 unexpectedNode(node); | |
| 640 } | |
| 641 | |
| 642 visitGetIndex(cps_ir.GetIndex node) { | |
| 643 unexpectedNode(node); | |
| 644 } | |
| 645 | |
| 646 visitSetIndex(cps_ir.SetIndex node) { | |
| 647 unexpectedNode(node); | |
| 648 } | |
| 649 | |
| 650 visitSetMutable(cps_ir.SetMutable node) { | |
| 651 unexpectedNode(node); | |
| 652 } | |
| 653 | |
| 654 visitSetField(cps_ir.SetField node) { | |
| 655 unexpectedNode(node); | |
| 656 } | |
| 657 | |
| 658 visitSetStatic(cps_ir.SetStatic node) { | |
| 659 unexpectedNode(node); | |
| 660 } | |
| 661 | |
| 662 visitForeignCode(cps_ir.ForeignCode node) { | |
| 663 unexpectedNode(node); | |
| 664 } | |
| 665 | |
| 666 visitAwait(cps_ir.Await node) { | |
| 667 unexpectedNode(node); | |
| 668 } | |
| 669 | |
| 670 visitYield(cps_ir.Yield node) { | |
| 671 unexpectedNode(node); | |
| 672 } | |
| 673 | |
| 674 visitRefinement(cps_ir.Refinement node) { | |
| 675 unexpectedNode(node); | |
| 676 } | |
| 677 | |
| 678 visitBoundsCheck(cps_ir.BoundsCheck node) { | |
| 679 unexpectedNode(node); | |
| 680 } | |
| 681 | |
| 682 visitReceiverCheck(cps_ir.ReceiverCheck node) { | |
| 683 unexpectedNode(node); | |
| 684 } | |
| 685 } | |
| OLD | NEW |