| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 library ssa.tracer; | 5 library ssa.tracer; |
| 6 | 6 |
| 7 import 'dart:async' show EventSink; | 7 import 'dart:async' show EventSink; |
| 8 | 8 |
| 9 import '../compiler.dart' show Compiler; | 9 import '../compiler.dart' show Compiler; |
| 10 import '../diagnostics/invariant.dart' show DEBUG_MODE; | 10 import '../diagnostics/invariant.dart' show DEBUG_MODE; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 } else { | 52 } else { |
| 53 addIndent(); | 53 addIndent(); |
| 54 add("successors"); | 54 add("successors"); |
| 55 for (HBasicBlock successor in block.successors) { | 55 for (HBasicBlock successor in block.successors) { |
| 56 add(' "B${successor.id}"'); | 56 add(' "B${successor.id}"'); |
| 57 } | 57 } |
| 58 add("\n"); | 58 add("\n"); |
| 59 } | 59 } |
| 60 } | 60 } |
| 61 | 61 |
| 62 void addInstructions(HInstructionStringifier stringifier, | 62 void addInstructions( |
| 63 HInstructionList list) { | 63 HInstructionStringifier stringifier, HInstructionList list) { |
| 64 for (HInstruction instruction = list.first; | 64 for (HInstruction instruction = list.first; |
| 65 instruction != null; | 65 instruction != null; |
| 66 instruction = instruction.next) { | 66 instruction = instruction.next) { |
| 67 int bci = 0; | 67 int bci = 0; |
| 68 int uses = instruction.usedBy.length; | 68 int uses = instruction.usedBy.length; |
| 69 String changes = instruction.sideEffects.hasSideEffects() ? '!' : ' '; | 69 String changes = instruction.sideEffects.hasSideEffects() ? '!' : ' '; |
| 70 String depends = instruction.sideEffects.dependsOnSomething() ? '?' : ''; | 70 String depends = instruction.sideEffects.dependsOnSomething() ? '?' : ''; |
| 71 addIndent(); | 71 addIndent(); |
| 72 String temporaryId = stringifier.temporaryId(instruction); | 72 String temporaryId = stringifier.temporaryId(instruction); |
| 73 String instructionString = stringifier.visit(instruction); | 73 String instructionString = stringifier.visit(instruction); |
| 74 add("$bci $uses $temporaryId $instructionString $changes $depends <|@\n"); | 74 add("$bci $uses $temporaryId $instructionString $changes $depends <|@\n"); |
| 75 } | 75 } |
| 76 } | 76 } |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 } | 155 } |
| 156 return "$prefix${instruction.id}"; | 156 return "$prefix${instruction.id}"; |
| 157 } | 157 } |
| 158 | 158 |
| 159 String visitBoolify(HBoolify node) { | 159 String visitBoolify(HBoolify node) { |
| 160 return "Boolify: ${temporaryId(node.inputs[0])}"; | 160 return "Boolify: ${temporaryId(node.inputs[0])}"; |
| 161 } | 161 } |
| 162 | 162 |
| 163 String handleInvokeBinary(HInvokeBinary node, String opcode) { | 163 String handleInvokeBinary(HInvokeBinary node, String opcode) { |
| 164 String left = temporaryId(node.left); | 164 String left = temporaryId(node.left); |
| 165 String right= temporaryId(node.right); | 165 String right = temporaryId(node.right); |
| 166 return '$opcode: $left $right'; | 166 return '$opcode: $left $right'; |
| 167 } | 167 } |
| 168 | 168 |
| 169 String visitAdd(HAdd node) => handleInvokeBinary(node, 'Add'); | 169 String visitAdd(HAdd node) => handleInvokeBinary(node, 'Add'); |
| 170 | 170 |
| 171 String visitBitAnd(HBitAnd node) => handleInvokeBinary(node, 'BitAnd'); | 171 String visitBitAnd(HBitAnd node) => handleInvokeBinary(node, 'BitAnd'); |
| 172 | 172 |
| 173 String visitBitNot(HBitNot node) { | 173 String visitBitNot(HBitNot node) { |
| 174 String operand = temporaryId(node.operand); | 174 String operand = temporaryId(node.operand); |
| 175 return "BitNot: $operand"; | 175 return "BitNot: $operand"; |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 248 | 248 |
| 249 String visitGoto(HGoto node) { | 249 String visitGoto(HGoto node) { |
| 250 HBasicBlock target = currentBlock.successors[0]; | 250 HBasicBlock target = currentBlock.successors[0]; |
| 251 return "Goto: (B${target.id})"; | 251 return "Goto: (B${target.id})"; |
| 252 } | 252 } |
| 253 | 253 |
| 254 String visitGreater(HGreater node) => handleInvokeBinary(node, 'Greater'); | 254 String visitGreater(HGreater node) => handleInvokeBinary(node, 'Greater'); |
| 255 String visitGreaterEqual(HGreaterEqual node) { | 255 String visitGreaterEqual(HGreaterEqual node) { |
| 256 return handleInvokeBinary(node, 'GreaterEqual'); | 256 return handleInvokeBinary(node, 'GreaterEqual'); |
| 257 } | 257 } |
| 258 |
| 258 String visitIdentity(HIdentity node) => handleInvokeBinary(node, 'Identity'); | 259 String visitIdentity(HIdentity node) => handleInvokeBinary(node, 'Identity'); |
| 259 | 260 |
| 260 String visitIf(HIf node) { | 261 String visitIf(HIf node) { |
| 261 HBasicBlock thenBlock = currentBlock.successors[0]; | 262 HBasicBlock thenBlock = currentBlock.successors[0]; |
| 262 HBasicBlock elseBlock = currentBlock.successors[1]; | 263 HBasicBlock elseBlock = currentBlock.successors[1]; |
| 263 String conditionId = temporaryId(node.inputs[0]); | 264 String conditionId = temporaryId(node.inputs[0]); |
| 264 return "If ($conditionId): (B${thenBlock.id}) else (B${elseBlock.id})"; | 265 return "If ($conditionId): (B${thenBlock.id}) else (B${elseBlock.id})"; |
| 265 } | 266 } |
| 266 | 267 |
| 267 String handleGenericInvoke(String invokeType, String functionName, | 268 String handleGenericInvoke( |
| 268 List<HInstruction> arguments) { | 269 String invokeType, String functionName, List<HInstruction> arguments) { |
| 269 StringBuffer argumentsString = new StringBuffer(); | 270 StringBuffer argumentsString = new StringBuffer(); |
| 270 for (int i = 0; i < arguments.length; i++) { | 271 for (int i = 0; i < arguments.length; i++) { |
| 271 if (i != 0) argumentsString.write(", "); | 272 if (i != 0) argumentsString.write(", "); |
| 272 argumentsString.write(temporaryId(arguments[i])); | 273 argumentsString.write(temporaryId(arguments[i])); |
| 273 } | 274 } |
| 274 return "$invokeType: $functionName($argumentsString)"; | 275 return "$invokeType: $functionName($argumentsString)"; |
| 275 } | 276 } |
| 276 | 277 |
| 277 String visitIndex(HIndex node) { | 278 String visitIndex(HIndex node) { |
| 278 String receiver = temporaryId(node.receiver); | 279 String receiver = temporaryId(node.receiver); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 291 String value = temporaryId(node.inputs[0]); | 292 String value = temporaryId(node.inputs[0]); |
| 292 if (node.interceptedClasses != null) { | 293 if (node.interceptedClasses != null) { |
| 293 JavaScriptBackend backend = compiler.backend; | 294 JavaScriptBackend backend = compiler.backend; |
| 294 String cls = | 295 String cls = |
| 295 backend.namer.suffixForGetInterceptor(node.interceptedClasses); | 296 backend.namer.suffixForGetInterceptor(node.interceptedClasses); |
| 296 return "Interceptor ($cls): $value"; | 297 return "Interceptor ($cls): $value"; |
| 297 } | 298 } |
| 298 return "Interceptor: $value"; | 299 return "Interceptor: $value"; |
| 299 } | 300 } |
| 300 | 301 |
| 301 String visitInvokeClosure(HInvokeClosure node) | 302 String visitInvokeClosure(HInvokeClosure node) => |
| 302 => handleInvokeDynamic(node, "InvokeClosure"); | 303 handleInvokeDynamic(node, "InvokeClosure"); |
| 303 | 304 |
| 304 String handleInvokeDynamic(HInvokeDynamic invoke, String kind) { | 305 String handleInvokeDynamic(HInvokeDynamic invoke, String kind) { |
| 305 String receiver = temporaryId(invoke.receiver); | 306 String receiver = temporaryId(invoke.receiver); |
| 306 String name = invoke.selector.name; | 307 String name = invoke.selector.name; |
| 307 String target = "$receiver.$name"; | 308 String target = "$receiver.$name"; |
| 308 int offset = HInvoke.ARGUMENTS_OFFSET; | 309 int offset = HInvoke.ARGUMENTS_OFFSET; |
| 309 List arguments = invoke.inputs.sublist(offset); | 310 List arguments = invoke.inputs.sublist(offset); |
| 310 return handleGenericInvoke(kind, target, arguments) + | 311 return handleGenericInvoke(kind, target, arguments) + "(${invoke.mask})"; |
| 311 "(${invoke.mask})"; | |
| 312 } | 312 } |
| 313 | 313 |
| 314 String visitInvokeDynamicMethod(HInvokeDynamicMethod node) | 314 String visitInvokeDynamicMethod(HInvokeDynamicMethod node) => |
| 315 => handleInvokeDynamic(node, "InvokeDynamicMethod"); | 315 handleInvokeDynamic(node, "InvokeDynamicMethod"); |
| 316 String visitInvokeDynamicGetter(HInvokeDynamicGetter node) | 316 String visitInvokeDynamicGetter(HInvokeDynamicGetter node) => |
| 317 => handleInvokeDynamic(node, "InvokeDynamicGetter"); | 317 handleInvokeDynamic(node, "InvokeDynamicGetter"); |
| 318 String visitInvokeDynamicSetter(HInvokeDynamicSetter node) | 318 String visitInvokeDynamicSetter(HInvokeDynamicSetter node) => |
| 319 => handleInvokeDynamic(node, "InvokeDynamicSetter"); | 319 handleInvokeDynamic(node, "InvokeDynamicSetter"); |
| 320 | 320 |
| 321 String visitInvokeStatic(HInvokeStatic invoke) { | 321 String visitInvokeStatic(HInvokeStatic invoke) { |
| 322 String target = invoke.element.name; | 322 String target = invoke.element.name; |
| 323 return handleGenericInvoke("InvokeStatic", target, invoke.inputs); | 323 return handleGenericInvoke("InvokeStatic", target, invoke.inputs); |
| 324 } | 324 } |
| 325 | 325 |
| 326 String visitInvokeSuper(HInvokeSuper invoke) { | 326 String visitInvokeSuper(HInvokeSuper invoke) { |
| 327 String target = invoke.element.name; | 327 String target = invoke.element.name; |
| 328 return handleGenericInvoke("InvokeSuper", target, invoke.inputs); | 328 return handleGenericInvoke("InvokeSuper", target, invoke.inputs); |
| 329 } | 329 } |
| 330 | 330 |
| 331 String visitInvokeConstructorBody(HInvokeConstructorBody invoke) { | 331 String visitInvokeConstructorBody(HInvokeConstructorBody invoke) { |
| 332 String target = invoke.element.name; | 332 String target = invoke.element.name; |
| 333 return handleGenericInvoke("InvokeConstructorBody", target, invoke.inputs); | 333 return handleGenericInvoke("InvokeConstructorBody", target, invoke.inputs); |
| 334 } | 334 } |
| 335 | 335 |
| 336 String visitForeignCode(HForeignCode foreign) { | 336 String visitForeignCode(HForeignCode foreign) { |
| 337 return handleGenericInvoke("ForeignCode", "${foreign.codeTemplate.ast}", | 337 return handleGenericInvoke( |
| 338 foreign.inputs); | 338 "ForeignCode", "${foreign.codeTemplate.ast}", foreign.inputs); |
| 339 } | 339 } |
| 340 | 340 |
| 341 String visitForeignNew(HForeignNew node) { | 341 String visitForeignNew(HForeignNew node) { |
| 342 return handleGenericInvoke("ForeignNew", | 342 return handleGenericInvoke( |
| 343 "${node.element.name}", | 343 "ForeignNew", "${node.element.name}", node.inputs); |
| 344 node.inputs); | |
| 345 } | 344 } |
| 346 | 345 |
| 347 String visitLess(HLess node) => handleInvokeBinary(node, 'Less'); | 346 String visitLess(HLess node) => handleInvokeBinary(node, 'Less'); |
| 348 String visitLessEqual(HLessEqual node) => | 347 String visitLessEqual(HLessEqual node) => |
| 349 handleInvokeBinary(node, 'LessEqual'); | 348 handleInvokeBinary(node, 'LessEqual'); |
| 350 | 349 |
| 351 String visitLiteralList(HLiteralList node) { | 350 String visitLiteralList(HLiteralList node) { |
| 352 StringBuffer elementsString = new StringBuffer(); | 351 StringBuffer elementsString = new StringBuffer(); |
| 353 for (int i = 0; i < node.inputs.length; i++) { | 352 for (int i = 0; i < node.inputs.length; i++) { |
| 354 if (i != 0) elementsString.write(", "); | 353 if (i != 0) elementsString.write(", "); |
| 355 elementsString.write(temporaryId(node.inputs[i])); | 354 elementsString.write(temporaryId(node.inputs[i])); |
| 356 } | 355 } |
| 357 return "LiteralList: [$elementsString]"; | 356 return "LiteralList: [$elementsString]"; |
| 358 } | 357 } |
| 359 | 358 |
| 360 String visitLoopBranch(HLoopBranch branch) { | 359 String visitLoopBranch(HLoopBranch branch) { |
| 361 HBasicBlock bodyBlock = currentBlock.successors[0]; | 360 HBasicBlock bodyBlock = currentBlock.successors[0]; |
| 362 HBasicBlock exitBlock = currentBlock.successors[1]; | 361 HBasicBlock exitBlock = currentBlock.successors[1]; |
| 363 String conditionId = temporaryId(branch.inputs[0]); | 362 String conditionId = temporaryId(branch.inputs[0]); |
| 364 return | 363 return "LoopBranch ($conditionId): (B${bodyBlock.id}) then (B${exitBlock.id}
)"; |
| 365 "LoopBranch ($conditionId): (B${bodyBlock.id}) then (B${exitBlock.id})"; | |
| 366 } | 364 } |
| 367 | 365 |
| 368 String visitMultiply(HMultiply node) => handleInvokeBinary(node, 'Multiply'); | 366 String visitMultiply(HMultiply node) => handleInvokeBinary(node, 'Multiply'); |
| 369 | 367 |
| 370 String visitNegate(HNegate node) { | 368 String visitNegate(HNegate node) { |
| 371 String operand = temporaryId(node.operand); | 369 String operand = temporaryId(node.operand); |
| 372 return "Negate: $operand"; | 370 return "Negate: $operand"; |
| 373 } | 371 } |
| 374 | 372 |
| 375 String visitNot(HNot node) => "Not: ${temporaryId(node.inputs[0])}"; | 373 String visitNot(HNot node) => "Not: ${temporaryId(node.inputs[0])}"; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 396 return 'Ref: ${temporaryId(node.value)}'; | 394 return 'Ref: ${temporaryId(node.value)}'; |
| 397 } | 395 } |
| 398 | 396 |
| 399 String visitReturn(HReturn node) => "Return: ${temporaryId(node.inputs[0])}"; | 397 String visitReturn(HReturn node) => "Return: ${temporaryId(node.inputs[0])}"; |
| 400 | 398 |
| 401 String visitShiftLeft(HShiftLeft node) => | 399 String visitShiftLeft(HShiftLeft node) => |
| 402 handleInvokeBinary(node, 'ShiftLeft'); | 400 handleInvokeBinary(node, 'ShiftLeft'); |
| 403 String visitShiftRight(HShiftRight node) => | 401 String visitShiftRight(HShiftRight node) => |
| 404 handleInvokeBinary(node, 'ShiftRight'); | 402 handleInvokeBinary(node, 'ShiftRight'); |
| 405 | 403 |
| 406 String visitStatic(HStatic node) | 404 String visitStatic(HStatic node) => "Static: ${node.element.name}"; |
| 407 => "Static: ${node.element.name}"; | |
| 408 | 405 |
| 409 String visitLazyStatic(HLazyStatic node) | 406 String visitLazyStatic(HLazyStatic node) => |
| 410 => "LazyStatic: ${node.element.name}"; | 407 "LazyStatic: ${node.element.name}"; |
| 411 | 408 |
| 412 String visitOneShotInterceptor(HOneShotInterceptor node) | 409 String visitOneShotInterceptor(HOneShotInterceptor node) => |
| 413 => handleInvokeDynamic(node, "OneShotInterceptor"); | 410 handleInvokeDynamic(node, "OneShotInterceptor"); |
| 414 | 411 |
| 415 String visitStaticStore(HStaticStore node) { | 412 String visitStaticStore(HStaticStore node) { |
| 416 String lhs = node.element.name; | 413 String lhs = node.element.name; |
| 417 return "StaticStore: $lhs = ${temporaryId(node.inputs[0])}"; | 414 return "StaticStore: $lhs = ${temporaryId(node.inputs[0])}"; |
| 418 } | 415 } |
| 419 | 416 |
| 420 String visitStringConcat(HStringConcat node) { | 417 String visitStringConcat(HStringConcat node) { |
| 421 var leftId = temporaryId(node.left); | 418 var leftId = temporaryId(node.left); |
| 422 var rightId = temporaryId(node.right); | 419 var rightId = temporaryId(node.right); |
| 423 return "StringConcat: $leftId + $rightId"; | 420 return "StringConcat: $leftId + $rightId"; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 483 return "Is: ${temporaryId(node.expression)} is $type"; | 480 return "Is: ${temporaryId(node.expression)} is $type"; |
| 484 } | 481 } |
| 485 | 482 |
| 486 String visitIsViaInterceptor(HIsViaInterceptor node) { | 483 String visitIsViaInterceptor(HIsViaInterceptor node) { |
| 487 String type = node.typeExpression.toString(); | 484 String type = node.typeExpression.toString(); |
| 488 return "IsViaInterceptor: ${temporaryId(node.inputs[0])} is $type"; | 485 return "IsViaInterceptor: ${temporaryId(node.inputs[0])} is $type"; |
| 489 } | 486 } |
| 490 | 487 |
| 491 String visitTypeConversion(HTypeConversion node) { | 488 String visitTypeConversion(HTypeConversion node) { |
| 492 assert(node.inputs.length <= 2); | 489 assert(node.inputs.length <= 2); |
| 493 String otherInput = (node.inputs.length == 2) | 490 String otherInput = |
| 494 ? temporaryId(node.inputs[1]) | 491 (node.inputs.length == 2) ? temporaryId(node.inputs[1]) : ''; |
| 495 : ''; | |
| 496 return "TypeConversion: ${temporaryId(node.checkedInput)} to " | 492 return "TypeConversion: ${temporaryId(node.checkedInput)} to " |
| 497 "${node.instructionType} $otherInput"; | 493 "${node.instructionType} $otherInput"; |
| 498 } | 494 } |
| 499 | 495 |
| 500 String visitTypeKnown(HTypeKnown node) { | 496 String visitTypeKnown(HTypeKnown node) { |
| 501 assert(node.inputs.length <= 2); | 497 assert(node.inputs.length <= 2); |
| 502 String result = | 498 String result = |
| 503 "TypeKnown: ${temporaryId(node.checkedInput)} is ${node.knownType}"; | 499 "TypeKnown: ${temporaryId(node.checkedInput)} is ${node.knownType}"; |
| 504 if (node.witness != null) { | 500 if (node.witness != null) { |
| 505 result += " witnessed by ${temporaryId(node.witness)}"; | 501 result += " witnessed by ${temporaryId(node.witness)}"; |
| 506 } | 502 } |
| 507 return result; | 503 return result; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 532 } | 528 } |
| 533 | 529 |
| 534 String visitAwait(HAwait node) { | 530 String visitAwait(HAwait node) { |
| 535 return "Await: ${temporaryId(node.inputs[0])}"; | 531 return "Await: ${temporaryId(node.inputs[0])}"; |
| 536 } | 532 } |
| 537 | 533 |
| 538 String visitYield(HYield node) { | 534 String visitYield(HYield node) { |
| 539 return "Yield${node.hasStar ? "*" : ""}: ${temporaryId(node.inputs[0])}"; | 535 return "Yield${node.hasStar ? "*" : ""}: ${temporaryId(node.inputs[0])}"; |
| 540 } | 536 } |
| 541 } | 537 } |
| OLD | NEW |