Permalink
Browse files

New instrumentation format support

  • Loading branch information...
inossidabile committed Mar 29, 2013
1 parent 65e4306 commit 7e600ec1199378fdfe8cd07c7081eb6841398491
Showing with 9,204 additions and 312 deletions.
  1. +9 −9 lib/furnace-xray/app/assets/javascripts/application.js.coffee
  2. +6 −5 lib/furnace-xray/app/assets/javascripts/lib/graph.js.coffee
  3. +43 −106 lib/furnace-xray/app/assets/javascripts/lib/input.js.coffee
  4. +6 −4 lib/furnace-xray/app/assets/javascripts/lib/input_state.js.coffee
  5. +0 −45 lib/furnace-xray/app/assets/javascripts/lib/map.js.coffee
  6. +39 −0 lib/furnace-xray/app/assets/javascripts/lib/node.js.coffee
  7. +9 −2 lib/furnace-xray/app/assets/javascripts/lib/nodes/argument.js.coffee
  8. +82 −0 lib/furnace-xray/app/assets/javascripts/lib/nodes/basic_block.js.coffee
  9. +0 −76 lib/furnace-xray/app/assets/javascripts/lib/nodes/block.js.coffee
  10. +9 −0 lib/furnace-xray/app/assets/javascripts/lib/nodes/constant.js.coffee
  11. +20 −5 lib/furnace-xray/app/assets/javascripts/lib/nodes/function.js.coffee
  12. +43 −24 lib/furnace-xray/app/assets/javascripts/lib/nodes/instruction.js.coffee
  13. +8 −0 lib/furnace-xray/app/assets/javascripts/lib/nodes/module.js.coffee
  14. +0 −21 lib/furnace-xray/app/assets/javascripts/lib/nodes/operand.js.coffee
  15. +10 −0 lib/furnace-xray/app/assets/javascripts/lib/nodes/phi.js.coffee
  16. +6 −9 lib/furnace-xray/app/assets/javascripts/lib/nodes/type.js.coffee
  17. +3 −0 lib/furnace-xray/app/assets/javascripts/lib/nodes/type_bottom.js.coffee
  18. +1 −0 lib/furnace-xray/app/assets/javascripts/lib/nodes/type_variable.js.coffee
  19. 0 lib/furnace-xray/app/views/nodes/{instruction_typed.jst.mustache → instruction.jst.mustache}
  20. +0 −1 lib/furnace-xray/app/views/nodes/operand_constant_function.jst.mustache
  21. 0 lib/furnace-xray/app/views/nodes/{operand_argument.jst.mustache → operands/argument.jst.mustache}
  22. 0 ...rnace-xray/app/views/nodes/{operand_basic_block.jst.mustache → operands/basic_block.jst.mustache}
  23. 0 lib/furnace-xray/app/views/nodes/{operand_constant.jst.mustache → operands/constant.jst.mustache}
  24. 0 ...rnace-xray/app/views/nodes/{operand_instruction.jst.mustache → operands/instruction.jst.mustache}
  25. 0 lib/furnace-xray/app/views/nodes/{type_constant.jst.mustache → type.jst.mustache}
  26. +0 −3 lib/furnace-xray/app/views/nodes/type_parametric.jst.mustache
  27. +1 −1 lib/furnace-xray/version.rb
  28. +8,909 −1 sample.json
