Skip to content

Commit

Permalink
Added constant folding to variable assignments. Avoid using reference…
Browse files Browse the repository at this point in the history
…s where possible.

(cherry picked from commit b09a6bf)
  • Loading branch information
dop251 authored and Gabri3l committed Sep 1, 2022
1 parent 33b5ee8 commit 551e150
Show file tree
Hide file tree
Showing 6 changed files with 255 additions and 89 deletions.
13 changes: 8 additions & 5 deletions compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,17 +395,21 @@ func (p *Program) addSrcMap(srcPos int) {
func (s *scope) lookupName(name unistring.String) (binding *binding, noDynamics bool) {
noDynamics = true
toStash := false
for curScope := s; curScope != nil; curScope = curScope.outer {
if curScope.dynamic {
noDynamics = false
} else {
for curScope := s; ; curScope = curScope.outer {
if curScope.outer != nil {
if b, exists := curScope.boundNames[name]; exists {
if toStash && !b.inStash {
b.moveToStash()
}
binding = b
return
}
} else {
noDynamics = false
return
}
if curScope.dynamic {
noDynamics = false
}
if name == "arguments" && curScope.function && !curScope.arrow {
curScope.argsNeeded = true
Expand All @@ -416,7 +420,6 @@ func (s *scope) lookupName(name unistring.String) (binding *binding, noDynamics
toStash = true
}
}
return
}

func (s *scope) ensureBoundNamesCreated() {
Expand Down
71 changes: 32 additions & 39 deletions compiler_expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,11 +395,11 @@ func (e *compiledIdentifierExpr) emitGetterAndCallee() {
func (e *compiledIdentifierExpr) emitVarSetter1(putOnStack bool, emitRight func(isRef bool)) {
e.addSrcMap()
c := e.c
if c.scope.strict {
c.checkIdentifierLName(e.name, e.offset)
}

if b, noDynamics := c.scope.lookupName(e.name); noDynamics {
if c.scope.strict {
c.checkIdentifierLName(e.name, e.offset)
}
emitRight(false)
if b != nil {
if putOnStack {
Expand All @@ -418,15 +418,7 @@ func (e *compiledIdentifierExpr) emitVarSetter1(putOnStack bool, emitRight func(
}
}
} else {
if b != nil {
b.emitResolveVar(c.scope.strict)
} else {
if c.scope.strict {
c.emit(resolveVar1Strict(e.name))
} else {
c.emit(resolveVar1(e.name))
}
}
c.emitVarRef(e.name, e.offset, b)
emitRight(true)
if putOnStack {
c.emit(putValue)
Expand All @@ -438,16 +430,15 @@ func (e *compiledIdentifierExpr) emitVarSetter1(putOnStack bool, emitRight func(

func (e *compiledIdentifierExpr) emitVarSetter(valueExpr compiledExpr, putOnStack bool) {
e.emitVarSetter1(putOnStack, func(bool) {
e.c.emitExpr(valueExpr, true)
e.c.emitNamedOrConst(valueExpr, e.name)
})
}

func (c *compiler) emitVarRef(name unistring.String, offset int) {
func (c *compiler) emitVarRef(name unistring.String, offset int, b *binding) {
if c.scope.strict {
c.checkIdentifierLName(name, offset)
}

b, _ := c.scope.lookupName(name)
if b != nil {
b.emitResolveVar(c.scope.strict)
} else {
Expand All @@ -460,7 +451,8 @@ func (c *compiler) emitVarRef(name unistring.String, offset int) {
}

func (e *compiledIdentifierExpr) emitRef() {
e.c.emitVarRef(e.name, e.offset)
b, _ := e.c.scope.lookupName(e.name)
e.c.emitVarRef(e.name, e.offset, b)
}

func (e *compiledIdentifierExpr) emitSetter(valueExpr compiledExpr, putOnStack bool) {
Expand Down Expand Up @@ -773,13 +765,6 @@ func (e *deleteGlobalExpr) emitGetter(putOnStack bool) {
func (e *compiledAssignExpr) emitGetter(putOnStack bool) {
switch e.operator {
case token.ASSIGN:
if fn, ok := e.right.(*compiledFunctionLiteral); ok {
if fn.name == nil {
if id, ok := e.left.(*compiledIdentifierExpr); ok {
fn.lhsName = id.name
}
}
}
e.left.emitSetter(e.right, putOnStack)
case token.PLUS:
e.left.emitUnary(nil, func() {
Expand Down Expand Up @@ -1065,14 +1050,14 @@ func (e *compiledFunctionLiteral) emitGetter(putOnStack bool) {
}
}, item.Initializer, item.Target.Idx0()).emitGetter(true)
e.c.emitPattern(pattern, func(target, init compiledExpr) {
e.c.emitPatternLexicalAssign(target, init, false)
e.c.emitPatternLexicalAssign(target, init)
}, false)
} else if item.Initializer != nil {
markGet := len(e.c.p.code)
e.c.emit(nil)
mark := len(e.c.p.code)
e.c.emit(nil)
e.c.compileExpression(item.Initializer).emitGetter(true)
e.c.emitExpr(e.c.compileExpression(item.Initializer), true)
if firstForwardRef == -1 && (s.isDynamic() || s.bindings[i].useCount() > 0) {
firstForwardRef = i
}
Expand Down Expand Up @@ -1100,7 +1085,7 @@ func (e *compiledFunctionLiteral) emitGetter(putOnStack bool) {
e.c.emit(createArgsRestStack(paramsCount))
}, rest.Idx0()),
func(target, init compiledExpr) {
e.c.emitPatternLexicalAssign(target, init, false)
e.c.emitPatternLexicalAssign(target, init)
})
}
if firstForwardRef != -1 {
Expand Down Expand Up @@ -1471,14 +1456,6 @@ func (c *compiler) emitConst(expr compiledExpr, putOnStack bool) {
}
}

func (c *compiler) emitExpr(expr compiledExpr, putOnStack bool) {
if expr.constant() {
c.emitConst(expr, putOnStack)
} else {
expr.emitGetter(putOnStack)
}
}

func (c *compiler) evalConst(expr compiledExpr) (Value, *Exception) {
if expr, ok := expr.(*compiledLiteral); ok {
return expr.val, nil
Expand Down Expand Up @@ -1825,7 +1802,7 @@ func (e *compiledObjectLiteral) emitGetter(putOnStack bool) {
}
if computed {
e.c.emit(_toPropertyKey{})
valueExpr.emitGetter(true)
e.c.emitExpr(valueExpr, true)
switch prop.Kind {
case ast.PropertyKindValue, ast.PropertyKindMethod:
if anonFn != nil {
Expand All @@ -1852,7 +1829,7 @@ func (e *compiledObjectLiteral) emitGetter(putOnStack bool) {
if anonFn != nil && !isProto {
anonFn.lhsName = key
}
valueExpr.emitGetter(true)
e.c.emitExpr(valueExpr, true)
switch prop.Kind {
case ast.PropertyKindValue:
if isProto {
Expand Down Expand Up @@ -1912,7 +1889,7 @@ func (e *compiledArrayLiteral) emitGetter(putOnStack bool) {
e.c.emit(pushArraySpread)
} else {
if v != nil {
e.c.compileExpression(v).emitGetter(true)
e.c.emitExpr(e.c.compileExpression(v), true)
} else {
e.c.emit(loadNil)
}
Expand Down Expand Up @@ -2195,6 +2172,14 @@ func (e *compiledArrayAssignmentPattern) emitGetter(putOnStack bool) {
}
}

func (c *compiler) emitExpr(expr compiledExpr, putOnStack bool) {
if expr.constant() {
c.emitConst(expr, putOnStack)
} else {
expr.emitGetter(putOnStack)
}
}

func (c *compiler) emitNamed(expr compiledExpr, name unistring.String) {
if en, ok := expr.(interface {
emitNamed(name unistring.String)
Expand All @@ -2205,6 +2190,14 @@ func (c *compiler) emitNamed(expr compiledExpr, name unistring.String) {
}
}

func (c *compiler) emitNamedOrConst(expr compiledExpr, name unistring.String) {
if expr.constant() {
c.emitConst(expr, true)
} else {
c.emitNamed(expr, name)
}
}

func (e *compiledFunctionLiteral) emitNamed(name unistring.String) {
e.lhsName = name
e.emitGetter(true)
Expand Down Expand Up @@ -2327,7 +2320,7 @@ func (e *compiledPatternInitExpr) emitGetter(putOnStack bool) {
if e.def != nil {
mark := len(e.c.p.code)
e.c.emit(nil)
e.def.emitGetter(true)
e.c.emitExpr(e.def, true)
e.c.p.code[mark] = jdef(len(e.c.p.code) - mark)
}
}
Expand All @@ -2337,7 +2330,7 @@ func (e *compiledPatternInitExpr) emitNamed(name unistring.String) {
if e.def != nil {
mark := len(e.c.p.code)
e.c.emit(nil)
e.c.emitNamed(e.def, name)
e.c.emitNamedOrConst(e.def, name)
e.c.p.code[mark] = jdef(len(e.c.p.code) - mark)
}
}
Expand Down
64 changes: 36 additions & 28 deletions compiler_stmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
)

func (c *compiler) compileStatement(v ast.Statement, needResult bool) {
// log.Printf("compileStatement(): %T", v)

switch v := v.(type) {
case *ast.BlockStatement:
Expand Down Expand Up @@ -158,7 +157,7 @@ func (c *compiler) compileTryStatement(v *ast.TryStatement, needResult bool) {
if pattern, ok := v.Catch.Parameter.(ast.Pattern); ok {
c.scope.bindings[0].emitGet()
c.emitPattern(pattern, func(target, init compiledExpr) {
c.emitPatternLexicalAssign(target, init, false)
c.emitPatternLexicalAssign(target, init)
}, false)
}
for _, decl := range funcs {
Expand Down Expand Up @@ -392,7 +391,7 @@ func (c *compiler) compileForInto(into ast.ForInto, needResult bool) (enter *ent
c.createLexicalBinding(target, into.IsConst)
c.emit(enumGet)
c.emitPattern(target, func(target, init compiledExpr) {
c.emitPatternLexicalAssign(target, init, into.IsConst)
c.emitPatternLexicalAssign(target, init)
}, false)
default:
c.throwSyntaxError(int(into.Idx)-1, "Unsupported ForBinding: %T", into.Target)
Expand Down Expand Up @@ -725,7 +724,7 @@ func (c *compiler) compileIfStatement(v *ast.IfStatement, needResult bool) {

func (c *compiler) compileReturnStatement(v *ast.ReturnStatement) {
if v.Argument != nil {
c.compileExpression(v.Argument).emitGetter(true)
c.emitExpr(c.compileExpression(v.Argument), true)
} else {
c.emit(loadUndef)
}
Expand Down Expand Up @@ -754,10 +753,17 @@ func (c *compiler) checkVarConflict(name unistring.String, offset int) {
func (c *compiler) emitVarAssign(name unistring.String, offset int, init compiledExpr) {
c.checkVarConflict(name, offset)
if init != nil {
c.emitVarRef(name, offset)
c.emitNamed(init, name)
c.p.addSrcMap(offset)
c.emit(initValueP)
b, noDyn := c.scope.lookupName(name)
if noDyn {
c.emitNamedOrConst(init, name)
c.p.addSrcMap(offset)
b.emitInit()
} else {
c.emitVarRef(name, offset, b)
c.emitNamedOrConst(init, name)
c.p.addSrcMap(offset)
c.emit(initValueP)
}
}
}

Expand All @@ -773,16 +779,16 @@ func (c *compiler) compileVarBinding(expr *ast.Binding) {
}
}

func (c *compiler) emitLexicalAssign(name unistring.String, offset int, init compiledExpr, isConst bool) {
func (c *compiler) emitLexicalAssign(name unistring.String, offset int, init compiledExpr) {
b := c.scope.boundNames[name]
if b == nil {
panic("Lexical declaration for an unbound name")
}
if init != nil {
c.emitNamed(init, name)
c.emitNamedOrConst(init, name)
c.p.addSrcMap(offset)
} else {
if isConst {
if b.isConst {
c.throwSyntaxError(offset, "Missing initializer in const declaration")
}
c.emit(loadUndef)
Expand All @@ -799,29 +805,37 @@ func (c *compiler) emitPatternVarAssign(target, init compiledExpr) {
c.emitVarAssign(id.name, id.offset, init)
}

func (c *compiler) emitPatternLexicalAssign(target, init compiledExpr, isConst bool) {
func (c *compiler) emitPatternLexicalAssign(target, init compiledExpr) {
id := target.(*compiledIdentifierExpr)
c.emitLexicalAssign(id.name, id.offset, init, isConst)
c.emitLexicalAssign(id.name, id.offset, init)
}

func (c *compiler) emitPatternAssign(target, init compiledExpr) {
target.emitRef()
if id, ok := target.(*compiledIdentifierExpr); ok {
c.emitNamed(init, id.name)
b, noDyn := c.scope.lookupName(id.name)
if noDyn {
c.emitNamedOrConst(init, id.name)
b.emitSetP()
} else {
c.emitVarRef(id.name, id.offset, b)
c.emitNamedOrConst(init, id.name)
c.emit(putValueP)
}
} else {
init.emitGetter(true)
target.emitRef()
c.emitExpr(init, true)
c.emit(putValueP)
}
c.emit(initValueP)
}

func (c *compiler) compileLexicalBinding(expr *ast.Binding, isConst bool) {
func (c *compiler) compileLexicalBinding(expr *ast.Binding) {
switch target := expr.Target.(type) {
case *ast.Identifier:
c.emitLexicalAssign(target.Name, int(target.Idx)-1, c.compileExpression(expr.Initializer), isConst)
c.emitLexicalAssign(target.Name, int(target.Idx)-1, c.compileExpression(expr.Initializer))
case ast.Pattern:
c.compileExpression(expr.Initializer).emitGetter(true)
c.emitPattern(target, func(target, init compiledExpr) {
c.emitPatternLexicalAssign(target, init, isConst)
c.emitPatternLexicalAssign(target, init)
}, false)
default:
c.throwSyntaxError(int(target.Idx0()-1), "unsupported lexical binding target: %T", target)
Expand All @@ -835,9 +849,8 @@ func (c *compiler) compileVariableStatement(v *ast.VariableStatement) {
}

func (c *compiler) compileLexicalDeclaration(v *ast.LexicalDeclaration) {
isConst := v.Token == token.CONST
for _, e := range v.List {
c.compileLexicalBinding(e, isConst)
c.compileLexicalBinding(e)
}
}

Expand Down Expand Up @@ -964,12 +977,7 @@ func (c *compiler) compileBlockStatement(v *ast.BlockStatement, needResult bool)
}

func (c *compiler) compileExpressionStatement(v *ast.ExpressionStatement, needResult bool) {
expr := c.compileExpression(v.Expression)
if expr.constant() {
c.emitConst(expr, needResult)
} else {
expr.emitGetter(needResult)
}
c.emitExpr(c.compileExpression(v.Expression), needResult)
if needResult {
c.emit(saveResult)
}
Expand Down
Loading

0 comments on commit 551e150

Please sign in to comment.