test/script/trusted/JDK-8006529.js

Fri, 06 Sep 2019 03:21:30 +0100

author
andrew
date
Fri, 06 Sep 2019 03:21:30 +0100
changeset 2516
ad8af81cc28b
parent 1544
689cb2dfe091
child 1959
61ffdd1b89f2
permissions
-rw-r--r--

Added tag jdk8u242-b00 for changeset 8a951fd037e2

attila@62 1 /*
attila@62 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
attila@62 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
attila@962 4 *
attila@62 5 * This code is free software; you can redistribute it and/or modify it
attila@62 6 * under the terms of the GNU General Public License version 2 only, as
attila@62 7 * published by the Free Software Foundation.
attila@962 8 *
attila@62 9 * This code is distributed in the hope that it will be useful, but WITHOUT
attila@62 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
attila@62 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
attila@62 12 * version 2 for more details (a copy is included in the LICENSE file that
attila@62 13 * accompanied this code).
attila@962 14 *
attila@62 15 * You should have received a copy of the GNU General Public License version
attila@62 16 * 2 along with this work; if not, write to the Free Software Foundation,
attila@62 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
attila@962 18 *
attila@62 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
attila@62 20 * or visit www.oracle.com if you need additional information or have any
attila@62 21 * questions.
attila@62 22 */
attila@62 23
attila@62 24 /**
attila@62 25 * JDK-8006529 : Methods should not always get callee parameter, and they
attila@62 26 * should not be too eager in creation of scopes.
attila@62 27 *
attila@62 28 * @test
attila@62 29 * @run
attila@62 30 */
attila@62 31
sundar@82 32 /*
sundar@82 33 * This test script depends on nashorn Compiler internals. It uses reflection
sundar@82 34 * to get access to private field and many public methods of Compiler and
sundar@82 35 * FunctionNode classes. Note that this is trusted code and access to such
attila@962 36 * internal package classes and methods is okay. But, if you modify any
sundar@82 37 * Compiler or FunctionNode class, you may have to revisit this script.
sundar@82 38 * We cannot use direct Java class (via dynalink bean linker) to Compiler
sundar@82 39 * and FunctionNode because of package-access check and so reflective calls.
sundar@82 40 */
sundar@82 41
attila@963 42 var forName = java.lang.Class["forName(String)"];
sundar@468 43 var Parser = forName("jdk.nashorn.internal.parser.Parser").static
sundar@468 44 var Compiler = forName("jdk.nashorn.internal.codegen.Compiler").static
attila@963 45 var CompilationPhases = forName("jdk.nashorn.internal.codegen.Compiler$CompilationPhases").static;
sundar@468 46 var Context = forName("jdk.nashorn.internal.runtime.Context").static
attila@963 47 var CodeInstaller = forName("jdk.nashorn.internal.runtime.CodeInstaller").static
sundar@468 48 var ScriptEnvironment = forName("jdk.nashorn.internal.runtime.ScriptEnvironment").static
sundar@468 49 var Source = forName("jdk.nashorn.internal.runtime.Source").static
sundar@468 50 var FunctionNode = forName("jdk.nashorn.internal.ir.FunctionNode").static
sundar@468 51 var Block = forName("jdk.nashorn.internal.ir.Block").static
sundar@468 52 var VarNode = forName("jdk.nashorn.internal.ir.VarNode").static
sundar@468 53 var ExpressionStatement = forName("jdk.nashorn.internal.ir.ExpressionStatement").static
sundar@468 54 var UnaryNode = forName("jdk.nashorn.internal.ir.UnaryNode").static
sundar@468 55 var BinaryNode = forName("jdk.nashorn.internal.ir.BinaryNode").static
sundar@468 56 var ThrowErrorManager = forName("jdk.nashorn.internal.runtime.Context$ThrowErrorManager").static
sundar@468 57 var ErrorManager = forName("jdk.nashorn.internal.runtime.ErrorManager").static
sundar@468 58 var Debug = forName("jdk.nashorn.internal.runtime.Debug").static
attila@963 59 var String = forName("java.lang.String").static
attila@963 60 var boolean = Java.type("boolean");
attila@422 61
lagergren@89 62 var parseMethod = Parser.class.getMethod("parse");
attila@963 63 var compileMethod = Compiler.class.getMethod("compile", FunctionNode.class, CompilationPhases.class);
attila@422 64 var getBodyMethod = FunctionNode.class.getMethod("getBody");
attila@422 65 var getStatementsMethod = Block.class.getMethod("getStatements");
attila@422 66 var getInitMethod = VarNode.class.getMethod("getInit");
attila@430 67 var getExpressionMethod = ExpressionStatement.class.getMethod("getExpression")
attila@963 68 var rhsMethod = UnaryNode.class.getMethod("getExpression")
attila@422 69 var lhsMethod = BinaryNode.class.getMethod("lhs")
attila@422 70 var binaryRhsMethod = BinaryNode.class.getMethod("rhs")
attila@422 71 var debugIdMethod = Debug.class.getMethod("id", java.lang.Object.class)
attila@963 72 var compilePhases = CompilationPhases.class.getField("COMPILE_UPTO_BYTECODE").get(null);
sundar@82 73
sundar@82 74 // These are method names of methods in FunctionNode class
attila@963 75 var allAssertionList = ['isVarArg', 'needsParentScope', 'needsCallee', 'hasScopeBlock', 'usesSelfSymbol', 'isSplit', 'hasEval', 'allVarsInScope', 'isStrict']
sundar@82 76
sundar@82 77 // corresponding Method objects of FunctionNode class
sundar@82 78 var functionNodeMethods = {};
sundar@82 79 // initialize FunctionNode methods
sundar@82 80 (function() {
sundar@82 81 for (var f in allAssertionList) {
sundar@82 82 var method = allAssertionList[f];
sundar@82 83 functionNodeMethods[method] = FunctionNode.class.getMethod(method);
sundar@82 84 }
sundar@82 85 })();
sundar@82 86
attila@422 87 // returns functionNode.getBody().getStatements().get(0)
attila@422 88 function getFirstFunction(functionNode) {
attila@422 89 var f = findFunction(getBodyMethod.invoke(functionNode))
attila@422 90 if (f == null) {
attila@422 91 throw new Error();
attila@422 92 }
attila@422 93 return f;
sundar@82 94 }
sundar@82 95
attila@422 96 function findFunction(node) {
attila@422 97 if(node instanceof Block) {
attila@422 98 var stmts = getStatementsMethod.invoke(node)
attila@422 99 for(var i = 0; i < stmts.size(); ++i) {
attila@422 100 var retval = findFunction(stmts.get(i))
attila@422 101 if(retval != null) {
attila@422 102 return retval;
attila@422 103 }
attila@422 104 }
attila@422 105 } else if(node instanceof VarNode) {
attila@422 106 return findFunction(getInitMethod.invoke(node))
attila@422 107 } else if(node instanceof UnaryNode) {
attila@422 108 return findFunction(rhsMethod.invoke(node))
attila@422 109 } else if(node instanceof BinaryNode) {
attila@422 110 return findFunction(lhsMethod.invoke(node)) || findFunction(binaryRhsMethod.invoke(node))
attila@962 111 } else if(node instanceof ExpressionStatement) {
attila@962 112 return findFunction(getExpressionMethod.invoke(node))
attila@422 113 } else if(node instanceof FunctionNode) {
attila@422 114 return node
attila@422 115 }
sundar@82 116 }
sundar@82 117
attila@422 118 var getContextMethod = Context.class.getMethod("getContext")
attila@422 119 var getEnvMethod = Context.class.getMethod("getEnv")
attila@422 120
hannesw@845 121 var sourceForMethod = Source.class.getMethod("sourceFor", java.lang.String.class, java.lang.String.class)
attila@464 122 var ParserConstructor = Parser.class.getConstructor(ScriptEnvironment.class, Source.class, ErrorManager.class)
attila@1544 123 var CompilerConstructor = Compiler.class.getMethod("forNoInstallerCompilation", Context.class, Source.class, boolean.class);
attila@464 124
attila@962 125 // compile(script) -- compiles a script specified as a string with its
attila@962 126 // source code, returns a jdk.nashorn.internal.ir.FunctionNode object
attila@62 127 // representing it.
attila@963 128 function compile(source, phases) {
hannesw@845 129 var source = sourceForMethod.invoke(null, "<no name>", source);
attila@422 130
attila@963 131 var ctxt = getContextMethod.invoke(null);
attila@963 132 var env = getEnvMethod.invoke(ctxt);
attila@422 133
attila@465 134 var parser = ParserConstructor.newInstance(env, source, ThrowErrorManager.class.newInstance());
lagergren@89 135 var func = parseMethod.invoke(parser);
lagergren@89 136
attila@1543 137 var compiler = CompilerConstructor.invoke(null, ctxt, source, false);
lagergren@89 138
attila@963 139 return compileMethod.invoke(compiler, func, phases);
sundar@82 140 };
attila@62 141
attila@62 142 var allAssertions = (function() {
attila@62 143 var allAssertions = {}
attila@62 144 for(var assertion in allAssertionList) {
attila@62 145 allAssertions[allAssertionList[assertion]] = true
attila@62 146 }
attila@62 147 return allAssertions;
attila@62 148 })();
attila@62 149
sundar@82 150
attila@62 151 // test(f[, assertions...]) tests whether all the specified assertions on the
attila@62 152 // passed function node are true.
attila@62 153 function test(f) {
attila@62 154 var assertions = {}
attila@62 155 for(var i = 1; i < arguments.length; ++i) {
attila@62 156 var assertion = arguments[i]
attila@62 157 if(!allAssertions[assertion]) {
attila@62 158 throw "Unknown assertion " + assertion + " for " + f;
attila@62 159 }
attila@62 160 assertions[assertion] = true
attila@62 161 }
attila@62 162 for(var assertion in allAssertions) {
attila@62 163 var expectedValue = !!assertions[assertion]
attila@422 164 var actualValue = functionNodeMethods[assertion].invoke(f)
attila@422 165 if(actualValue !== expectedValue) {
attila@422 166 throw "Expected " + assertion + " === " + expectedValue + ", got " + actualValue + " for " + f + ":" + debugIdMethod.invoke(null, f);
attila@62 167 }
attila@62 168 }
attila@62 169 }
attila@62 170
attila@62 171 // testFirstFn(script[, assertions...] tests whether all the specified
attila@62 172 // assertions are true in the first function in the given script; "script"
attila@62 173 // is a string with the source text of the script.
attila@62 174 function testFirstFn(script) {
attila@963 175 arguments[0] = getFirstFunction(compile(script, compilePhases));
attila@963 176 test.apply(null, arguments);
attila@62 177 }
attila@62 178
attila@62 179 // ---------------------------------- ACTUAL TESTS START HERE --------------
attila@62 180
attila@62 181 // The simplest possible functions have no attributes set
attila@62 182 testFirstFn("function f() { }")
attila@62 183 testFirstFn("function f(x) { x }")
attila@62 184
attila@62 185 // A function referencing a global needs parent scope, and it needs callee
attila@62 186 // (because parent scope is passed through callee)
attila@62 187 testFirstFn("function f() { x }", 'needsCallee', 'needsParentScope')
attila@62 188
attila@62 189 // A function referencing "arguments" will have to be vararg. It also needs
attila@62 190 // the callee, as it needs to fill out "arguments.callee".
attila@62 191 testFirstFn("function f() { arguments }", 'needsCallee', 'isVarArg')
attila@62 192
attila@62 193 // A function referencing "arguments" will have to be vararg. If it is
attila@62 194 // strict, it will not have to have a callee, though.
attila@422 195 testFirstFn("function f() {'use strict'; arguments }", 'isVarArg', 'isStrict')
attila@62 196
attila@62 197 // A function defining "arguments" as a parameter will not be vararg.
attila@62 198 testFirstFn("function f(arguments) { arguments }")
attila@62 199
attila@62 200 // A function defining "arguments" as a nested function will not be vararg.
attila@62 201 testFirstFn("function f() { function arguments() {}; arguments; }")
attila@62 202
attila@62 203 // A function defining "arguments" as a local variable will be vararg.
attila@62 204 testFirstFn("function f() { var arguments; arguments; }", 'isVarArg', 'needsCallee')
attila@62 205
attila@962 206 // A self-referencing function defined as a statement doesn't need a self
attila@62 207 // symbol, as it'll rather obtain itself from the parent scope.
attila@62 208 testFirstFn("function f() { f() }", 'needsCallee', 'needsParentScope')
attila@62 209
attila@62 210 // A self-referencing function defined as an expression needs a self symbol,
attila@62 211 // as it can't obtain itself from the parent scope.
attila@963 212 testFirstFn("(function f() { f() })", 'needsCallee', 'usesSelfSymbol')
attila@62 213
attila@62 214 // A child function accessing parent's variable triggers the need for scope
attila@62 215 // in parent
attila@422 216 testFirstFn("(function f() { var x; function g() { x } })", 'hasScopeBlock')
attila@62 217
attila@62 218 // A child function accessing parent's parameter triggers the need for scope
attila@62 219 // in parent
attila@422 220 testFirstFn("(function f(x) { function g() { x } })", 'hasScopeBlock')
attila@62 221
attila@62 222 // A child function accessing a global variable triggers the need for parent
attila@62 223 // scope in parent
attila@62 224 testFirstFn("(function f() { function g() { x } })", 'needsParentScope', 'needsCallee')
attila@62 225
attila@962 226 // A child function redefining a local variable from its parent should not
attila@62 227 // affect the parent function in any way
attila@62 228 testFirstFn("(function f() { var x; function g() { var x; x } })")
attila@62 229
attila@422 230 // Using "with" on its own doesn't do much.
attila@422 231 testFirstFn("(function f() { var o; with(o) {} })")
attila@62 232
attila@422 233 // "with" referencing a local variable triggers scoping.
attila@422 234 testFirstFn("(function f() { var x; var y; with(x) { y } })", 'hasScopeBlock')
attila@422 235
attila@422 236 // "with" referencing a non-local variable triggers parent scope.
attila@422 237 testFirstFn("(function f() { var x; with(x) { y } })", 'needsCallee', 'needsParentScope')
attila@62 238
attila@62 239 // Nested function using "with" is pretty much the same as the parent
attila@62 240 // function needing with.
attila@422 241 testFirstFn("(function f() { function g() { var o; with(o) {} } })")
attila@422 242
attila@422 243 // Nested function using "with" referencing a local variable.
attila@422 244 testFirstFn("(function f() { var x; function g() { var o; with(o) { x } } })", 'hasScopeBlock')
attila@422 245
attila@422 246 // Using "eval" triggers pretty much everything. The function even needs to be
attila@422 247 // vararg, 'cause we don't know if eval will be using "arguments".
attila@963 248 testFirstFn("(function f() { eval() })", 'usesSelfSymbol', 'needsParentScope', 'needsCallee', 'hasScopeBlock', 'hasEval', 'isVarArg', 'allVarsInScope')
attila@422 249
attila@62 250 // Nested function using "eval" is almost the same as parent function using
attila@62 251 // eval, but at least the parent doesn't have to be vararg.
attila@963 252 testFirstFn("(function f() { function g() { eval() } })", 'usesSelfSymbol', 'needsParentScope', 'needsCallee', 'hasScopeBlock', 'allVarsInScope')
attila@62 253
attila@62 254 // Function with 250 named parameters is ordinary
attila@62 255 testFirstFn("function f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, p96, p97, p98, p99, p100, p101, p102, p103, p104, p105, p106, p107, p108, p109, p110, p111, p112, p113, p114, p115, p116, p117, p118, p119, p120, p121, p122, p123, p124, p125, p126, p127, p128, p129, p130, p131, p132, p133, p134, p135, p136, p137, p138, p139, p140, p141, p142, p143, p144, p145, p146, p147, p148, p149, p150, p151, p152, p153, p154, p155, p156, p157, p158, p159, p160, p161, p162, p163, p164, p165, p166, p167, p168, p169, p170, p171, p172, p173, p174, p175, p176, p177, p178, p179, p180, p181, p182, p183, p184, p185, p186, p187, p188, p189, p190, p191, p192, p193, p194, p195, p196, p197, p198, p199, p200, p201, p202, p203, p204, p205, p206, p207, p208, p209, p210, p211, p212, p213, p214, p215, p216, p217, p218, p219, p220, p221, p222, p223, p224, p225, p226, p227, p228, p229, p230, p231, p232, p233, p234, p235, p236, p237, p238, p239, p240, p241, p242, p243, p244, p245, p246, p247, p248, p249, p250) { p250 = p249 }")
attila@62 256
attila@62 257 // Function with 251 named parameters is variable arguments
attila@963 258 // NOTE: hasScopeBlock should be optimized away. Implementation of JDK-8038942 should take care of it.
attila@963 259 testFirstFn("function f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, p96, p97, p98, p99, p100, p101, p102, p103, p104, p105, p106, p107, p108, p109, p110, p111, p112, p113, p114, p115, p116, p117, p118, p119, p120, p121, p122, p123, p124, p125, p126, p127, p128, p129, p130, p131, p132, p133, p134, p135, p136, p137, p138, p139, p140, p141, p142, p143, p144, p145, p146, p147, p148, p149, p150, p151, p152, p153, p154, p155, p156, p157, p158, p159, p160, p161, p162, p163, p164, p165, p166, p167, p168, p169, p170, p171, p172, p173, p174, p175, p176, p177, p178, p179, p180, p181, p182, p183, p184, p185, p186, p187, p188, p189, p190, p191, p192, p193, p194, p195, p196, p197, p198, p199, p200, p201, p202, p203, p204, p205, p206, p207, p208, p209, p210, p211, p212, p213, p214, p215, p216, p217, p218, p219, p220, p221, p222, p223, p224, p225, p226, p227, p228, p229, p230, p231, p232, p233, p234, p235, p236, p237, p238, p239, p240, p241, p242, p243, p244, p245, p246, p247, p248, p249, p250, p251) { p250 = p251 }", 'isVarArg', 'hasScopeBlock')

mercurial