@@ -64,16 +64,16 @@ class Application
@transform.removeClass('active').html('')
@diff.html('')
- input = @data[@currentFunction]
+ input = Input.functions[@currentFunction].input
- Drawer.reset() if @input?.source.name != input.source.name
+ Drawer.reset() if @input?.function.name != input.function.name
Drawer.clear()
@input = input
@input.rewind(@currentStep)
@drawer = new Drawer(new Graph(@input))
- @title.html @input.function.title()
+ @title.html @input.map[@input.function.id]?.title()
@diff.html "~ " + @input.previousState.cursor if @input.previousState?.cursor?
@renewZoomer()
@@ -87,16 +87,16 @@ class Application
dehasherize: ->
hash = window.location.hash.from(1)
- hash = "0:#{@data[0].events.length-1}" if hash.length == 0
+ hash = "0:#{Input.functions[0].input.events.length-1}" if hash.length == 0
[@currentFunction, @currentStep] = hash.split(":").map (x) -> x.toNumber()
jumpTo: (func, step) ->
if Object.isString(func)
@selector.find('option').each (x) ->
func = $(@).attr('value').toNumber() if $(@).text() == func
- @currentFunction = func; step = @data[func].events.length-1 if step == undefined
- @currentStep = [step, @data[func].events.length-1].min()
+ @currentFunction = func; step = Input.functions[func].input.events.length-1 if step == undefined
+ @currentStep = [step, Input.functions[func].input.events.length-1].min()
@currentStep = [0, @currentStep].max()
window.location.hash = "#{@currentFunction}:#{@currentStep || 0}"
@@ -162,9 +162,9 @@ class Application
buildSelector: ->
groups = ['Present', 'Removed'].map (x) -> $("<optgroup label='#{x}'></optgroup>")
- @data.each (f, i) =>
- group = if f.source.present then groups[0] else groups[1]
- group.append "<option value='#{i}'>#{f.source.name}</option>"
+ Input.functions.each (f, i) ->
+ group = if f.present then groups[0] else groups[1]
+ group.append "<option value='#{i}'>#{f.name}</option>"
groups.each (x) => @selector.append x
@@ -8,18 +8,19 @@ class @Graph
@edges = []
blockNodes = Object.extended()
- @input.blocks.each (i, b) =>
- blockNodes[b.name] =
+ @input.activeBlocks()?.each (b) =>
+ blockNodes[b.id] =
edges: b.references()
label: b.name
- data: b.title(@input.previousState?.blocks[b.name])
+ data: b.title(unless @input.previousState? then false else (@input.previousState.basicBlocks[b.id] || []))
blockNodes.each (i, n) =>
edges = []
n.edges.each (x) =>
- edges.add {source: n, target: blockNodes[x], data: blockNodes[x].label}
- @edges.add edges.last()
+ if blockNodes[x]?
+ edges.add {source: n, target: blockNodes[x], data: blockNodes[x].label}
+ @edges.add edges.last()
n.edges = edges
@@ -2,61 +2,63 @@
# Internal representation of input JSON
#
class @Input
- @normalize: (data) ->
- data.map (x) -> new Input(x)
-
- constructor: (@source) ->
- @source.events.each (x) -> x.event = x.event.camelize(false)
-
- # Scan for effective events
- @events = []
- reducer = []
+ @normalize: (@events) =>
+ @functions = []
+ events = Object.extended()
transforms = Object.extended()
- @source.events.each (x, i) =>
- switch x.event
- when 'addInstruction'
- reducer.add x.name
- @events.add i
- when 'removeInstruction'
- reducer.exclude x.name
- @events.add i
- when 'updateInstruction', 'renameInstruction'
- @events.add i if reducer.any(x.name)
- when 'type', 'transformStart'
- else
- @events.add i
-
- if x.event == 'transformStart'
- id = @events.length-1
- transforms[id] = {id: id, label: x.name}
-
- @transforms = transforms.values()
+ @events.each (event, i) =>
+ if event['kind'] == 'transform'
+ f = event['function_id']
+
+ transforms[f] ||= []
+ transforms[f].push
+ id: events[f].length - 1
+ label: event['name']
+ else
+ node = Node.refresh(event)
+
+ if node.attachedFunctions?
+ Object.each node.attachedFunctions(), (id, f) =>
+ events[id] ||= []
+ events[id].push i
+
+ Node.kinds['function'].each (f) =>
+ @functions.push
+ name: f.name
+ present: f.present
+ input: new Input(f, events[f.id], transforms[f.id])
+
+ @constantize: (kind) ->
+ result = window[kind.camelize()+'Node']
+ result
+
+ constructor: (@function, @events, @transforms) ->
@transforms = @transforms.filter (x, i) =>
x.length = (@transforms[i+1]?.id || @events.length) - x.id
- x.id < @events.length-1
+ x.id < @events.length-1 && x.length > 0
@reset()
- reset: ->
- @types = Object.extended()
- @blocks = Object.extended()
- @instructions = Object.extended()
- @blocksMap = new Map 'blocks'
- @instructionsMap = new Map 'instructions'
+ activeBlocks: ->
+ data = @kinds['basic_block']?.findAll (b) =>
+ b.attachedFunctions()[@function.id]?
- @function = new FunctionNode(@source.name, @source.present)
- @cursor = 0
+ data || []
- # run first step at initialization
- i = -1; @run(i) while (i+=1) <= (@events[1] || @source.events.length-1)
+ reset: ->
+ @map = Object.extended()
+ @kinds = Object.extended()
+ @cursor = 0
+
+ # run upcoming steps at initialization
+ i = -1; @run(i) while (i+=1) < @events[0]
rewind: (to) ->
return if to == @cursor
if to < @cursor
delete @previousState
- @reset()
else
@previousState = new InputState(@)
@@ -72,69 +74,4 @@ class @Input
@cursor = stop
run: (step) ->
- event = @source.events[step]
-
- if event.event == 'type'
- @types[event.id] = new TypeNode(event.kind, event.name, event.parameters)
- else
- @[event.event]?(event)
- console.log "UNKNOWN EVENT: #{event.event}" unless @[event.event]?
-
- type: (id) ->
- return undefined unless id?
-
- if type = @types[id]
- return type
- else
- @reset()
- throw "Type #{id} not found in #{@types.keys().join(',')}"
-
- setReturnType: (event) ->
- @function.setReturnType @type(event.return_type)
-
- setArguments: (event) ->
- @function.setArguments(event.arguments.map (x) =>
- new ArgumentNode(x.name, @type(x.type)))
-
- addBasicBlock: (event) ->
- @blocksMap.add event.name, (id) =>
- @blocks[id] = new BlockNode(event.name)
-
- removeBasicBlock: (event) ->
- @blocksMap.remove event.name, (id) =>
- delete @blocks[id]
-
- renameBasicBlock: (event) ->
- @blocksMap.rename event.name, event.new_name, (id) =>
- @blocks[id].setName(event.new_name)
-
- updateInstruction: (event) ->
- id = @instructionsMap.add event.name, (id) =>
- @instructions[id] = new InstructionNode
-
- if Object.isArray(event.operands)
- operands = event.operands.map (x) =>
- new OperandNode x.kind, @type(x.type), x.name, x.value
- else
- operands = []
- Object.each event.operands, (key, x) =>
- operands.push [key, new OperandNode(x.kind, @type(x.type), x.name, x.value)]
-
- @instructions[id].update event.opcode, event.name, event.parameters, operands, @type(event.type)
-
- addInstruction: (event) ->
- id = @instructionsMap.add event.name, (id) =>
- @instructions[id] = new InstructionNode(event.name)
-
- @blocksMap.locate event.basic_block, (b) =>
- @instructions[id].link @blocks[b], event.index
-
- removeInstruction: (event) ->
- @instructionsMap.locate event.name, (id) =>
- @instructions[id].unlink()
-
- renameInstruction: (event) ->
- @instructionsMap.rename event.name, event.new_name, (id) =>
- @instructions[id].name = event.new_name
-
- transformStart: (event) ->
+ node = Node.refresh(Input.events[step], @map, @kinds)
@@ -1,8 +1,10 @@
class @InputState
constructor: (input) ->
- @blocks = Object.extended()
+ @basicBlocks = Object.extended()
@cursor = input.cursor
- input.blocksMap.each (bname, id) =>
- @blocks[bname] = input.blocks[id].instructions.map (x) ->
- {title: x.title(), name: x.name}
+ input.kinds['basic_block']?.each (b) =>
+ @basicBlocks[b.id] = b.instructions.map (i) =>
+ id: i.id
+ name: i.name
+ title: i.title()
@@ -1,45 +0,0 @@
-#
-# Failsafe Map container
-#
-class @Map
- constructor: (@title) ->
- @data = []
- @map = Object.extended()
-
- each: (block) -> @map.each block
-
- add: (name, block) ->
- id = @map[name]
-
- unless id?
- @data.add name
- id = @data.length-1
- block(id) if block
- @map[name] = id
-
- id
-
- find: (name) ->
- id = @map[name]
-
- unless id?
- error = "Map '#{@title}': '#{name}' element not found"
- throw error
-
- id
-
- remove: (name, block) ->
- id = @find(name)
- @data.splice id, 1
- block(id) if block
- delete @map[name]
-
- rename: (name, newName, block) ->
- id = @find(name)
- @data[id] = newName
- block(id) if block
- delete @map[name]
- @map[newName] = id
-
- locate: (name, block) ->
- block(@find(name))
@@ -0,0 +1,39 @@
+class @Node
+ @refresh: (data, map=false, kinds=false) ->
+ Node.map ||= Object.extended()
+ Node.kinds ||= Object.extended()
+
+ map ||= Node.map
+ kinds ||= Node.kinds
+
+ if map[data.id]
+ map[data.id].update(data, map)
+ else
+ klass = window[data.kind.camelize()+'Node']
+
+ return false if !klass?
+
+ kinds[data.kind] ||= []
+ kinds[data.kind].push map[data.id] = new klass(data, map)
+
+ map[data.id]
+
+ @reset: ->
+ Node.map = Object.extended()
+ Node.kinds = {}
+
+ constructor: (data, map) ->
+ @id = data.id
+ @update(data, map)
+
+ update: (data, map) ->
+
+ locate: (id, map) ->
+ map[id] || throw("Element #{id} not found in map")
+
+ reassign: (before, after, callback) ->
+ if !before? || before.length == 0
+ callback([], after)
+ else
+ intersection = before.intersect(after)
+ callback before.subtract(intersection), after.subtract(intersection)
@@ -1,7 +1,14 @@
-class @ArgumentNode
- constructor: (@name, @type) ->
+class @ArgumentNode extends Node
+ update: (data, map) ->
+ @name = data['name']
+ @type = @locate(data['type'], map)
title: ->
JST['nodes/argument']
+ type: @type.title()
+ name: @name
+
+ operandTitle: ->
+ JST['nodes/operands/argument']
type: @type.title()
name: @name
Oops, something went wrong.

0 comments on commit 7e600ec

Please sign in to comment.