offlineasm: fix macro scoping
https://bugs.webkit.org/show_bug.cgi?id=189902
Reviewed by Mark Lam.
In the code below, the reference to `f` in `g`, which should refer to
the outer macro definition will instead refer to the f argument of the
anonymous macro passed to `g`. That leads to this code failing to
compile (f expected 0 args but got 1).
```
macro f(x)
move x, t0
end
macro g(fn)
fn(macro () f(42) end)
end
g(macro(f) f() end)
```
* offlineasm/ast.rb:
* offlineasm/transform.rb:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@236434 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 14c340f..a5eccf3 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,5 +1,32 @@
2018-09-24 Tadeu Zagallo <tzagallo@apple.com>
+ offlineasm: fix macro scoping
+ https://bugs.webkit.org/show_bug.cgi?id=189902
+
+ Reviewed by Mark Lam.
+
+ In the code below, the reference to `f` in `g`, which should refer to
+ the outer macro definition will instead refer to the f argument of the
+ anonymous macro passed to `g`. That leads to this code failing to
+ compile (f expected 0 args but got 1).
+
+ ```
+ macro f(x)
+ move x, t0
+ end
+
+ macro g(fn)
+ fn(macro () f(42) end)
+ end
+
+ g(macro(f) f() end)
+ ```
+
+ * offlineasm/ast.rb:
+ * offlineasm/transform.rb:
+
+2018-09-24 Tadeu Zagallo <tzagallo@apple.com>
+
Add forEach method for iterating CodeBlock's ValueProfiles
https://bugs.webkit.org/show_bug.cgi?id=189897
diff --git a/Source/JavaScriptCore/offlineasm/ast.rb b/Source/JavaScriptCore/offlineasm/ast.rb
index 0ccf7b3..bfe866b 100644
--- a/Source/JavaScriptCore/offlineasm/ast.rb
+++ b/Source/JavaScriptCore/offlineasm/ast.rb
@@ -727,26 +727,31 @@
class Variable < NoChildren
attr_reader :name
- def initialize(codeOrigin, name)
+ def initialize(codeOrigin, name, originalName = nil)
super(codeOrigin)
@name = name
+ @originalName = originalName
end
@@mapping = {}
- def self.forName(codeOrigin, name)
+ def self.forName(codeOrigin, name, originalName = nil)
unless @@mapping[name]
- @@mapping[name] = Variable.new(codeOrigin, name)
+ @@mapping[name] = Variable.new(codeOrigin, name, originalName)
end
@@mapping[name]
end
+
+ def originalName
+ @originalName || name
+ end
def dump
- name
+ originalName
end
def inspect
- "<variable #{name} at #{codeOriginString}>"
+ "<variable #{originalName} at #{codeOriginString}>"
end
end
@@ -1455,13 +1460,18 @@
class MacroCall < Node
attr_reader :name, :operands, :annotation
- def initialize(codeOrigin, name, operands, annotation)
+ def initialize(codeOrigin, name, operands, annotation, originalName = nil)
super(codeOrigin)
@name = name
@operands = operands
raise unless @operands
@operands.each{|v| raise unless v}
@annotation = annotation
+ @originalName = originalName
+ end
+
+ def originalName
+ @originalName || name
end
def children
@@ -1469,11 +1479,11 @@
end
def mapChildren(&proc)
- MacroCall.new(codeOrigin, @name, @operands.map(&proc), @annotation)
+ MacroCall.new(codeOrigin, @name, @operands.map(&proc), @annotation, @originalName)
end
def dump
- "\t#{name}(" + operands.collect{|v| v.dump}.join(", ") + ")"
+ "\t#{originalName}(" + operands.collect{|v| v.dump}.join(", ") + ")"
end
end
diff --git a/Source/JavaScriptCore/offlineasm/transform.rb b/Source/JavaScriptCore/offlineasm/transform.rb
index 2a08255..75a4b34 100644
--- a/Source/JavaScriptCore/offlineasm/transform.rb
+++ b/Source/JavaScriptCore/offlineasm/transform.rb
@@ -134,7 +134,20 @@
end
end
+$uniqueMacroVarID = 0
class Macro
+ def capture
+ mapping = {}
+ newVars = []
+ variables.each do |var|
+ $uniqueMacroVarID += 1
+ newVar = Variable.forName(var.codeOrigin, "_var#{$uniqueMacroVarID}", var.originalName)
+ newVars << newVar
+ mapping[var] = newVar
+ end
+ Macro.new(codeOrigin, name, newVars, body.substitute(mapping))
+ end
+
def substitute(mapping)
myMapping = {}
mapping.each_pair {
@@ -150,6 +163,17 @@
end
end
+class MacroCall
+ def substitute(mapping)
+ newName = Variable.forName(codeOrigin, name)
+ if mapping[newName]
+ newName = mapping[newName]
+ end
+ newOperands = operands.map { |operand| operand.substitute(mapping) }
+ MacroCall.new(codeOrigin, newName.name, newOperands, annotation, originalName)
+ end
+end
+
class Variable
def substitute(mapping)
if mapping[self]
@@ -203,7 +227,7 @@
@list.each {
| item |
if item.is_a? Macro
- myMacros[item.name] = item
+ myMacros[item.name] = item.capture
end
}
newList = []
@@ -214,15 +238,15 @@
elsif item.is_a? MacroCall
mapping = {}
myMyMacros = myMacros.dup
- raise "Could not find macro #{item.name} at #{item.codeOriginString}" unless myMacros[item.name]
- raise "Argument count mismatch for call to #{item.name} at #{item.codeOriginString}" unless item.operands.size == myMacros[item.name].variables.size
+ raise "Could not find macro #{item.originalName} at #{item.codeOriginString}" unless myMacros[item.name]
+ raise "Argument count mismatch for call to #{item.originalName} at #{item.codeOriginString}" unless item.operands.size == myMacros[item.name].variables.size
item.operands.size.times {
| idx |
if item.operands[idx].is_a? Variable and myMacros[item.operands[idx].name]
myMyMacros[myMacros[item.name].variables[idx].name] = myMacros[item.operands[idx].name]
mapping[myMacros[item.name].variables[idx].name] = nil
elsif item.operands[idx].is_a? Macro
- myMyMacros[myMacros[item.name].variables[idx].name] = item.operands[idx]
+ myMyMacros[myMacros[item.name].variables[idx].name] = item.operands[idx].capture
mapping[myMacros[item.name].variables[idx].name] = nil
else
myMyMacros[myMacros[item.name].variables[idx]] = nil
@@ -232,7 +256,7 @@
if item.annotation
newList << Instruction.new(item.codeOrigin, "localAnnotation", [], item.annotation)
end
- newList += myMacros[item.name].body.substitute(mapping).demacroify(myMyMacros).renameLabels(item.name).list
+ newList += myMacros[item.name].body.substitute(mapping).demacroify(myMyMacros).renameLabels(item.originalName).list
else
newList << item.demacroify(myMacros)
end