author | hannesw |
Wed, 21 Mar 2018 16:55:34 +0100 | |
changeset 49275 | c639a6b33c5c |
parent 47437 | 54a2f246edd8 |
permissions | -rw-r--r-- |
16147 | 1 |
/* |
16151 | 2 |
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. |
16147 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. Oracle designates this |
|
8 |
* particular file as subject to the "Classpath" exception as provided |
|
9 |
* by Oracle in the LICENSE file that accompanied this code. |
|
10 |
* |
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
24 |
*/ |
|
25 |
||
26 |
package jdk.nashorn.internal.runtime; |
|
27 |
||
16277 | 28 |
import static jdk.nashorn.internal.lookup.Lookup.MH; |
32694
da2f35ab2ea6
8136544: Call site switching to megamorphic causes incorrect property read
sundar
parents:
32527
diff
changeset
|
29 |
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; |
16147 | 30 |
|
31 |
import java.lang.invoke.MethodHandle; |
|
32 |
import java.lang.invoke.MethodHandles; |
|
16780
f23743ec1a93
8011555: Invalid class name in with block with JavaImporter causes MH type mismatch
attila
parents:
16277
diff
changeset
|
33 |
import java.lang.invoke.MethodType; |
19884
1bacbaa1bfc7
8024180: Incorrect handling of expression and parent scope in 'with' statements
sundar
parents:
19621
diff
changeset
|
34 |
import java.lang.invoke.SwitchPoint; |
34447
ec4c069f9436
8141338: Move jdk.internal.dynalink package to jdk.dynalink
attila
parents:
33690
diff
changeset
|
35 |
import jdk.dynalink.CallSiteDescriptor; |
ec4c069f9436
8141338: Move jdk.internal.dynalink package to jdk.dynalink
attila
parents:
33690
diff
changeset
|
36 |
import jdk.dynalink.NamedOperation; |
ec4c069f9436
8141338: Move jdk.internal.dynalink package to jdk.dynalink
attila
parents:
33690
diff
changeset
|
37 |
import jdk.dynalink.Operation; |
ec4c069f9436
8141338: Move jdk.internal.dynalink package to jdk.dynalink
attila
parents:
33690
diff
changeset
|
38 |
import jdk.dynalink.StandardOperation; |
ec4c069f9436
8141338: Move jdk.internal.dynalink package to jdk.dynalink
attila
parents:
33690
diff
changeset
|
39 |
import jdk.dynalink.linker.GuardedInvocation; |
ec4c069f9436
8141338: Move jdk.internal.dynalink package to jdk.dynalink
attila
parents:
33690
diff
changeset
|
40 |
import jdk.dynalink.linker.LinkRequest; |
25821
fbb51e67d2a7
8048869: Reduce compile time by about 5% by removing the Class.casts from the AST nodes
lagergren
parents:
25247
diff
changeset
|
41 |
import jdk.nashorn.api.scripting.AbstractJSObject; |
fbb51e67d2a7
8048869: Reduce compile time by about 5% by removing the Class.casts from the AST nodes
lagergren
parents:
25247
diff
changeset
|
42 |
import jdk.nashorn.api.scripting.ScriptObjectMirror; |
16147 | 43 |
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; |
23084
6c5c02d1023a
8035948: Redesign property listeners for shared classes
hannesw
parents:
20933
diff
changeset
|
44 |
import jdk.nashorn.internal.runtime.linker.NashornGuards; |
16147 | 45 |
|
46 |
/** |
|
47 |
* This class supports the handling of scope in a with body. |
|
48 |
* |
|
49 |
*/ |
|
31199 | 50 |
public final class WithObject extends Scope { |
32695
9b708b92c695
8134609: Allow constructors with same prototoype map to share the allocator map
hannesw
parents:
32694
diff
changeset
|
51 |
private static final MethodHandle WITHEXPRESSIONGUARD = findOwnMH("withExpressionGuard", boolean.class, Object.class, PropertyMap.class, SwitchPoint[].class); |
16780
f23743ec1a93
8011555: Invalid class name in with block with JavaImporter causes MH type mismatch
attila
parents:
16277
diff
changeset
|
52 |
private static final MethodHandle WITHEXPRESSIONFILTER = findOwnMH("withFilterExpression", Object.class, Object.class); |
f23743ec1a93
8011555: Invalid class name in with block with JavaImporter causes MH type mismatch
attila
parents:
16277
diff
changeset
|
53 |
private static final MethodHandle WITHSCOPEFILTER = findOwnMH("withFilterScope", Object.class, Object.class); |
f23743ec1a93
8011555: Invalid class name in with block with JavaImporter causes MH type mismatch
attila
parents:
16277
diff
changeset
|
54 |
private static final MethodHandle BIND_TO_EXPRESSION_OBJ = findOwnMH("bindToExpression", Object.class, Object.class, Object.class); |
f23743ec1a93
8011555: Invalid class name in with block with JavaImporter causes MH type mismatch
attila
parents:
16277
diff
changeset
|
55 |
private static final MethodHandle BIND_TO_EXPRESSION_FN = findOwnMH("bindToExpression", Object.class, ScriptFunction.class, Object.class); |
16147 | 56 |
|
57 |
/** With expression object. */ |
|
19884
1bacbaa1bfc7
8024180: Incorrect handling of expression and parent scope in 'with' statements
sundar
parents:
19621
diff
changeset
|
58 |
private final ScriptObject expression; |
16147 | 59 |
|
60 |
/** |
|
61 |
* Constructor |
|
62 |
* |
|
63 |
* @param scope scope object |
|
64 |
* @param expression with expression |
|
65 |
*/ |
|
19884
1bacbaa1bfc7
8024180: Incorrect handling of expression and parent scope in 'with' statements
sundar
parents:
19621
diff
changeset
|
66 |
WithObject(final ScriptObject scope, final ScriptObject expression) { |
19085
066c9e5afd79
8020731: Revisit checkPermission calls in Context class
sundar
parents:
17236
diff
changeset
|
67 |
super(scope, null); |
16147 | 68 |
this.expression = expression; |
39900
a9ad93ab3f6d
8160034: The `this` value in the `with` is broken by the repetition of a function call
hannesw
parents:
39164
diff
changeset
|
69 |
setIsInternal(); |
16147 | 70 |
} |
71 |
||
72 |
/** |
|
73 |
* Delete a property based on a key. |
|
74 |
* @param key Any valid JavaScript value. |
|
75 |
* @param strict strict mode execution. |
|
76 |
* @return True if deleted. |
|
77 |
*/ |
|
78 |
@Override |
|
79 |
public boolean delete(final Object key, final boolean strict) { |
|
19884
1bacbaa1bfc7
8024180: Incorrect handling of expression and parent scope in 'with' statements
sundar
parents:
19621
diff
changeset
|
80 |
final ScriptObject self = expression; |
1bacbaa1bfc7
8024180: Incorrect handling of expression and parent scope in 'with' statements
sundar
parents:
19621
diff
changeset
|
81 |
final String propName = JSType.toString(key); |
16147 | 82 |
|
19884
1bacbaa1bfc7
8024180: Incorrect handling of expression and parent scope in 'with' statements
sundar
parents:
19621
diff
changeset
|
83 |
final FindProperty find = self.findProperty(propName, true); |
16147 | 84 |
|
19884
1bacbaa1bfc7
8024180: Incorrect handling of expression and parent scope in 'with' statements
sundar
parents:
19621
diff
changeset
|
85 |
if (find != null) { |
1bacbaa1bfc7
8024180: Incorrect handling of expression and parent scope in 'with' statements
sundar
parents:
19621
diff
changeset
|
86 |
return self.delete(propName, strict); |
16147 | 87 |
} |
88 |
||
89 |
return false; |
|
90 |
} |
|
91 |
||
92 |
||
93 |
@Override |
|
16195
3f6c0ab2597a
8006766: Array-like access to characters of a string is slow
hannesw
parents:
16173
diff
changeset
|
94 |
public GuardedInvocation lookup(final CallSiteDescriptor desc, final LinkRequest request) { |
23372
09707b3e5fb0
8021350: Share script classes between threads/globals within context
hannesw
parents:
23084
diff
changeset
|
95 |
if (request.isCallSiteUnstable()) { |
09707b3e5fb0
8021350: Share script classes between threads/globals within context
hannesw
parents:
23084
diff
changeset
|
96 |
// Fall back to megamorphic invocation which performs a complete lookup each time without further relinking. |
09707b3e5fb0
8021350: Share script classes between threads/globals within context
hannesw
parents:
23084
diff
changeset
|
97 |
return super.lookup(desc, request); |
09707b3e5fb0
8021350: Share script classes between threads/globals within context
hannesw
parents:
23084
diff
changeset
|
98 |
} |
09707b3e5fb0
8021350: Share script classes between threads/globals within context
hannesw
parents:
23084
diff
changeset
|
99 |
|
16147 | 100 |
GuardedInvocation link = null; |
33343
23abd10384a5
8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
33330
diff
changeset
|
101 |
final Operation op = desc.getOperation(); |
16147 | 102 |
|
39900
a9ad93ab3f6d
8160034: The `this` value in the `with` is broken by the repetition of a function call
hannesw
parents:
39164
diff
changeset
|
103 |
assert op instanceof NamedOperation; // WithObject is a scope object, access is always named |
a9ad93ab3f6d
8160034: The `this` value in the `with` is broken by the repetition of a function call
hannesw
parents:
39164
diff
changeset
|
104 |
final String name = ((NamedOperation)op).getName().toString(); |
a9ad93ab3f6d
8160034: The `this` value in the `with` is broken by the repetition of a function call
hannesw
parents:
39164
diff
changeset
|
105 |
|
a9ad93ab3f6d
8160034: The `this` value in the `with` is broken by the repetition of a function call
hannesw
parents:
39164
diff
changeset
|
106 |
FindProperty find = expression.findProperty(name, true); |
16147 | 107 |
|
19884
1bacbaa1bfc7
8024180: Incorrect handling of expression and parent scope in 'with' statements
sundar
parents:
19621
diff
changeset
|
108 |
if (find != null) { |
39900
a9ad93ab3f6d
8160034: The `this` value in the `with` is broken by the repetition of a function call
hannesw
parents:
39164
diff
changeset
|
109 |
link = expression.lookup(desc, request); |
19884
1bacbaa1bfc7
8024180: Incorrect handling of expression and parent scope in 'with' statements
sundar
parents:
19621
diff
changeset
|
110 |
if (link != null) { |
41842
50202a344d28
8168005: Introduce namespaces for GET, SET Dynalink operations
attila
parents:
41422
diff
changeset
|
111 |
return fixExpressionCallSite(desc, link); |
16147 | 112 |
} |
113 |
} |
|
114 |
||
115 |
final ScriptObject scope = getProto(); |
|
39900
a9ad93ab3f6d
8160034: The `this` value in the `with` is broken by the repetition of a function call
hannesw
parents:
39164
diff
changeset
|
116 |
find = scope.findProperty(name, true); |
16147 | 117 |
|
118 |
if (find != null) { |
|
23084
6c5c02d1023a
8035948: Redesign property listeners for shared classes
hannesw
parents:
20933
diff
changeset
|
119 |
return fixScopeCallSite(scope.lookup(desc, request), name, find.getOwner()); |
16147 | 120 |
} |
121 |
||
122 |
// the property is not found - now check for |
|
123 |
// __noSuchProperty__ and __noSuchMethod__ in expression |
|
39900
a9ad93ab3f6d
8160034: The `this` value in the `with` is broken by the repetition of a function call
hannesw
parents:
39164
diff
changeset
|
124 |
final String fallBack; |
16147 | 125 |
|
41842
50202a344d28
8168005: Introduce namespaces for GET, SET Dynalink operations
attila
parents:
41422
diff
changeset
|
126 |
final Operation firstOp = NashornCallSiteDescriptor.getBaseOperation(desc); |
50202a344d28
8168005: Introduce namespaces for GET, SET Dynalink operations
attila
parents:
41422
diff
changeset
|
127 |
if (firstOp == StandardOperation.GET) { |
50202a344d28
8168005: Introduce namespaces for GET, SET Dynalink operations
attila
parents:
41422
diff
changeset
|
128 |
if (NashornCallSiteDescriptor.isMethodFirstOperation(desc)) { |
50202a344d28
8168005: Introduce namespaces for GET, SET Dynalink operations
attila
parents:
41422
diff
changeset
|
129 |
fallBack = NO_SUCH_METHOD_NAME; |
50202a344d28
8168005: Introduce namespaces for GET, SET Dynalink operations
attila
parents:
41422
diff
changeset
|
130 |
} else { |
50202a344d28
8168005: Introduce namespaces for GET, SET Dynalink operations
attila
parents:
41422
diff
changeset
|
131 |
fallBack = NO_SUCH_PROPERTY_NAME; |
50202a344d28
8168005: Introduce namespaces for GET, SET Dynalink operations
attila
parents:
41422
diff
changeset
|
132 |
} |
50202a344d28
8168005: Introduce namespaces for GET, SET Dynalink operations
attila
parents:
41422
diff
changeset
|
133 |
} else { |
39900
a9ad93ab3f6d
8160034: The `this` value in the `with` is broken by the repetition of a function call
hannesw
parents:
39164
diff
changeset
|
134 |
fallBack = null; |
a9ad93ab3f6d
8160034: The `this` value in the `with` is broken by the repetition of a function call
hannesw
parents:
39164
diff
changeset
|
135 |
} |
16147 | 136 |
|
39900
a9ad93ab3f6d
8160034: The `this` value in the `with` is broken by the repetition of a function call
hannesw
parents:
39164
diff
changeset
|
137 |
if (fallBack != null) { |
a9ad93ab3f6d
8160034: The `this` value in the `with` is broken by the repetition of a function call
hannesw
parents:
39164
diff
changeset
|
138 |
find = expression.findProperty(fallBack, true); |
a9ad93ab3f6d
8160034: The `this` value in the `with` is broken by the repetition of a function call
hannesw
parents:
39164
diff
changeset
|
139 |
if (find != null) { |
41842
50202a344d28
8168005: Introduce namespaces for GET, SET Dynalink operations
attila
parents:
41422
diff
changeset
|
140 |
if (NO_SUCH_METHOD_NAME.equals(fallBack)) { |
47437
54a2f246edd8
8165198: Inconsistent values with JavaImporter after accessing undefined variable
hannesw
parents:
47216
diff
changeset
|
141 |
link = expression.noSuchMethod(desc, request).addSwitchPoint(getProtoSwitchPoint(name)); |
41842
50202a344d28
8168005: Introduce namespaces for GET, SET Dynalink operations
attila
parents:
41422
diff
changeset
|
142 |
} else if (NO_SUCH_PROPERTY_NAME.equals(fallBack)) { |
47437
54a2f246edd8
8165198: Inconsistent values with JavaImporter after accessing undefined variable
hannesw
parents:
47216
diff
changeset
|
143 |
link = expression.noSuchProperty(desc, request).addSwitchPoint(getProtoSwitchPoint(name)); |
16147 | 144 |
} |
145 |
} |
|
39900
a9ad93ab3f6d
8160034: The `this` value in the `with` is broken by the repetition of a function call
hannesw
parents:
39164
diff
changeset
|
146 |
} |
16147 | 147 |
|
39900
a9ad93ab3f6d
8160034: The `this` value in the `with` is broken by the repetition of a function call
hannesw
parents:
39164
diff
changeset
|
148 |
if (link != null) { |
41842
50202a344d28
8168005: Introduce namespaces for GET, SET Dynalink operations
attila
parents:
41422
diff
changeset
|
149 |
return fixExpressionCallSite(desc, link); |
16147 | 150 |
} |
151 |
||
152 |
// still not found, may be scope can handle with it's own |
|
153 |
// __noSuchProperty__, __noSuchMethod__ etc. |
|
16195
3f6c0ab2597a
8006766: Array-like access to characters of a string is slow
hannesw
parents:
16173
diff
changeset
|
154 |
link = scope.lookup(desc, request); |
16147 | 155 |
|
156 |
if (link != null) { |
|
23084
6c5c02d1023a
8035948: Redesign property listeners for shared classes
hannesw
parents:
20933
diff
changeset
|
157 |
return fixScopeCallSite(link, name, null); |
16147 | 158 |
} |
159 |
||
160 |
return null; |
|
161 |
} |
|
162 |
||
16264
e0c3c97cd93e
8006984: Introducing local into a function inside with statement confuses its scope
attila
parents:
16234
diff
changeset
|
163 |
/** |
e0c3c97cd93e
8006984: Introducing local into a function inside with statement confuses its scope
attila
parents:
16234
diff
changeset
|
164 |
* Overridden to try to find the property first in the expression object (and its prototypes), and only then in this |
e0c3c97cd93e
8006984: Introducing local into a function inside with statement confuses its scope
attila
parents:
16234
diff
changeset
|
165 |
* object (and its prototypes). |
e0c3c97cd93e
8006984: Introducing local into a function inside with statement confuses its scope
attila
parents:
16234
diff
changeset
|
166 |
* |
e0c3c97cd93e
8006984: Introducing local into a function inside with statement confuses its scope
attila
parents:
16234
diff
changeset
|
167 |
* @param key Property key. |
e0c3c97cd93e
8006984: Introducing local into a function inside with statement confuses its scope
attila
parents:
16234
diff
changeset
|
168 |
* @param deep Whether the search should look up proto chain. |
39164
d40cf0f38270
8159977: typeof operator does not see lexical bindings declared in other scripts
hannesw
parents:
34447
diff
changeset
|
169 |
* @param isScope true if is this a scope access |
16264
e0c3c97cd93e
8006984: Introducing local into a function inside with statement confuses its scope
attila
parents:
16234
diff
changeset
|
170 |
* @param start the object on which the lookup was originally initiated |
e0c3c97cd93e
8006984: Introducing local into a function inside with statement confuses its scope
attila
parents:
16234
diff
changeset
|
171 |
* @return FindPropertyData or null if not found. |
e0c3c97cd93e
8006984: Introducing local into a function inside with statement confuses its scope
attila
parents:
16234
diff
changeset
|
172 |
*/ |
e0c3c97cd93e
8006984: Introducing local into a function inside with statement confuses its scope
attila
parents:
16234
diff
changeset
|
173 |
@Override |
41422 | 174 |
protected FindProperty findProperty(final Object key, final boolean deep, final boolean isScope, final ScriptObject start) { |
26765
97501edd2979
8047764: Indexed or polymorphic set on global affects Object.prototype
hannesw
parents:
26068
diff
changeset
|
175 |
// We call findProperty on 'expression' with 'expression' itself as start parameter. |
97501edd2979
8047764: Indexed or polymorphic set on global affects Object.prototype
hannesw
parents:
26068
diff
changeset
|
176 |
// This way in ScriptObject.setObject we can tell the property is from a 'with' expression |
97501edd2979
8047764: Indexed or polymorphic set on global affects Object.prototype
hannesw
parents:
26068
diff
changeset
|
177 |
// (as opposed from another non-scope object in the proto chain such as Object.prototype). |
39164
d40cf0f38270
8159977: typeof operator does not see lexical bindings declared in other scripts
hannesw
parents:
34447
diff
changeset
|
178 |
final FindProperty exprProperty = expression.findProperty(key, true, false, expression); |
19884
1bacbaa1bfc7
8024180: Incorrect handling of expression and parent scope in 'with' statements
sundar
parents:
19621
diff
changeset
|
179 |
if (exprProperty != null) { |
39900
a9ad93ab3f6d
8160034: The `this` value in the `with` is broken by the repetition of a function call
hannesw
parents:
39164
diff
changeset
|
180 |
return exprProperty; |
16264
e0c3c97cd93e
8006984: Introducing local into a function inside with statement confuses its scope
attila
parents:
16234
diff
changeset
|
181 |
} |
39164
d40cf0f38270
8159977: typeof operator does not see lexical bindings declared in other scripts
hannesw
parents:
34447
diff
changeset
|
182 |
return super.findProperty(key, deep, isScope, start); |
16264
e0c3c97cd93e
8006984: Introducing local into a function inside with statement confuses its scope
attila
parents:
16234
diff
changeset
|
183 |
} |
e0c3c97cd93e
8006984: Introducing local into a function inside with statement confuses its scope
attila
parents:
16234
diff
changeset
|
184 |
|
16147 | 185 |
@Override |
33690 | 186 |
protected Object invokeNoSuchProperty(final Object key, final boolean isScope, final int programPoint) { |
33330
35531ae624ef
8139304: Remove elaborate call site descriptor class hierarchy and factory for them. Remove AutoDiscovery, DefaultPrelinkFilter, and BottomGuardingDynamicLinker as they can be inlined into DynamicLinkerFactory. Remove CallerSensitiveDetector as it can be inlined into AbstractJavaLinker. Make ClassMap non-public.
attila
parents:
32695
diff
changeset
|
187 |
final FindProperty find = expression.findProperty(NO_SUCH_PROPERTY_NAME, true); |
27097
423a434620b4
8060101: AssertionError: __noSuchProperty__ placeholder called from NativeJavaImporter
sundar
parents:
26765
diff
changeset
|
188 |
if (find != null) { |
423a434620b4
8060101: AssertionError: __noSuchProperty__ placeholder called from NativeJavaImporter
sundar
parents:
26765
diff
changeset
|
189 |
final Object func = find.getObjectValue(); |
423a434620b4
8060101: AssertionError: __noSuchProperty__ placeholder called from NativeJavaImporter
sundar
parents:
26765
diff
changeset
|
190 |
if (func instanceof ScriptFunction) { |
32694
da2f35ab2ea6
8136544: Call site switching to megamorphic causes incorrect property read
sundar
parents:
32527
diff
changeset
|
191 |
final ScriptFunction sfunc = (ScriptFunction)func; |
da2f35ab2ea6
8136544: Call site switching to megamorphic causes incorrect property read
sundar
parents:
32527
diff
changeset
|
192 |
final Object self = isScope && sfunc.isStrict()? UNDEFINED : expression; |
33690 | 193 |
return ScriptRuntime.apply(sfunc, self, key); |
27097
423a434620b4
8060101: AssertionError: __noSuchProperty__ placeholder called from NativeJavaImporter
sundar
parents:
26765
diff
changeset
|
194 |
} |
423a434620b4
8060101: AssertionError: __noSuchProperty__ placeholder called from NativeJavaImporter
sundar
parents:
26765
diff
changeset
|
195 |
} |
423a434620b4
8060101: AssertionError: __noSuchProperty__ placeholder called from NativeJavaImporter
sundar
parents:
26765
diff
changeset
|
196 |
|
33690 | 197 |
return getProto().invokeNoSuchProperty(key, isScope, programPoint); |
27097
423a434620b4
8060101: AssertionError: __noSuchProperty__ placeholder called from NativeJavaImporter
sundar
parents:
26765
diff
changeset
|
198 |
} |
423a434620b4
8060101: AssertionError: __noSuchProperty__ placeholder called from NativeJavaImporter
sundar
parents:
26765
diff
changeset
|
199 |
|
423a434620b4
8060101: AssertionError: __noSuchProperty__ placeholder called from NativeJavaImporter
sundar
parents:
26765
diff
changeset
|
200 |
@Override |
16147 | 201 |
public void setSplitState(final int state) { |
31194
f00cb8259826
8098546: eval within a 'with' leaks definitions into global scope
hannesw
parents:
29756
diff
changeset
|
202 |
((Scope) getNonWithParent()).setSplitState(state); |
16147 | 203 |
} |
204 |
||
205 |
@Override |
|
206 |
public int getSplitState() { |
|
31194
f00cb8259826
8098546: eval within a 'with' leaks definitions into global scope
hannesw
parents:
29756
diff
changeset
|
207 |
return ((Scope) getNonWithParent()).getSplitState(); |
f00cb8259826
8098546: eval within a 'with' leaks definitions into global scope
hannesw
parents:
29756
diff
changeset
|
208 |
} |
f00cb8259826
8098546: eval within a 'with' leaks definitions into global scope
hannesw
parents:
29756
diff
changeset
|
209 |
|
f00cb8259826
8098546: eval within a 'with' leaks definitions into global scope
hannesw
parents:
29756
diff
changeset
|
210 |
@Override |
f00cb8259826
8098546: eval within a 'with' leaks definitions into global scope
hannesw
parents:
29756
diff
changeset
|
211 |
public void addBoundProperties(final ScriptObject source, final Property[] properties) { |
f00cb8259826
8098546: eval within a 'with' leaks definitions into global scope
hannesw
parents:
29756
diff
changeset
|
212 |
// Declared variables in nested eval go to first normal (non-with) parent scope. |
f00cb8259826
8098546: eval within a 'with' leaks definitions into global scope
hannesw
parents:
29756
diff
changeset
|
213 |
getNonWithParent().addBoundProperties(source, properties); |
16147 | 214 |
} |
215 |
||
216 |
/** |
|
217 |
* Get first parent scope that is not an instance of WithObject. |
|
218 |
*/ |
|
31194
f00cb8259826
8098546: eval within a 'with' leaks definitions into global scope
hannesw
parents:
29756
diff
changeset
|
219 |
private ScriptObject getNonWithParent() { |
f00cb8259826
8098546: eval within a 'with' leaks definitions into global scope
hannesw
parents:
29756
diff
changeset
|
220 |
ScriptObject proto = getProto(); |
16147 | 221 |
|
222 |
while (proto != null && proto instanceof WithObject) { |
|
31194
f00cb8259826
8098546: eval within a 'with' leaks definitions into global scope
hannesw
parents:
29756
diff
changeset
|
223 |
proto = proto.getProto(); |
16147 | 224 |
} |
225 |
||
31194
f00cb8259826
8098546: eval within a 'with' leaks definitions into global scope
hannesw
parents:
29756
diff
changeset
|
226 |
return proto; |
16147 | 227 |
} |
228 |
||
17236
75779a53c6a9
8012919: findMegaMorphicSetMethod should not cast result type
jlaskey
parents:
17234
diff
changeset
|
229 |
private static GuardedInvocation fixReceiverType(final GuardedInvocation link, final MethodHandle filter) { |
75779a53c6a9
8012919: findMegaMorphicSetMethod should not cast result type
jlaskey
parents:
17234
diff
changeset
|
230 |
// The receiver may be an Object or a ScriptObject. |
75779a53c6a9
8012919: findMegaMorphicSetMethod should not cast result type
jlaskey
parents:
17234
diff
changeset
|
231 |
final MethodType invType = link.getInvocation().type(); |
75779a53c6a9
8012919: findMegaMorphicSetMethod should not cast result type
jlaskey
parents:
17234
diff
changeset
|
232 |
final MethodType newInvType = invType.changeParameterType(0, filter.type().returnType()); |
75779a53c6a9
8012919: findMegaMorphicSetMethod should not cast result type
jlaskey
parents:
17234
diff
changeset
|
233 |
return link.asType(newInvType); |
75779a53c6a9
8012919: findMegaMorphicSetMethod should not cast result type
jlaskey
parents:
17234
diff
changeset
|
234 |
} |
75779a53c6a9
8012919: findMegaMorphicSetMethod should not cast result type
jlaskey
parents:
17234
diff
changeset
|
235 |
|
41842
50202a344d28
8168005: Introduce namespaces for GET, SET Dynalink operations
attila
parents:
41422
diff
changeset
|
236 |
private static GuardedInvocation fixExpressionCallSite(final CallSiteDescriptor desc, final GuardedInvocation link) { |
16147 | 237 |
// If it's not a getMethod, just add an expression filter that converts WithObject in "this" position to its |
238 |
// expression. |
|
41842
50202a344d28
8168005: Introduce namespaces for GET, SET Dynalink operations
attila
parents:
41422
diff
changeset
|
239 |
if (NashornCallSiteDescriptor.getBaseOperation(desc) != StandardOperation.GET || !NashornCallSiteDescriptor.isMethodFirstOperation(desc)) { |
17236
75779a53c6a9
8012919: findMegaMorphicSetMethod should not cast result type
jlaskey
parents:
17234
diff
changeset
|
240 |
return fixReceiverType(link, WITHEXPRESSIONFILTER).filterArguments(0, WITHEXPRESSIONFILTER); |
16147 | 241 |
} |
242 |
||
24720 | 243 |
final MethodHandle linkInvocation = link.getInvocation(); |
244 |
final MethodType linkType = linkInvocation.type(); |
|
245 |
final boolean linkReturnsFunction = ScriptFunction.class.isAssignableFrom(linkType.returnType()); |
|
24719 | 246 |
|
16147 | 247 |
return link.replaceMethods( |
248 |
// Make sure getMethod will bind the script functions it receives to WithObject.expression |
|
24720 | 249 |
MH.foldArguments( |
250 |
linkReturnsFunction ? |
|
251 |
BIND_TO_EXPRESSION_FN : |
|
252 |
BIND_TO_EXPRESSION_OBJ, |
|
253 |
filterReceiver( |
|
254 |
linkInvocation.asType( |
|
255 |
linkType.changeReturnType( |
|
256 |
linkReturnsFunction ? |
|
257 |
ScriptFunction.class : |
|
258 |
Object.class). |
|
259 |
changeParameterType( |
|
260 |
0, |
|
24727 | 261 |
Object.class)), |
24720 | 262 |
WITHEXPRESSIONFILTER)), |
263 |
filterGuardReceiver(link, WITHEXPRESSIONFILTER)); |
|
264 |
// No clever things for the guard -- it is still identically filtered. |
|
265 |
||
16147 | 266 |
} |
267 |
||
23084
6c5c02d1023a
8035948: Redesign property listeners for shared classes
hannesw
parents:
20933
diff
changeset
|
268 |
private GuardedInvocation fixScopeCallSite(final GuardedInvocation link, final String name, final ScriptObject owner) { |
24733
1e825be55fd1
8027043: Turn global accesses into MethodHandle.constant, with one chance of reassignment, e.g. x = value occuring once in the global scope is ok, twice is not.
lagergren
parents:
24727
diff
changeset
|
269 |
final GuardedInvocation newLink = fixReceiverType(link, WITHSCOPEFILTER); |
1e825be55fd1
8027043: Turn global accesses into MethodHandle.constant, with one chance of reassignment, e.g. x = value occuring once in the global scope is ok, twice is not.
lagergren
parents:
24727
diff
changeset
|
270 |
final MethodHandle expressionGuard = expressionGuard(name, owner); |
39900
a9ad93ab3f6d
8160034: The `this` value in the `with` is broken by the repetition of a function call
hannesw
parents:
39164
diff
changeset
|
271 |
final MethodHandle filteredGuard = filterGuardReceiver(newLink, WITHSCOPEFILTER); |
24733
1e825be55fd1
8027043: Turn global accesses into MethodHandle.constant, with one chance of reassignment, e.g. x = value occuring once in the global scope is ok, twice is not.
lagergren
parents:
24727
diff
changeset
|
272 |
return link.replaceMethods( |
1e825be55fd1
8027043: Turn global accesses into MethodHandle.constant, with one chance of reassignment, e.g. x = value occuring once in the global scope is ok, twice is not.
lagergren
parents:
24727
diff
changeset
|
273 |
filterReceiver( |
1e825be55fd1
8027043: Turn global accesses into MethodHandle.constant, with one chance of reassignment, e.g. x = value occuring once in the global scope is ok, twice is not.
lagergren
parents:
24727
diff
changeset
|
274 |
newLink.getInvocation(), |
1e825be55fd1
8027043: Turn global accesses into MethodHandle.constant, with one chance of reassignment, e.g. x = value occuring once in the global scope is ok, twice is not.
lagergren
parents:
24727
diff
changeset
|
275 |
WITHSCOPEFILTER), |
1e825be55fd1
8027043: Turn global accesses into MethodHandle.constant, with one chance of reassignment, e.g. x = value occuring once in the global scope is ok, twice is not.
lagergren
parents:
24727
diff
changeset
|
276 |
NashornGuards.combineGuards( |
1e825be55fd1
8027043: Turn global accesses into MethodHandle.constant, with one chance of reassignment, e.g. x = value occuring once in the global scope is ok, twice is not.
lagergren
parents:
24727
diff
changeset
|
277 |
expressionGuard, |
39900
a9ad93ab3f6d
8160034: The `this` value in the `with` is broken by the repetition of a function call
hannesw
parents:
39164
diff
changeset
|
278 |
filteredGuard)); |
16147 | 279 |
} |
280 |
||
24719 | 281 |
private static MethodHandle filterGuardReceiver(final GuardedInvocation link, final MethodHandle receiverFilter) { |
16147 | 282 |
final MethodHandle test = link.getGuard(); |
24720 | 283 |
if (test == null) { |
284 |
return null; |
|
285 |
} |
|
286 |
||
287 |
final Class<?> receiverType = test.type().parameterType(0); |
|
288 |
final MethodHandle filter = MH.asType(receiverFilter, |
|
289 |
receiverFilter.type().changeParameterType(0, receiverType). |
|
290 |
changeReturnType(receiverType)); |
|
291 |
||
292 |
return filterReceiver(test, filter); |
|
16147 | 293 |
} |
294 |
||
24719 | 295 |
private static MethodHandle filterReceiver(final MethodHandle mh, final MethodHandle receiverFilter) { |
24720 | 296 |
//With expression filter == receiverFilter, i.e. receiver is cast to withobject and its expression returned |
24727 | 297 |
return MH.filterArguments(mh, 0, receiverFilter.asType(receiverFilter.type().changeReturnType(mh.type().parameterType(0)))); |
16147 | 298 |
} |
299 |
||
300 |
/** |
|
301 |
* Drops the WithObject wrapper from the expression. |
|
302 |
* @param receiver WithObject wrapper. |
|
303 |
* @return The with expression. |
|
304 |
*/ |
|
305 |
public static Object withFilterExpression(final Object receiver) { |
|
306 |
return ((WithObject)receiver).expression; |
|
307 |
} |
|
308 |
||
309 |
@SuppressWarnings("unused") |
|
310 |
private static Object bindToExpression(final Object fn, final Object receiver) { |
|
25247
c0f911459863
8046013: TypeError: Cannot apply "with" to non script object
sundar
parents:
24733
diff
changeset
|
311 |
if (fn instanceof ScriptFunction) { |
c0f911459863
8046013: TypeError: Cannot apply "with" to non script object
sundar
parents:
24733
diff
changeset
|
312 |
return bindToExpression((ScriptFunction) fn, receiver); |
c0f911459863
8046013: TypeError: Cannot apply "with" to non script object
sundar
parents:
24733
diff
changeset
|
313 |
} else if (fn instanceof ScriptObjectMirror) { |
c0f911459863
8046013: TypeError: Cannot apply "with" to non script object
sundar
parents:
24733
diff
changeset
|
314 |
final ScriptObjectMirror mirror = (ScriptObjectMirror)fn; |
c0f911459863
8046013: TypeError: Cannot apply "with" to non script object
sundar
parents:
24733
diff
changeset
|
315 |
if (mirror.isFunction()) { |
c0f911459863
8046013: TypeError: Cannot apply "with" to non script object
sundar
parents:
24733
diff
changeset
|
316 |
// We need to make sure correct 'this' is used for calls with Ident call |
c0f911459863
8046013: TypeError: Cannot apply "with" to non script object
sundar
parents:
24733
diff
changeset
|
317 |
// expressions. We do so here using an AbstractJSObject instance. |
c0f911459863
8046013: TypeError: Cannot apply "with" to non script object
sundar
parents:
24733
diff
changeset
|
318 |
return new AbstractJSObject() { |
25821
fbb51e67d2a7
8048869: Reduce compile time by about 5% by removing the Class.casts from the AST nodes
lagergren
parents:
25247
diff
changeset
|
319 |
@Override |
25247
c0f911459863
8046013: TypeError: Cannot apply "with" to non script object
sundar
parents:
24733
diff
changeset
|
320 |
public Object call(final Object thiz, final Object... args) { |
c0f911459863
8046013: TypeError: Cannot apply "with" to non script object
sundar
parents:
24733
diff
changeset
|
321 |
return mirror.call(withFilterExpression(receiver), args); |
c0f911459863
8046013: TypeError: Cannot apply "with" to non script object
sundar
parents:
24733
diff
changeset
|
322 |
} |
c0f911459863
8046013: TypeError: Cannot apply "with" to non script object
sundar
parents:
24733
diff
changeset
|
323 |
}; |
c0f911459863
8046013: TypeError: Cannot apply "with" to non script object
sundar
parents:
24733
diff
changeset
|
324 |
} |
c0f911459863
8046013: TypeError: Cannot apply "with" to non script object
sundar
parents:
24733
diff
changeset
|
325 |
} |
c0f911459863
8046013: TypeError: Cannot apply "with" to non script object
sundar
parents:
24733
diff
changeset
|
326 |
|
c0f911459863
8046013: TypeError: Cannot apply "with" to non script object
sundar
parents:
24733
diff
changeset
|
327 |
return fn; |
16780
f23743ec1a93
8011555: Invalid class name in with block with JavaImporter causes MH type mismatch
attila
parents:
16277
diff
changeset
|
328 |
} |
f23743ec1a93
8011555: Invalid class name in with block with JavaImporter causes MH type mismatch
attila
parents:
16277
diff
changeset
|
329 |
|
f23743ec1a93
8011555: Invalid class name in with block with JavaImporter causes MH type mismatch
attila
parents:
16277
diff
changeset
|
330 |
private static Object bindToExpression(final ScriptFunction fn, final Object receiver) { |
32527
b105632002c5
8027137: Merge ScriptFunction and ScriptFunctionImpl
sundar
parents:
31199
diff
changeset
|
331 |
return fn.createBound(withFilterExpression(receiver), ScriptRuntime.EMPTY_ARRAY); |
16147 | 332 |
} |
333 |
||
23084
6c5c02d1023a
8035948: Redesign property listeners for shared classes
hannesw
parents:
20933
diff
changeset
|
334 |
private MethodHandle expressionGuard(final String name, final ScriptObject owner) { |
19884
1bacbaa1bfc7
8024180: Incorrect handling of expression and parent scope in 'with' statements
sundar
parents:
19621
diff
changeset
|
335 |
final PropertyMap map = expression.getMap(); |
32695
9b708b92c695
8134609: Allow constructors with same prototoype map to share the allocator map
hannesw
parents:
32694
diff
changeset
|
336 |
final SwitchPoint[] sp = expression.getProtoSwitchPoints(name, owner); |
19884
1bacbaa1bfc7
8024180: Incorrect handling of expression and parent scope in 'with' statements
sundar
parents:
19621
diff
changeset
|
337 |
return MH.insertArguments(WITHEXPRESSIONGUARD, 1, map, sp); |
1bacbaa1bfc7
8024180: Incorrect handling of expression and parent scope in 'with' statements
sundar
parents:
19621
diff
changeset
|
338 |
} |
1bacbaa1bfc7
8024180: Incorrect handling of expression and parent scope in 'with' statements
sundar
parents:
19621
diff
changeset
|
339 |
|
1bacbaa1bfc7
8024180: Incorrect handling of expression and parent scope in 'with' statements
sundar
parents:
19621
diff
changeset
|
340 |
@SuppressWarnings("unused") |
32695
9b708b92c695
8134609: Allow constructors with same prototoype map to share the allocator map
hannesw
parents:
32694
diff
changeset
|
341 |
private static boolean withExpressionGuard(final Object receiver, final PropertyMap map, final SwitchPoint[] sp) { |
9b708b92c695
8134609: Allow constructors with same prototoype map to share the allocator map
hannesw
parents:
32694
diff
changeset
|
342 |
return ((WithObject)receiver).expression.getMap() == map && !hasBeenInvalidated(sp); |
9b708b92c695
8134609: Allow constructors with same prototoype map to share the allocator map
hannesw
parents:
32694
diff
changeset
|
343 |
} |
9b708b92c695
8134609: Allow constructors with same prototoype map to share the allocator map
hannesw
parents:
32694
diff
changeset
|
344 |
|
9b708b92c695
8134609: Allow constructors with same prototoype map to share the allocator map
hannesw
parents:
32694
diff
changeset
|
345 |
private static boolean hasBeenInvalidated(final SwitchPoint[] switchPoints) { |
9b708b92c695
8134609: Allow constructors with same prototoype map to share the allocator map
hannesw
parents:
32694
diff
changeset
|
346 |
if (switchPoints != null) { |
9b708b92c695
8134609: Allow constructors with same prototoype map to share the allocator map
hannesw
parents:
32694
diff
changeset
|
347 |
for (final SwitchPoint switchPoint : switchPoints) { |
9b708b92c695
8134609: Allow constructors with same prototoype map to share the allocator map
hannesw
parents:
32694
diff
changeset
|
348 |
if (switchPoint.hasBeenInvalidated()) { |
9b708b92c695
8134609: Allow constructors with same prototoype map to share the allocator map
hannesw
parents:
32694
diff
changeset
|
349 |
return true; |
9b708b92c695
8134609: Allow constructors with same prototoype map to share the allocator map
hannesw
parents:
32694
diff
changeset
|
350 |
} |
9b708b92c695
8134609: Allow constructors with same prototoype map to share the allocator map
hannesw
parents:
32694
diff
changeset
|
351 |
} |
9b708b92c695
8134609: Allow constructors with same prototoype map to share the allocator map
hannesw
parents:
32694
diff
changeset
|
352 |
} |
9b708b92c695
8134609: Allow constructors with same prototoype map to share the allocator map
hannesw
parents:
32694
diff
changeset
|
353 |
return false; |
19884
1bacbaa1bfc7
8024180: Incorrect handling of expression and parent scope in 'with' statements
sundar
parents:
19621
diff
changeset
|
354 |
} |
1bacbaa1bfc7
8024180: Incorrect handling of expression and parent scope in 'with' statements
sundar
parents:
19621
diff
changeset
|
355 |
|
16147 | 356 |
/** |
357 |
* Drops the WithObject wrapper from the scope. |
|
358 |
* @param receiver WithObject wrapper. |
|
359 |
* @return The with scope. |
|
360 |
*/ |
|
361 |
public static Object withFilterScope(final Object receiver) { |
|
362 |
return ((WithObject)receiver).getProto(); |
|
363 |
} |
|
364 |
||
365 |
/** |
|
366 |
* Get the with expression for this {@code WithObject} |
|
367 |
* @return the with expression |
|
368 |
*/ |
|
19884
1bacbaa1bfc7
8024180: Incorrect handling of expression and parent scope in 'with' statements
sundar
parents:
19621
diff
changeset
|
369 |
public ScriptObject getExpression() { |
16147 | 370 |
return expression; |
371 |
} |
|
372 |
||
373 |
private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) { |
|
374 |
return MH.findStatic(MethodHandles.lookup(), WithObject.class, name, MH.type(rtype, types)); |
|
375 |
} |
|
376 |
} |