Make JetStream 2
[WebKit-https.git] / PerformanceTests / JetStream2 / WSL / PropertyResolver.js
1 /*
2  * Copyright (C) 2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25 "use strict";
26
27 class PropertyResolver extends Visitor {
28     _visitRValuesWithinLValue(node)
29     {
30         let visit = node => node.visit(this);
31         
32         class RValueFinder {
33             visitDotExpression(node)
34             {
35                 node.struct.visit(this);
36             }
37             
38             visitIndexExpression(node)
39             {
40                 node.array.visit(this);
41                 visit(node.index);
42             }
43             
44             visitVariableRef(node)
45             {
46             }
47             
48             visitDereferenceExpression(node)
49             {
50                 visit(node.ptr);
51             }
52             
53             visitIdentityExpression(node)
54             {
55                 node.target.visit(this);
56             }
57             
58             visitMakeArrayRefExpression(node)
59             {
60                 visit(node.lValue);
61             }
62         }
63         
64         node.visit(new RValueFinder());
65     }
66     
67     _visitPropertyAccess(node)
68     {
69         let newNode = node.visit(new NormalUsePropertyResolver());
70         newNode.visit(this);
71         node.become(newNode);
72     }
73     
74     visitDotExpression(node)
75     {
76         this._visitPropertyAccess(node);
77     }
78     
79     visitIndexExpression(node)
80     {
81         this._visitPropertyAccess(node);
82     }
83     
84     _handleReadModifyWrite(node)
85     {
86         let type = node.oldValueVar.type;
87         if (!type)
88             throw new Error("Null type");
89         let simpleLHS = node.lValue.visit(new NormalUsePropertyResolver());
90         if (simpleLHS.isLValue) {
91             if (!simpleLHS.addressSpace)
92                 throw new Error(node.origin.originString + ": LHS without address space: " + simpleLHS);
93             let ptrType = new PtrType(node.origin, simpleLHS.addressSpace, type);
94             let ptrVar = new AnonymousVariable(node.origin, ptrType);
95             node.become(new CommaExpression(node.origin, [
96                 node.oldValueVar, node.newValueVar, ptrVar,
97                 new Assignment(
98                     node.origin, VariableRef.wrap(ptrVar),
99                     new MakePtrExpression(node.origin, simpleLHS), ptrType),
100                 new Assignment(
101                     node.origin, node.oldValueRef(),
102                     new DereferenceExpression(
103                         node.origin, VariableRef.wrap(ptrVar), type, simpleLHS.addressSpace),
104                     type),
105                 new Assignment(node.origin, node.newValueRef(), node.newValueExp, type),
106                 new Assignment(
107                     node.origin,
108                     new DereferenceExpression(
109                         node.origin, VariableRef.wrap(ptrVar), type, simpleLHS.addressSpace),
110                     node.newValueRef(), type),
111                 node.resultExp
112             ]));
113             return;
114         }
115         
116         let result = new ReadModifyWriteExpression(node.origin, node.lValue.base, node.lValue.baseType);
117         result.newValueExp = new CommaExpression(node.origin, [
118             node.oldValueVar, node.newValueVar,
119             new Assignment(node.origin, node.oldValueRef(), node.lValue.emitGet(result.oldValueRef()), type),
120             new Assignment(node.origin, node.newValueRef(), node.newValueExp, type),
121             node.lValue.emitSet(result.oldValueRef(), node.newValueRef())
122         ]);
123         result.resultExp = node.newValueRef();
124         this._handleReadModifyWrite(result);
125         node.become(result);
126     }
127     
128     visitReadModifyWriteExpression(node)
129     {
130         node.newValueExp.visit(this);
131         node.resultExp.visit(this);
132         this._visitRValuesWithinLValue(node.lValue);
133         this._handleReadModifyWrite(node);
134     }
135     
136     visitAssignment(node)
137     {
138         this._visitRValuesWithinLValue(node.lhs);
139         node.rhs.visit(this);
140         
141         let simpleLHS = node.lhs.visit(new NormalUsePropertyResolver());
142         if (simpleLHS.isLValue) {
143             node.lhs.become(simpleLHS);
144             return;
145         }
146         
147         if (!(node.lhs instanceof PropertyAccessExpression))
148             throw new Error("Unexpected lhs type: " + node.lhs.constructor.name);
149         
150         let result = new ReadModifyWriteExpression(node.origin, node.lhs.base, node.lhs.baseType);
151         let resultVar = new AnonymousVariable(node.origin, node.type);
152         result.newValueExp = new CommaExpression(node.origin, [
153             resultVar,
154             new Assignment(node.origin, VariableRef.wrap(resultVar), node.rhs, node.type),
155             node.lhs.emitSet(result.oldValueRef(), VariableRef.wrap(resultVar))
156         ]);
157         result.resultExp = VariableRef.wrap(resultVar);
158         this._handleReadModifyWrite(result);
159         node.become(result);
160     }
161     
162     visitMakePtrExpression(node)
163     {
164         super.visitMakePtrExpression(node);
165         if (!node.lValue.isLValue)
166             throw new WTypeError(node.origin.originString, "Not an lvalue: " + node.lValue);
167     }
168     
169     visitMakeArrayRefExpression(node)
170     {
171         super.visitMakeArrayRefExpression(node);
172         if (!node.lValue.isLValue)
173             throw new WTypeError(node.origin.originString, "Not an lvalue: " + node.lValue);
174     }
175 }
176